An asio::any_io_executor compatible wrapper around the event loop. all the query functions are for that compatibility.
| 30 | // An asio::any_io_executor compatible wrapper around the event loop. |
| 31 | // all the query functions are for that compatibility. |
| 32 | struct python_executor |
| 33 | { |
| 34 | python_executor(py::object loop = ::get_loop()) noexcept |
| 35 | : m_ptr(loop.ptr()) |
| 36 | { |
| 37 | // the asio::execution_context needs to present, we put it into the event loop. |
| 38 | if (!py::hasattr(loop, "__asio_execution_context")) |
| 39 | { |
| 40 | auto ptr = std::make_unique<asio::execution_context>(); |
| 41 | context_ = ptr.get(); |
| 42 | py::setattr(loop, "__asio_execution_context", |
| 43 | py::cast(std::move(ptr))); |
| 44 | } |
| 45 | else |
| 46 | context_ = py::cast<std::unique_ptr<asio::execution_context>&>( |
| 47 | py::getattr(loop, "__asio_execution_context") |
| 48 | ).get(); |
| 49 | } |
| 50 | |
| 51 | asio::execution_context &query(asio::execution::context_t) const |
| 52 | { |
| 53 | return *context_; |
| 54 | } |
| 55 | |
| 56 | static constexpr asio::execution::blocking_t |
| 57 | query(asio::execution::blocking_t) noexcept |
| 58 | { |
| 59 | return asio::execution::blocking.never; |
| 60 | } |
| 61 | |
| 62 | // this function takes the function F and runs it on the event loop. |
| 63 | template<class F> |
| 64 | void |
| 65 | execute(F f) const |
| 66 | { |
| 67 | py::gil_scoped_acquire lock; |
| 68 | py::handle loop(m_ptr); |
| 69 | struct wrapper // override the const. |
| 70 | { |
| 71 | mutable F impl; |
| 72 | |
| 73 | void operator()( ) const |
| 74 | { |
| 75 | std::move(impl)(); |
| 76 | } |
| 77 | }; |
| 78 | loop.attr("call_soon_threadsafe")(py::cpp_function(wrapper{std::move(f)})); |
| 79 | } |
| 80 | |
| 81 | bool |
| 82 | operator==(python_executor const &other) const noexcept |
| 83 | { |
| 84 | return m_ptr == other.m_ptr; |
| 85 | } |
| 86 | |
| 87 | bool |
| 88 | operator!=(python_executor const &other) const noexcept |
| 89 | { |