Skip to content

Commit 7996d64

Browse files
committed
add some docstrings to SelectorThread methods
based on confusion in feedback
1 parent 8c76be9 commit 7996d64

File tree

1 file changed

+28
-4
lines changed

1 file changed

+28
-4
lines changed

Lib/asyncio/_selector_thread.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
Compatibility for [add|remove]_[reader|writer] where unavailable (Proactor).
77
88
Runs select in a background thread.
9+
_Only_ `select.select` is called in the background thread.
10+
11+
Callbacks are all handled back in the event loop's thread,
12+
as scheduled by `loop.call_soon_threadsafe`.
913
1014
Adapted from Tornado 6.5.2
1115
"""
@@ -61,10 +65,8 @@ class SelectorThread:
6165
6266
Instances of this class start a second thread to run a selector.
6367
This thread is completely hidden from the user;
64-
all callbacks are run on the wrapped event loop's thread.
65-
66-
Typically used via ``AddThreadSelectorEventLoop``,
67-
but can be attached to a running asyncio loop.
68+
all callbacks are run on the wrapped event loop's thread
69+
via :meth:`loop.call_soon_threadsafe`.
6870
"""
6971

7072
_closed = False
@@ -140,6 +142,7 @@ async def _thread_manager(self) -> typing.AsyncGenerator[None, None]:
140142
raise
141143

142144
def _wake_selector(self) -> None:
145+
"""Wake the selector thread from another thread."""
143146
if self._closed:
144147
return
145148
try:
@@ -148,12 +151,18 @@ def _wake_selector(self) -> None:
148151
pass
149152

150153
def _consume_waker(self) -> None:
154+
"""Consume messages sent via _wake_selector."""
151155
try:
152156
self._waker_r.recv(1024)
153157
except BlockingIOError:
154158
pass
155159

156160
def _start_select(self) -> None:
161+
"""Start select waiting for events.
162+
163+
Called from the event loop thread,
164+
schedules select to be called in the background thread.
165+
"""
157166
# Capture reader and writer sets here in the event loop
158167
# thread to avoid any problems with concurrent
159168
# modification while the select loop uses them.
@@ -163,6 +172,12 @@ def _start_select(self) -> None:
163172
self._select_cond.notify()
164173

165174
def _run_select(self) -> None:
175+
"""The main function of the select thread.
176+
177+
Runs `select.select()` until `_closing_selector` attribute is set (typically by `close()`).
178+
Schedules handling of `select.select` output on the main thread
179+
via `loop.call_soon_threadsafe()`.
180+
"""
166181
while not self._closing_selector:
167182
with self._select_cond:
168183
while self._select_args is None and not self._closing_selector:
@@ -223,6 +238,10 @@ def _run_select(self) -> None:
223238
def _handle_select(
224239
self, rs: list[_FileDescriptorLike], ws: list[_FileDescriptorLike]
225240
) -> None:
241+
"""Handle the result of select.select.
242+
243+
This method is called on the event loop thread via `call_soon_threadsafe`.
244+
"""
226245
for r in rs:
227246
self._handle_event(r, self._readers)
228247
for w in ws:
@@ -234,6 +253,11 @@ def _handle_event(
234253
fd: _FileDescriptorLike,
235254
cb_map: dict[int, tuple[_FileDescriptorLike, Callable]],
236255
) -> None:
256+
"""Handle one callback event.
257+
258+
This method is called on the event loop thread via `call_soon_threadsafe` (from `_handle_select`),
259+
so exception handler wrappers, etc. are applied.
260+
"""
237261
try:
238262
fileobj, callback = cb_map[fd]
239263
except KeyError:

0 commit comments

Comments
 (0)