Commit 4dedb180 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Avoid unnecessary ping-pong in portable test semaphore wakeup

Summary: [Folly] Avoid unnecessary ping-pong in portable test semaphore wakeup when `wait()` is called without callback arguments.

Reviewed By: nbronson

Differential Revision: D15903121

fbshipit-source-id: c40018bbd0c49f5114a340a9b97c8cc9f8f70a7c
parent 78868270
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include <folly/Optional.h>
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
#include <folly/lang/Exception.h> #include <folly/lang/Exception.h>
...@@ -134,19 +135,23 @@ class PolicySemaphore { ...@@ -134,19 +135,23 @@ class PolicySemaphore {
--value_; --value_;
post_wait(); post_wait();
} else { } else {
auto const protect_post_wait = !is_empty_callable(post_wait);
Waiter w; Waiter w;
waiters_.push_back(w); waiters_.push_back(w);
w.protect_waiter_post_wait = protect_post_wait;
w.wake_waiter.wait(lock); w.wake_waiter.wait(lock);
auto guard = makeGuard([&] { auto guard = makeGuard([&] {
w.wake_poster->post(); if (protect_post_wait) {
w.wake_waiter.wait(lock); w.wake_poster->post();
w.wake_waiter.wait(lock);
}
}); });
post_wait(); post_wait();
} }
} }
void wait() { void wait() {
wait([] {}, [] {}); wait(EmptyCallable{}, EmptyCallable{});
} }
template <typename PrePost> template <typename PrePost>
...@@ -161,11 +166,17 @@ class PolicySemaphore { ...@@ -161,11 +166,17 @@ class PolicySemaphore {
} else { } else {
auto& w = pull(); auto& w = pull();
waiters_.erase(waiters_.iterator_to(w)); waiters_.erase(waiters_.iterator_to(w));
Event wake_poster; auto const protect_waiter_post_wait = w.protect_waiter_post_wait;
w.wake_poster = &wake_poster; Optional<Event> wake_poster;
w.wake_waiter.post(); if (protect_waiter_post_wait) {
wake_poster.wait(lock); wake_poster.emplace();
w.wake_poster = &*wake_poster;
}
w.wake_waiter.post(); w.wake_waiter.post();
if (protect_waiter_post_wait) {
wake_poster->wait(lock);
w.wake_waiter.post();
}
} }
} }
...@@ -191,11 +202,25 @@ class PolicySemaphore { ...@@ -191,11 +202,25 @@ class PolicySemaphore {
}; };
struct Waiter : boost::intrusive::list_base_hook<> { struct Waiter : boost::intrusive::list_base_hook<> {
bool protect_waiter_post_wait = false;
Event wake_waiter; Event wake_waiter;
Event* wake_poster; Event* wake_poster = nullptr;
}; };
using WaiterList = boost::intrusive::list<Waiter>; using WaiterList = boost::intrusive::list<Waiter>;
class EmptyCallable {
public:
constexpr void operator()() const noexcept {}
};
template <typename Callable>
std::false_type is_empty_callable(Callable const&) {
return {};
}
std::true_type is_empty_callable(EmptyCallable const&) {
return {};
}
Waiter& pull() { Waiter& pull() {
switch (WakePolicy) { switch (WakePolicy) {
case SemaphoreWakePolicy::Fifo: case SemaphoreWakePolicy::Fifo:
......
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