On May 20, 7:12 pm, anthony....@gmail.com wrote:
"Dmitriy V'jukov" <dvyu...@gmail.comwrites:
On May 20, 6:15 pm, "Dmitriy V'jukov" <dvyu...@gmail.comwrote:
2. Acquire operation must read value in 'release-sequence' of release
operation. What value "reads" fence() function? Since fence() is RMW
atomic operation, it must "read" some value. But how can I find out
what value it reads?
Btw, this applies to atomic_fence() function in general - what value
it "reads"?
You apply a fence on a specific variable, and it "reads" one of the
values written to the variable by some thread. A fence is a RMW
operation that writes the same value back.
If I don't know what value it reads then I can't be sure that
something 'synchronized-with'.
True. Fences need to be used carefully, and in combination with other
operations.
Ok. In following example I know what value fence operation will
"read". And luckily 'release sequence' is still not broken when
acquire operation executes.
void release(T* obj)
{
int rc = obj->rc.fetch_add(-1, memory_order_release) - 1;
if (0 == rc)
{
if (0 == obj->rc.fence(memory_order_acquire))
delete obj;
else
assert(false);
}
}
But let's consider Paul McKenney's motivating example from N2153
(
http://www.open-std.org/jtc1/sc22/wg...07/n2153.pdf):
for (i=0; i< num_mailboxes; i++)
{
if (mailbox[i].load_raw() == my_id)
{
acquire_fence(); // Prevents speculation of memory do_work(i);
// accesses in do_work
}
}
The goal is to remove acquire fence from every load. And issue acquire
fence only when there is real work to do.
As I understand following code won't work:
for (i=0; i< num_mailboxes; i++)
{
if (mailbox[i].load(std::memory_order_relaxed) == my_id)
{
mailbox[i].fence(std::memory_order_acquire); // Prevents
speculation of memory do_work(i);
// accesses in do_work
}
}
Because 'release sequence' is just broken by relaxed load. Right?
This code will work if definition of 'synchronizes with' will be
changed from:
"An evaluation A that performs a release operation on an object M
synchronizes with an evaluation B that performs an acquire operation
on M and reads a value written by any side effect in the release
sequence headed by A."
to:
"An evaluation A that performs a release operation on an object M
synchronizes with an evaluation B that performs an acquire operation
on M and B *or any expression sequenced before B* reads a value
written by any side effect in the release sequence headed by A."
What do you think?
Dmitriy V'jukov