Commit c379a920 authored by Matthieu Martin's avatar Matthieu Martin Committed by Facebook Github Bot

Add try_acquire to folly::fibers::Semaphore

Summary: This provides an interface for the Semaphore, which allow async waiting for more complex usage on fiber, without the future overhead.

Reviewed By: andriigrynenko

Differential Revision: D15082111

fbshipit-source-id: 76306525509f36867999db459ee0b7c42f416b6c
parent beef6090
......@@ -94,6 +94,23 @@ void Semaphore::wait() {
std::memory_order_acquire));
}
bool Semaphore::try_wait(Baton& waitBaton) {
auto oldVal = tokens_.load(std::memory_order_acquire);
do {
while (oldVal == 0) {
if (waitSlow(waitBaton)) {
return false;
}
oldVal = tokens_.load(std::memory_order_acquire);
}
} while (!tokens_.compare_exchange_weak(
oldVal,
oldVal - 1,
std::memory_order_release,
std::memory_order_acquire));
return true;
}
#if FOLLY_HAS_COROUTINES
coro::Task<void> Semaphore::co_wait() {
......
......@@ -49,6 +49,14 @@ class Semaphore {
*/
void wait();
/**
* Try to wait on the semaphore.
* Return true on success.
* On failure, the passed baton is enqueued, it will be posted once the
* semaphore has capacity. Caller is responsible to wait then signal.
*/
bool try_wait(Baton& waitBaton);
#if FOLLY_HAS_COROUTINES
/*
......
......@@ -1594,14 +1594,25 @@ TEST(FiberManager, semaphore) {
for (size_t i = 0; i < kTasks; ++i) {
manager.addTask([&, completionCounter]() {
for (size_t j = 0; j < kIterations; ++j) {
if (j % 2) {
sem.wait();
} else {
switch (j % 3) {
case 0:
sem.wait();
break;
case 1:
#if FOLLY_FUTURE_USING_FIBER
sem.future_wait().get();
sem.future_wait().get();
#else
sem.wait();
sem.wait();
#endif
break;
case 2: {
Baton baton;
bool acquired = sem.try_wait(baton);
if (!acquired) {
baton.wait();
}
break;
}
}
++counter;
sem.signal();
......
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