Commit 621b5b0b authored by Robin Cheng's avatar Robin Cheng Committed by Facebook GitHub Bot

Fix memory ordering for EventBase::isRunning().

Summary: Technically speaking the contract of isRunning() is unclear on whether it can be used as a synchronization mechanism; it could, e.g. be used solely for diagnostics purposes, in which case memory_order_relaxed would be enough. But it is used at least to implement waitUntilRunning(), so memory_order_acquire/memory_order_release is needed to achieve proper synchronization.

Reviewed By: yfeldblum

Differential Revision: D26436697

fbshipit-source-id: 2be07c473e1cb286e6044fa677304816921e888d
parent 87d9f1da
...@@ -286,7 +286,7 @@ static std::chrono::milliseconds getTimeDelta( ...@@ -286,7 +286,7 @@ static std::chrono::milliseconds getTimeDelta(
} }
void EventBase::waitUntilRunning() { void EventBase::waitUntilRunning() {
while (!isRunning()) { while (loopThread_.load(std::memory_order_acquire) == std::thread::id()) {
std::this_thread::yield(); std::this_thread::yield();
} }
} }
...@@ -340,7 +340,7 @@ bool EventBase::loopBody(int flags, bool ignoreKeepAlive) { ...@@ -340,7 +340,7 @@ bool EventBase::loopBody(int flags, bool ignoreKeepAlive) {
std::chrono::microseconds idle; std::chrono::microseconds idle;
auto const prevLoopThread = loopThread_.exchange( auto const prevLoopThread = loopThread_.exchange(
std::this_thread::get_id(), std::memory_order_relaxed); std::this_thread::get_id(), std::memory_order_release);
CHECK_EQ(std::thread::id(), prevLoopThread) CHECK_EQ(std::thread::id(), prevLoopThread)
<< "Driving an EventBase in one thread (" << std::this_thread::get_id() << "Driving an EventBase in one thread (" << std::this_thread::get_id()
<< ") while it is already being driven in another thread (" << ") while it is already being driven in another thread ("
......
...@@ -663,7 +663,10 @@ class EventBase : public TimeoutManager, ...@@ -663,7 +663,10 @@ class EventBase : public TimeoutManager,
} }
/** /**
* check if the event base loop is running. * Check if the event base loop is running.
*
* This may only be used as a sanity check mechanism; it cannot be used to
* make any decisions; for that, consider waitUntilRunning().
*/ */
bool isRunning() const { bool isRunning() const {
return loopThread_.load(std::memory_order_relaxed) != std::thread::id(); return loopThread_.load(std::memory_order_relaxed) != std::thread::id();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment