#define NDEBUG #include #include #define NR(x) (sizeof(x)/sizeof*(x)) struct rb_element { unsigned i; }; struct rb { unsigned head, length; /**< consume at head. append at tail. */ struct rb_element elements[4]; }; struct rb_element *rb_top(struct rb *rb) { assert(rb != NULL); if(!rb->length) return NULL; return &rb->elements[rb->head]; } #if (__arm__-0) /* may optimize a little better on ARM(didn't check), and if elements[] isn't a power of 2. */ struct rb_element *rb_pop(struct rb *rb) { assert(rb != NULL); if(!rb->length) return NULL; --rb->length; //fprintf(stderr, "Consume slot %d\n", rb->head); if(rb->headelements)-1) return &rb->elements[rb->head++]; rb->head=0; return &rb->elements[NR(rb->elements)-1]; } #else /* optimizes a little better on x86-64 (at -Os). * but if elements[] isn't a power of 2 a division will happen. */ struct rb_element *rb_pop(struct rb *rb) { unsigned curr; assert(rb != NULL); curr=rb->head; if(!rb->length) return NULL; --rb->length, ++rb->head; // fprintf(stderr, "Consume slot %d\n", rb->head); rb->head%=NR(rb->elements); return &rb->elements[curr]; } #endif /** return number of empty slots available. */ unsigned rb_remaining(const struct rb *rb) { assert(rb != NULL); return NR(rb->elements)-rb->length; } int rb_enqueue(struct rb *rb, const struct rb_element *elm) { unsigned tail; assert(rb != NULL); if(rb->length>=NR(rb->elements)) return 0; tail=rb->head+rb->length++; if(tail>NR(rb->elements)) tail-=NR(rb->elements); rb->elements[tail]=*elm; fprintf(stderr, "Place at slot %d\n", tail); return 1; } int main() { /* TEST */ struct rb rb; struct rb_element elm, *tmp; int res; rb.head=rb.length=0; elm.i=100; do { printf("remaining_before=%d ", rb_remaining(&rb)); printf("res=%d ", res=rb_enqueue(&rb, &elm)); printf("remaining_after=%d\n", rb_remaining(&rb)); elm.i++; } while(res); while((tmp=rb_pop(&rb))) { printf("pop %d\n", tmp->i); } return 0; }