in src/moolib.cc [301:374]
py::object await() {
if (!moduleState) {
fatal("moolib module is not loaded");
}
if (!moduleState->get_running_loop) {
moduleState->get_running_loop = py::module::import("asyncio").attr("get_running_loop");
}
py::object loop = moduleState->get_running_loop();
py::object future = loop.attr("create_future")();
callback = rpc::Function<void()>([me = shared(), loop = GilWrapper<py::object>(std::move(loop)),
future = GilWrapper<py::object>(future)]() mutable noexcept {
int f = me->flags.load(std::memory_order_relaxed);
py::gil_scoped_acquire gil;
if (_Py_IsFinalizing()) {
return;
}
try {
keepThreadAlive();
if (f & 1) {
loop->attr("call_soon_threadsafe")(
py::cpp_function([me = std::move(me), future = std::move(future)]() mutable {
try {
if (!me->value) {
future->attr("set_exception")(py::reinterpret_borrow<py::object>(PyExc_RuntimeError)(
"Future value not available. Maybe it has already been retrieved"));
} else {
future->attr("set_result")(me->value.release());
}
} catch (const py::error_already_set& e) {
// InvalidStateError probably means that the future was cancelled
if (!e.matches(py::module::import("asyncio").attr("InvalidStateError"))) {
throw;
}
}
}));
} else if (f & 2) {
try {
loop->attr("call_soon_threadsafe")(py::cpp_function([me, future = std::move(future)]() mutable {
try {
std::lock_guard l(me->errorMutex);
future->attr("set_exception")(
py::reinterpret_borrow<py::object>(PyExc_RuntimeError)(me->error->what()));
} catch (const py::error_already_set& e) {
if (!e.matches(py::module::import("asyncio").attr("InvalidStateError"))) {
throw;
}
}
}));
} catch (const py::error_already_set& e) {
std::string s;
{
std::lock_guard l(me->errorMutex);
s = me->error->what();
}
fatal("Python exception during callback: %s\nOriginal exception: %s", e.what(), s);
}
} else if (f & 4) {
loop->attr("call_soon_threadsafe")(
py::cpp_function([future = std::move(future)]() mutable { future->attr("cancel")(); }));
} else {
fatal("Future callback called in invalid state");
}
} catch (const py::error_already_set& e) {
fatal("Python exception during callback: %s", e.what());
}
future.reset();
loop.reset();
}).release();
if (flags.load() != 0) {
doCallback();
}
return future.attr("__await__")();
}