jeudi 2 juillet 2015

Uses of memory_order_relaxed

There are already a few questions on Stackoverflow that essentially ask about the use cases of memory_order_relaxed, such as:

Understanding memory_order_relaxed

What are some use cases for memory_order_relaxed

However, I'm still confused about the precise semantics of memory_order_relaxed. Generally, the example use case for memory_order_relaxed is something like std::shared_ptr - basically it keeps an atomic counter, but it doesn't need to sync with other threads.

Okay, so my understanding is as follows:

std::memory_order_relaxed, when used with load() only guarantees that the thread which loads it will do so atomically - it makes no guarantee about any orderings with respect to other threads that do store() operations on the same variable, and it makes absolutely no guarantee about any loads/stores of non-atomic variables (i.e. no memory fence will be generated.)

If my understanding is correct, isn't another valid use case for memory_order_relaxed for cases when a thread simply wants to load the value, and do something with it that doesn't involve syncing with other threads? Like say, generating a report, or outputting the "current" value to console?

Like:

std::atomic<int> x(0);

...

void get_current_value()
{
  int val = x.load(std::memory_order_relaxed);
  std::cout << "Last seen value of x from this thread is " << val << std::endl;
}

Is my understanding here correct?

But does memory_order_relaxed provide ANY sort of "happens-before" type ordering ability, with regard only to the single atomic value? For example, if we have:

std::atomic_flag x = ATOMIC_FLAG_INIT;

// Thread A:

if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread A got here first!" << std::endl;
}

// Thread B:

if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread B got here first!" << std::endl;
}

In the above example, even though we used memory_order_relaxed, haven't we also provided a guaranteed way to reason about ordering here? In others, both Thread A and Thread B will be able to reason about which thread set the flag first. Or am I incorrect here?

Aucun commentaire:

Enregistrer un commentaire