like a normal semaphore, but with awaitable acquire actions. this is primarily intended as an intermediate concurrency limiting device in the Worker code, but it may find other uses over time. we do not use std::counting_semaphore as a base because the counter of that is not inspectable as will be needed for Worker. we also do not need atomic operations for cross-thread consistency since we don't have multiple threads (thanks to kj event loops being confined to a single thread) Change-Id: Ie2bcb107f3a2c0185138330f7cbba4cec6cbdd95
75 lines
1.7 KiB
C++
75 lines
1.7 KiB
C++
#include "async-semaphore.hh"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <kj/async.h>
|
|
|
|
namespace nix {
|
|
|
|
TEST(AsyncSemaphore, counting)
|
|
{
|
|
kj::EventLoop loop;
|
|
kj::WaitScope waitScope(loop);
|
|
|
|
AsyncSemaphore sem(2);
|
|
|
|
ASSERT_EQ(sem.available(), 2);
|
|
ASSERT_EQ(sem.used(), 0);
|
|
|
|
auto a = kj::evalNow([&] { return sem.acquire(); });
|
|
ASSERT_EQ(sem.available(), 1);
|
|
ASSERT_EQ(sem.used(), 1);
|
|
auto b = kj::evalNow([&] { return sem.acquire(); });
|
|
ASSERT_EQ(sem.available(), 0);
|
|
ASSERT_EQ(sem.used(), 2);
|
|
|
|
auto c = kj::evalNow([&] { return sem.acquire(); });
|
|
auto d = kj::evalNow([&] { return sem.acquire(); });
|
|
|
|
ASSERT_TRUE(a.poll(waitScope));
|
|
ASSERT_TRUE(b.poll(waitScope));
|
|
ASSERT_FALSE(c.poll(waitScope));
|
|
ASSERT_FALSE(d.poll(waitScope));
|
|
|
|
a = nullptr;
|
|
ASSERT_TRUE(c.poll(waitScope));
|
|
ASSERT_FALSE(d.poll(waitScope));
|
|
|
|
{
|
|
auto lock = b.wait(waitScope);
|
|
ASSERT_FALSE(d.poll(waitScope));
|
|
}
|
|
|
|
ASSERT_TRUE(d.poll(waitScope));
|
|
|
|
ASSERT_EQ(sem.available(), 0);
|
|
ASSERT_EQ(sem.used(), 2);
|
|
c = nullptr;
|
|
ASSERT_EQ(sem.available(), 1);
|
|
ASSERT_EQ(sem.used(), 1);
|
|
d = nullptr;
|
|
ASSERT_EQ(sem.available(), 2);
|
|
ASSERT_EQ(sem.used(), 0);
|
|
}
|
|
|
|
TEST(AsyncSemaphore, cancelledWaiter)
|
|
{
|
|
kj::EventLoop loop;
|
|
kj::WaitScope waitScope(loop);
|
|
|
|
AsyncSemaphore sem(1);
|
|
|
|
auto a = kj::evalNow([&] { return sem.acquire(); });
|
|
auto b = kj::evalNow([&] { return sem.acquire(); });
|
|
auto c = kj::evalNow([&] { return sem.acquire(); });
|
|
|
|
ASSERT_TRUE(a.poll(waitScope));
|
|
ASSERT_FALSE(b.poll(waitScope));
|
|
|
|
b = nullptr;
|
|
a = nullptr;
|
|
|
|
ASSERT_TRUE(c.poll(waitScope));
|
|
}
|
|
|
|
}
|