#include 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 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()); }