我有一個場景,我可以有多個生產者,但環形緩衝區的單個消費者。這裏是源代碼:等待免費環形緩衝區
typedef struct ring_buffer_t {
uint8_t *data;
uint32_t element_size;
uint32_t element_count;
uint32_t head;
uint32_t tail;
uint32_t mask;
} ring_buffer;
uint32_t ring_buffer_put(ring_buffer *buf, void *data_element) {
int i;
uint32_t status = 0;
uint8_t *buf_pointer;
uint8_t *element = (uint8_t *) data_element;
if (buf && data_element) {
buf_pointer = &buf->data[(buf->head & buf->mask) * buf->element_size];
for (i = 0; i < buf->element_size; ++i) {
buf_pointer[i] = element[i];
}
status = 1;
__sync_fetch_and_add(&buf->head, 1);
}
return status;
}
uint32_t ring_buffer_size(ring_buffer *buf) {
return buf->head - buf->tail;
}
uint32_t ring_buffer_empty(ring_buffer *buf) {
return (ring_buffer_size(buf) == 0);
}
void *ring_buffer_get(ring_buffer *buf) {
void *element;
//preserve the invariant that tail is always <= head
if (ring_buffer_empty(buf)) {
return 0;
}
element = &buf->data[(buf->tail & buf->mask) * buf->element_size];
__sync_fetch_and_add(&buf->tail, 1);
return element;
}
問題陳述允許我覆蓋舊的條目,例如這就是爲什麼我使用and和沒有檢查緩衝區是否已滿時放 - 我只覆蓋最舊的條目。但是,我很難推斷這是否是線程安全的。如前所述 - 重要的是這是無等待的(根據定義分別是無鎖),因爲生產商無法承受阻塞。大小將始終是2的冪,因此這就是爲什麼索引期間&工作。
任何輸入將不勝感激?
我不明白它是如何可以線程安全的,__sync_fetch_and_add確實是原子的,但是什麼可以防止競爭條件?我沒看到。 –
唯一的無等待環形緩衝區實現是當緩衝區溢出時調用exit(1)的實現。 –
從技術上講,緩衝區永遠不會變滿,因爲覆蓋舊條目完全可以。 – LordDoskias