Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c++11 memory order problem #1

Open
wenzhang-dev opened this issue Dec 29, 2021 · 2 comments
Open

c++11 memory order problem #1

wenzhang-dev opened this issue Dec 29, 2021 · 2 comments

Comments

@wenzhang-dev
Copy link

wenzhang-dev commented Dec 29, 2021

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

@craflin
Copy link
Owner

craflin commented Dec 30, 2021

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.

@wenzhang-dev
Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants