У меня есть сценарий, в котором у меня может быть несколько производителей, но один потребитель кольцевого буфера. вот исходный код:
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, поэтому & во время индексации работает.
Любой вклад будет оценен?