#include <folly/fibers/SemaphoreBase.h>
namespace folly {
namespace fibers {
bool SemaphoreBase::signalSlow(int64_t tokens) { … }
bool SemaphoreBase::waitSlow(Waiter& waiter, int64_t tokens) { … }
void SemaphoreBase::wait_common(int64_t tokens) { … }
bool SemaphoreBase::try_wait_common(Waiter& waiter, int64_t tokens) { … }
bool SemaphoreBase::try_wait_common(int64_t tokens) { … }
#if FOLLY_HAS_COROUTINES
coro::Task<void> SemaphoreBase::co_wait_common(int64_t tokens) {
auto oldVal = tokens_.load(std::memory_order_acquire);
do {
while (oldVal < tokens) {
Waiter waiter{tokens};
if (waitSlow(waiter, tokens)) {
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 - tokens,
std::memory_order_release,
std::memory_order_acquire));
}
#endif
namespace {
class FutureWaiter final : public fibers::Baton::Waiter { … };
}
SemiFuture<Unit> SemaphoreBase::future_wait_common(int64_t tokens) { … }
size_t SemaphoreBase::getCapacity() const { … }
size_t SemaphoreBase::getAvailableTokens() const { … }
}
}