reorganizing repo

git-svn-id: svn://ultimatepp.org/upp/trunk@9206 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2015-11-22 11:23:48 +00:00
parent 7d17505cfe
commit e3e8d627f5
3840 changed files with 0 additions and 1161578 deletions

View file

@ -1,144 +0,0 @@
// Solution to our pre-interview test.
#include <stdlib.h>
#include <stdio.h>
// Macros I can't do without anymore.
#define hope(x) while ( ! (x) ) { onIllegalOperation() ; }
#define require(x) typedef char require[ (x) ? 1 : -1 ] ;
// Error handlers.
#define onOutOfMemory() do{ fprintf( stderr, "Out of memory!\n" ) ; exit( EXIT_FAILURE ) ; } while( 0 )
#define onIllegalOperation() do{ fprintf( stderr, "Illegal Operation!\n" ) ; exit( EXIT_FAILURE ) ; } while( 0 )
// Typedefs.
typedef unsigned char byte ;
typedef unsigned int uint ;
struct Q {
uint first ;
uint last ;
} ;
// Constants.
const uint BLOCK_SIZE = 8 ;
const uint BLOCK_MASK = BLOCK_SIZE - 1 ;
const uint BLOCK_LAST = BLOCK_SIZE - 1 ;
const uint TOTAL_SIZE = 2048 ;
const uint BLOCK_COUNT = TOTAL_SIZE / BLOCK_SIZE ;
// The provided memory, and appropriate aliasing.
//
// Everything is split to 256 8byte blocks.
//
// Blocks 1-255 are used for both queues and data, block 0 for book-keeping of free blocks.
// data[ 0 ] maintains single linked list of free blocks, while
// data[ 1 ] keeps the index of the last block ever allocated.
// Both used and free blocks are linked via their last byte.
//
// Note that array requires alignment to uint on some architectures,
// which is simple to achieve with "aligned" attribute if necessary.
// The alternative would be to use aligned memory within it ourselves.
byte data[ TOTAL_SIZE ] ;
#define queues ((Q *)(data))
require( sizeof( Q ) == BLOCK_SIZE ) ;
// Block management.
static byte allocate_block( void )
{
// Use one of the freed blocks, if possible.
byte block = data[ 0 ] ;
if ( block ) {
data[ 0 ] = data[ block * BLOCK_SIZE + BLOCK_LAST ] ;
return block ;
}
// Otherwise grab new block from the array, if possible.
//
// We can use an arguable trick that it will overflow in case we run out of blocks.
// This may be considered either cool or entirely intorelable, depending on the point of view.
require( BLOCK_COUNT == 256 ) ;
block = ++data[ 1 ] ;
if ( block ) {
return block ;
}
// Well, bad luck.
onOutOfMemory() ;
}
static void free_block( const byte block )
{
hope( block > 0 ) ;
hope( block < BLOCK_COUNT ) ;
data[ block * BLOCK_SIZE + BLOCK_LAST ] = data[ 0 ] ;
data[ 0 ] = block ;
}
// Queue methods themselves, each O(1).
Q * createQ( void )
{
Q * const q = queues + allocate_block() ;
q->first = q->last = allocate_block() * BLOCK_SIZE ;
return q ;
}
void destroyQ( Q * q )
{
hope( q ) ;
data[ q->last | BLOCK_MASK ] = data[ 0 ] ;
data[ 0 ] = q->first / BLOCK_SIZE ;
free_block( q - queues ) ;
}
void enQ( Q * q, byte n )
{
hope( q ) ;
if ( q->last & BLOCK_MASK == BLOCK_LAST ) {
const byte block = allocate_block() ;
data[ q->last ] = block ;
q->last = block * BLOCK_SIZE ;
}
data[ q->last++ ] = n ;
}
byte deQ( Q * q )
{
hope( q ) ;
if ( q->first == q->last ) {
onIllegalOperation() ;
}
if ( q->first & BLOCK_MASK == BLOCK_LAST ) {
const byte block = data[ q->first ] ;
free_block( q->first / BLOCK_SIZE ) ;
q->first = block * BLOCK_SIZE ;
}
return data[ q->first++ ] ;
}
void TestPatrik()
{
Q *q0 = createQ();
for(int i = 0; i < 3000; i++) {
DDUMP(i);
enQ(q0, 0);
}
}

