Commit d973a73e authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook GitHub Bot

Mitigate lock contention in BlockingWaitExecutor

Summary: `BlockingWaitExecutor::add` (and similarly `WaitExecutor`) posts the baton while holding the queue lock. If these happen in two different threads, the `drive()` thread wakes up while the lock is still held; the `add()` thread may be descheduled before the lock is released, causing the other thread to have to wait (and possibly sleep) for a while.

Reviewed By: andriigrynenko

Differential Revision: D25814620

fbshipit-source-id: 07d3e9afdc4647e68f996e3f0a1c007fd1596611
parent 1be254ba
...@@ -306,9 +306,12 @@ class BlockingWaitExecutor final : public folly::DrivableExecutor { ...@@ -306,9 +306,12 @@ class BlockingWaitExecutor final : public folly::DrivableExecutor {
} }
void add(Func func) override { void add(Func func) override {
bool empty;
{
auto wQueue = queue_.wlock(); auto wQueue = queue_.wlock();
bool empty = wQueue->empty(); empty = wQueue->empty();
wQueue->push_back(std::move(func)); wQueue->push_back(std::move(func));
}
if (empty) { if (empty) {
baton_.post(); baton_.post();
} }
......
...@@ -478,12 +478,15 @@ FutureBase<T>::thenImplementation( ...@@ -478,12 +478,15 @@ FutureBase<T>::thenImplementation(
class WaitExecutor final : public folly::Executor { class WaitExecutor final : public folly::Executor {
public: public:
void add(Func func) override { void add(Func func) override {
bool empty;
{
auto wQueue = queue_.wlock(); auto wQueue = queue_.wlock();
if (wQueue->detached) { if (wQueue->detached) {
return; return;
} }
bool empty = wQueue->funcs.empty(); empty = wQueue->funcs.empty();
wQueue->funcs.push_back(std::move(func)); wQueue->funcs.push_back(std::move(func));
}
if (empty) { if (empty) {
baton_.post(); baton_.post();
} }
......
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