LockFreeQueue icon indicating copy to clipboard operation
LockFreeQueue copied to clipboard

c++11 memory order problem

Open wenzhang-dev opened this issue 2 years ago • 2 comments

Hi, It's like I found a treasure. but when I read you c++ code, one question confused me.

The mpmc_bounded_queue::size method calculate the size of enqueued nodes by acquire-relaxed memory order. What that means?

Getting head by acquire barrier, it easily understand. but why we should use following relaxed memory order to get enqueue_pos_? I see the c++ spec about relaxed order, which only make sure that instruction is an atomic operation, but can't provide any synchorization. so the enqueue_pos_ variable may be an old value?

image

wenzhang-dev avatar Dec 29 '21 11:12 wenzhang-dev

Hi Micheal,

the intention is that dequeue_pos_ is read before enqueue_pos_. I think this is assured since there is a memory barrier after the first read because of memory_order_acquire. So, the second read cannot happen before the first and it does not really matter when it happens afterwards.

But, I am not sure if it actually works like this. (Maybe it does not since dequeue_pos_ and enqueue_pos_ are two different variables.) I guess size() could return a negative value if it does not work. Did you observe something like this?

Anyways, the value returned by size() is very prone to race conditions if there are concurrent data producer and consumer threads. So, the returned value is always just a hint of the current size.

craflin avatar Dec 30 '21 12:12 craflin

thank you for your response,

based on my recent research, I find that atomic operations alway make themself visible for other physical cores. but memory orders can further control compiler and cpu reorder the instructions. for Relaxed order, arbitrary reorder are allowed; for require memory order, subsequent Load instructions cannot reorder to the front; similarly, for release memory order, subsequent Store instructions cannot reorder to the front.

So i think your code using acquire-relaxed barrier is correct. enqueue_pos_ with relaxed-order is visible for local core, although its value may have changed.

even think that head and enqueue_pos_ are both relaxed-order, and the result is still correct. Can you agree with me?

wenzhang-dev avatar Dec 30 '21 13:12 wenzhang-dev