Simple, Fast, Practical Non-Blocking and Blocking Concurrent Queue Algorithms
cs.rochester.edu
cs.rochester.edu
You do need barriers: issue a write barrier before giving a copy of the write pointer to the reader. Issue a read barrier before reading the data.
Avoid cache line thrashing in a mostly full case by never allowing the circular buffer to become completely full (leave at least one cache line free).
The reader thread can quickly poll many circular buffers for work. The pointers will all reside in the reader's cache until someone has written some data (and updates the reader's copy of the write pointer).
You can get more benefits by delaying the update of the other thread's pointers: on the writer's side, until we have no more data available to write. On the reader's side, until we have read all the data (or some larger chunk of it). This allows the cache-line prefetching hardware to work (to prefetch likely used data).
Anyway, if you really want to use a linked list, at the very least allocate multiple items per cache line, and then link the cache lines together (so one link pointer or less per cache line).
https://github.com/mjpt777/examples/tree/master/src/java/uk/...
I have a number of Go implementations of the same queues here
C11 has a new header stdatomic.h which only allows atomic for integer types.
How do you perform CAS on a struct in C( without using a mutex of course )?