Skip to content

Commit e4ec199

Browse files
committed
add event_loop doc
1 parent afcccbc commit e4ec199

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

Diff for: doc/reference/eventloop.qbk

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
[chapter Event Loop
2+
[quickbook 1.7]
3+
]
4+
5+
[section boost/python/eventloop.hpp]
6+
7+
[section Introduction]
8+
Provide a Boost.Asio-based implementation for the Python [@https://docs.python.org/3/library/asyncio-eventloop.html `EventLoop`] type. Every callback is scheduled in strand.
9+
[endsect]
10+
11+
[section Function `set_default_event_loop`]
12+
``
13+
void set_default_event_loop(const boost::asio::io_context::strand& strand);
14+
``
15+
[variablelist
16+
[[Effect][construct an `event_loop` object using provided [@https://www.boost.org/doc/libs/1_76_0/doc/html/boost_asio/overview/core/strands.html `strand`] object. Setup a new [@https://docs.python.org/3/library/asyncio-policy.html event loop policy], when user call `get_event_loop` using that policy, it returns the Boost Asio `event_loop` object]]
17+
[[Throws][nothing]]
18+
]
19+
[endsect]
20+
21+
[section Function `PyInit_boost_event_loop`]
22+
``
23+
extern "C"
24+
{
25+
PyObject* PyInit_boost_event_loop();
26+
}
27+
``
28+
[variablelist
29+
[[Effect][user must call `PyImport_AppendInittab("boost_event_loop", &PyInit_boost_event_loop);` before [@https://docs.python.org/3/c-api/init.html#c.Py_Initialize `Py_Initialize`]]]
30+
[[Throws][nothing]]
31+
]
32+
[endsect]
33+
34+
[section Example]
35+
``
36+
// example.cpp
37+
io_context ctx;
38+
io_context::strand st{ctx};
39+
40+
PyImport_AppendInittab("boost_event_loop", &PyInit_boost_event_loop);
41+
Py_Initialize();
42+
set_default_event_loop(st);
43+
44+
object py_module = import("example.py");
45+
py_module.attr("hello_world")();
46+
st.context().run();
47+
48+
// example.py
49+
import asyncio
50+
def hello_world():
51+
print("hello world")
52+
53+
def call_event_loop():
54+
loop = asyncio.get_event_loop_policy().get_event_loop()
55+
loop.call_soon(hello_world)
56+
``
57+
Note: `set_default_event_loop` must be called before any Python module is imported. Otherwise it may result in the module-level variables registered against the default asyncio eventloop instead the boost asio eventloop. Here is an example demonstrating the issue.
58+
``
59+
// bad_import.cpp
60+
Py_Initialize();
61+
import("example_module"); // example_module is initialized
62+
set_default_event_loop(st); // boost_asio_eventloop is set to default, but the example_module.lock was registered against the old eventloop
63+
64+
// example_module.py
65+
import asyncio
66+
lock = asyncio.Lock()
67+
``
68+
[endsect]
69+
70+
[section Event Loop and Multiple Python Sub-interpreters]
71+
It's allowed to have multiple Python sub-interpreter instances in a same program. Each interpreter will act as a guest VM, and C++ host will schedule all the asynchronous events committed by the Python VM.[br]
72+
The Python interpreter must outlive the [@https://www.boost.org/doc/libs/1_76_0/doc/html/boost_asio/reference/io_service.html `asio::io_context`] objects it owns. It's not safe to destroy the interpreter midways.[br]
73+
[endsect]
74+
75+
[section [@https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock `GIL`]]
76+
`boost::asio::io_context::run()` may be called from multiple threads and the completion handlers may wakeup on different threads as well. The GIL must be released after setting up the Python IO object and before the call to `boost::asio::io_context::run()`. In the completion handler, the GIL must be reacquired and release before it calls into Python to deliver the result.
77+
``
78+
// gil.cpp
79+
py_func(); // call func imported from gil.py
80+
PyEval_ReleaseLock(); // release GIL
81+
ctx.run();
82+
83+
// gil.py
84+
import asyncio
85+
86+
def hello():
87+
print("hello_world")
88+
89+
def func():
90+
loop = asyncio.get_event_loop_policy().get_event_loop()
91+
loop.call_soon(hello)
92+
``
93+
[endsect]
94+
95+
[endsect]

0 commit comments

Comments
 (0)