I am looking for "complete" producer-consumer sample using C++11 memory barrier.
(I have derived following example from Jeff's article and added a line to make it complete.)
void SendTestMessage(void* param)
{
// Copy to shared memory using non-atomic stores.
g_payload.tick = clock();
g_payload.str = "TestMessage";
g_payload.param = param;
// Release fence.
std::atomic_thread_fence(std::memory_order_release);
// Perform an atomic write to indicate that the message is ready.
g_guard.store(1, std::memory_order_relaxed);
}
bool TryReceiveMessage(Message& result)
{
// Perform an atomic read to check whether the message is ready.
int ready = g_guard.load(std::memory_order_relaxed);
if (ready != 0)
{
g_guard.store(0, std::memory_order_relaxed);
// Acquire fence.
std::atomic_thread_fence(std::memory_order_acquire);
// Yes. Copy from shared memory using non-atomic loads.
result.tick = g_payload.tick;
result.str = g_payload.str;
result.param = g_payload.param;
return true;
}
// No.
return false;
}
if you notice, i added "g_guard.store(0, std::memory_order_relaxed);" just before acquire. This will help following ways
- It would avoid "TryReciveMessage" to cosnume same message if called multiple times before new message is written
- It would not add explicit memory fence and hence won't affect performance
- since "std::memory_order_relaxed" guarantees the ordering, it would be get overwritten by "SendTestMessage" value if new load added after the "std::memory_order_acquire" is called. So, we will not miss any load.
Please provide your comments and/or suggestions.
Aucun commentaire:
Enregistrer un commentaire