#include <folly/fibers/Semaphore.h>
namespace folly {
namespace fibers {
bool Semaphore::signalSlow() { … }
void Semaphore::signal() { … }
bool Semaphore::waitSlow(Waiter& waiter) { … }
void Semaphore::wait() { … }
bool Semaphore::try_wait(Waiter& waiter) { … }
bool Semaphore::try_wait() { … }
#if FOLLY_HAS_COROUTINES
coro::Task<void> Semaphore::co_wait() {
auto oldVal = tokens_.load(std::memory_order_acquire);
do {
while (oldVal == 0) {
Waiter waiter;
if (waitSlow(waiter)) {
bool cancelled = false;
{
const auto& ct = co_await folly::coro::co_current_cancellation_token;
folly::CancellationCallback cb{
ct, [&] {
{
auto waitListLock = waitList_.wlock();
auto& waitList = *waitListLock;
if (!waiter.hook_.is_linked()) {
return;
}
cancelled = true;
waitList.erase(waitList.iterator_to(waiter));
}
waiter.baton.post();
}};
co_await waiter.baton;
}
if (cancelled) {
co_yield folly::coro::co_cancelled;
}
co_return;
}
oldVal = tokens_.load(std::memory_order_acquire);
}
} while (!tokens_.compare_exchange_weak(
oldVal,
oldVal - 1,
std::memory_order_release,
std::memory_order_acquire));
}
#endif
namespace {
class FutureWaiter final : public fibers::Baton::Waiter { … };
}
SemiFuture<Unit> Semaphore::future_wait() { … }
size_t Semaphore::getCapacity() const { … }
size_t Semaphore::getAvailableTokens() const { … }
}
}