As known, there are 6 std::memory_order's, and 2 of its:
- acquire-semantic used for loads - avoids reordering Load-Load and Load-Store
- release-semantic used for stores - avoids reordering Store-Store and Load-Store
I.e. for acquire-semantic, only S = local1; can be executed after X.load(std::memory_order_acquire);:
static std::atomic<int> X;
static int L, S;
...
void thread_func()
{
int local1 = L; // load(L)-load(X) - !!! can be reordered with X !!!
S = local1; // store(S)-load(X) - !!! can be reordered with X !!!
int x_local = X.load(std::memory_order_acquire); // load(X)
int local2 = L; // load(X)-load(L) - can't be reordered with X
S = local2; // load(X)-store(S) - can't be reordered with X
}
But which of reorders across load(X) can be for consume-semantic?
static std::atomic<int *> X;
static int L1, L2, S1, S2;
static int L, S;
...
void thread_func()
{
int *x_ptr_local = new int(1);
int local1 = L1; // load(L1)-load(X) - !!! can be reordered with X !!!
S1 = local1; // store(S1)-load(X) - !!! can be reordered with X !!!
int dependent_x1 = *x_ptr_local; // load(x_ptr)-load(X) - !!! can be reordered with X !!!
S = dependent_x1; // store(S)-load(X) - !!! can be reordered with X !!!
x_ptr_local = X.load(std::memory_order_consume); // load(X)
int dependent_x2 = *x_ptr_local; // load(X)-load(x_ptr) - can't be reordered with X
S = dependent_x2; // load(X)-store(S) - can't be reordered with X
int local2 = L2; // load(X)-load(L2) - !!! can be reordered with X !!!
S2 = local2; // load(X)-store(S2) - !!! can be reordered with X !!!
}
Is it true, that only operations with dependent_x2 can't be reordered across X.load(std::memory_order_consume)?
And all of operations with variables L1, L2, S1, S2 and dependent_x1 can be reordered across X.load(std::memory_order_consume) - i.e. can be performed either before or after X.load(std::memory_order_consume), isn't it?

int local1 = L;be reordered belowx_localin the first example? - 2501int local1 = L;can't be reordered below (2)int x_local = X.load(std::memory_order_acquire);, because are both - Loads, andstd::memory_order_acquireprevent Load-Load reordering - as shown on picture, isn't it? - AlexS = local1;can go below 2, so can 1. What is so special about 1? - 2501Xin your 2nd example bestd::atomic<int*>instead ofstd::atomic<int>*? - Alejandro