19 class [[nodiscard(
"destroying a semaphore guard releases the semaphore immediately")]] Token
23 void operator()(AsyncSemaphore * sem)
const
29 std::unique_ptr<AsyncSemaphore, Release> parent;
33 Token(AsyncSemaphore & parent, kj::Badge<AsyncSemaphore>) : parent(&parent) {}
37 return parent !=
nullptr;
44 kj::PromiseFulfiller<Token> & fulfiller;
45 kj::ListLink<Waiter> link;
46 kj::List<Waiter, &Waiter::link> & list;
48 Waiter(kj::PromiseFulfiller<Token> & fulfiller, kj::List<Waiter, &Waiter::link> & list)
49 : fulfiller(fulfiller)
57 if (link.isLinked()) {
63 const unsigned capacity_;
65 kj::List<Waiter, &Waiter::link> waiters;
70 while (used_ < capacity_ && !waiters.empty()) {
72 auto & w = waiters.front();
73 w.fulfiller.fulfill(
Token{*
this, {}});
79 explicit AsyncSemaphore(
unsigned capacity) : capacity_(capacity) {}
81 KJ_DISALLOW_COPY_AND_MOVE(AsyncSemaphore);
85 assert(waiters.empty() &&
"destroyed a semaphore with active waiters");
88 std::optional<Token> tryAcquire()
90 if (used_ < capacity_) {
92 return Token{*
this, {}};
98 kj::Promise<Token> acquire()
100 if (
auto t = tryAcquire()) {
101 return std::move(*t);
103 return kj::newAdaptedPromise<Token, Waiter>(waiters);
107 unsigned capacity()
const
112 unsigned used()
const
117 unsigned available()
const
119 return capacity_ - used_;