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 @@
#include <boost/intrusive/list.hpp>
#include <folly/Optional.h>
#include <folly/ScopeGuard.h>
#include <folly/lang/Exception.h>
......@@ -134,19 +135,23 @@ class PolicySemaphore {
--value_;
post_wait();
} else {
auto const protect_post_wait = !is_empty_callable(post_wait);
Waiter w;
waiters_.push_back(w);
w.protect_waiter_post_wait = protect_post_wait;
w.wake_waiter.wait(lock);
auto guard = makeGuard([&] {
if (protect_post_wait) {
w.wake_poster->post();
w.wake_waiter.wait(lock);
}
});
post_wait();
}
}
void wait() {
wait([] {}, [] {});
wait(EmptyCallable{}, EmptyCallable{});
}
template <typename PrePost>
......@@ -161,13 +166,19 @@ class PolicySemaphore {
} else {
auto& w = pull();
waiters_.erase(waiters_.iterator_to(w));
Event wake_poster;
w.wake_poster = &wake_poster;
auto const protect_waiter_post_wait = w.protect_waiter_post_wait;
Optional<Event> wake_poster;
if (protect_waiter_post_wait) {
wake_poster.emplace();
w.wake_poster = &*wake_poster;
}
w.wake_waiter.post();
wake_poster.wait(lock);
if (protect_waiter_post_wait) {
wake_poster->wait(lock);
w.wake_waiter.post();
}
}
}
void post() {
post([] {});
......@@ -191,11 +202,25 @@ class PolicySemaphore {
};
struct Waiter : boost::intrusive::list_base_hook<> {
bool protect_waiter_post_wait = false;
Event wake_waiter;
Event* wake_poster;
Event* wake_poster = nullptr;
};
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() {
switch (WakePolicy) {
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