我有一个场景,我可以拥有多个生产者但只有一个环形缓冲区的消费者。这是源代码:
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;
}
问题陈述允许我覆盖较旧的条目,例如这就是为什么我使用和而且在放置时没有检查缓冲区是否已满 - 我只是覆盖了最旧的条目。但是,我很难推断这是否是线程安全的。如前所述 - 重要的是这是无等待的(根据定义分别无锁),因为生产者不能阻止。大小总是2的幂,这就是为什么&amp;在索引工作期间。
任何输入都会受到赞赏吗?
答案 0 :(得分:0)
不,您的实现不是线程安全的。
如果同时有两个线程put
元素,它们最终可以写入相同的位置,甚至可以在一个位置写入半个记录而另一个位置在下一个位置。