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't 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't be reordered with X
S = dependent_x1; // store(S)-load(X) - can't 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_x1
and dependent_x2
can't be reordered across X.load(std::memory_order_consume)
?
And all of operations with variables L1
, L2
, S1
, S2
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?
Aucun commentaire:
Enregistrer un commentaire