#include #include #include #include typedef struct SEM SEM; void P(SEM *sem); void V(SEM *sem); typedef struct BNDBUF { size_t size; _Atomic size_t read_index; size_t write_index; SEM *full; SEM *free; int *data; } BNDBUF; int bbGet(BNDBUF *bb) { P(bb->full); size_t pos = atomic_load(&bb->read_index); size_t next_pos; int value; do { // Use modulo-operator when accessing the element, not when writing the // read_index (-> generation counter). size_t index = pos % bb->size; value = bb->data[index]; if (pos < SIZE_MAX) { // No overflow: just increment. next_pos = pos + 1; } else { // pos == SIZE_MAX // Overflow: resume at next valid index (not simply 0, that might be // wrong depending on bb->size). next_pos = index + 1; } } while(atomic_compare_exchange_strong(&bb->read_index, &pos, next_pos) == false); V(bb->free); return value; }