View file

@ -1,158 +0,0 @@
#include <Core/Core.h>
using namespace Upp;
// Note that it is totally MT broken.... (can only be used in single thread)
typedef unsigned char byte;
class Queue {
struct Qitem {
byte next;
byte value[15];
};
static Qitem buffer[128];
static int freelist;
byte head_q;
byte head_i;
byte tail_q;
byte tail_i;
enum { NIL = 255 };
void Nil() { head_q = tail_i = NIL; }
static void Free(int q);
public:
bool IsEmpty() const { return head_q == NIL; }
void Put(byte value);
byte Get();
Queue();
~Queue();
};
Queue::Qitem Queue::buffer[128];
int Queue::freelist = -1;
void Queue::Free(int q)
{
buffer[q].next = freelist;
freelist = q;
}
Queue::Queue()
{
if(freelist < 0) {
buffer[0].next = NIL;
for(int i = 1; i < 128; i++)
buffer[i].next = i - 1;
freelist = 127;
}
Nil();
}
Queue::~Queue()
{
int q = head_q;
while(q != NIL) {
int w = q;
q = buffer[q].next;
Free(w);
}
}
void Queue::Put(byte value)
{
Qitem *m;
if(tail_i >= 15) {
if(freelist == NIL)
Panic("Out of memory");
int q = freelist;
freelist = buffer[freelist].next;
if(IsEmpty()) {
head_q = q;
head_i = 0;
}
else
buffer[tail_q].next = q;
tail_q = q;
tail_i = 0;
m = &buffer[q];
m->next = NIL;
}
else
m = &buffer[tail_q];
m->value[tail_i++] = value;
}
byte Queue::Get()
{
ASSERT(!IsEmpty());
if(head_i >= 15) {
int q = head_q;
head_q = buffer[head_q].next;
head_i = 0;
Free(q);
}
int val = buffer[head_q].value[head_i++];
if(head_q == tail_q && head_i == tail_i) {
Free(head_q);
Nil();
}
return val;
}
CONSOLE_APP_MAIN
{
{
BiVector<byte> ref[16];
Queue q[16];
int total = 0;
for(int i = 0; i < 100000000; i++) {
if(i % 1000000 == 0)
Cout() << i << '\n';
int ii = Random() & 15;
if((Random() & 65535) < 32900 && total < 128 * 10) {
total++;
byte v = (byte)Random();
q[ii].Put(v);
ref[ii].AddTail(v);
DDUMP(total);
}
else
if(!q[ii].IsEmpty()) {
total--;
ASSERT(q[ii].Get() == ref[ii].Head());
ref[ii].DropHead();
if(q[ii].IsEmpty())
LOG("Empty!");
}
}
}
{
Queue a, b;
for(int i = 0; i < 500; i++) {
a.Put(i);
for(int j = 0; j < 500; j++)
b.Put(j);
for(int j = 0; j < 500; j++)
ASSERT((byte)j == b.Get());
}
for(int i = 0; i < 500; i++)
ASSERT(a.Get() == (byte)i);
}
Queue a1;
for(int i = 0; i < 128 * 15; i++)
a1.Put(i);
for(int i = 0; i < 128 * 15; i++)
DUMP((int)a1.Get());
for(int i = 0; i < 128 * 15; i++)
a1.Put(i);
for(int i = 0; i < 128 * 15; i++)
DUMP((int)a1.Get());
}

View file

@ -1,10 +0,0 @@
uses
Core;
file
Patrik.cpp,
Queue.cpp;
mainconfig
"" = "";

View file

@ -1,4 +0,0 @@
#ifndef _Queue_icpp_init_stub
#define _Queue_icpp_init_stub
#include "Core/init"
#endif