Commit 1446ede2 authored by Kenton Varda's avatar Kenton Varda

Test using same-thread executor, fix bugs.

parent 776eee73
......@@ -432,5 +432,29 @@ KJ_TEST("cross-thread cancellation in both directions at once") {
simultaneous(parentExecutor, childExecutor);
}
KJ_TEST("call own thread's executor") {
KJ_XTHREAD_TEST_SETUP_LOOP;
auto& executor = getCurrentThreadExecutor();
{
uint i = executor.executeSync([]() {
return 123u;
});
KJ_EXPECT(i == 123);
}
KJ_EXPECT_THROW_MESSAGE(
"can't call executeSync() on own thread's executor with a promise-returning function",
executor.executeSync([]() { return kj::evalLater([]() {}); }));
{
uint i = executor.executeAsync([]() {
return 123u;
}).wait(waitScope);
KJ_EXPECT(i == 123);
}
}
} // namespace
} // namespace kj
......@@ -604,8 +604,25 @@ Executor::~Executor() noexcept(false) {}
void Executor::send(_::XThreadEvent& event, bool sync) const {
KJ_ASSERT(event.state == _::XThreadEvent::UNUSED);
if (!sync) {
if (sync) {
if (threadLocalEventLoop == &loop) {
// Invoking a sync request on our own thread. Just execute it directly; if we try to queue
// it to the loop, we'll deadlock.
auto promiseNode = event.execute();
// If the function returns a promise, we have no way to pump the event loop to wait for it,
// because the event loop may already be pumping somewhere up the stack.
KJ_ASSERT(promiseNode == nullptr,
"can't call executeSync() on own thread's executor with a promise-returning function");
return;
}
} else {
event.replyExecutor = getCurrentThreadExecutor();
// Note that async requests will "just work" even if the target executor is our own thread's
// executor. In theory we could detect this case to avoid some locking and signals but that
// would be extra code complexity for probably little benefit.
}
auto lock = impl->state.lockExclusive();
......
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