Skip to content

Commit 3a07f26

Browse files
committed
clean up after introducing EventLoopPolicy
1 parent 5dd264e commit 3a07f26

2 files changed

Lines changed: 21 additions & 23 deletions

File tree

chess/engine.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ class StopAsyncIteration(Exception):
7777

7878
class EventLoopPolicy(asyncio.DefaultEventLoopPolicy):
7979
"""
80-
Creates and sets up a new asyncio event loop that is capable of spawning
81-
and watching subprocesses.
80+
An event loop policy that ensures the event loop is capable of spawning
81+
and watching subprocesses, even when not running in the main thread.
8282
83-
Unix: Uses relatively slow polling to watch child processes, when not
84-
running on the main thread. This only affects detection of process
85-
termination, not communication.
83+
Unix: Child watchers are thread local. Uses relatively slow polling to
84+
watch child processes, when not running on the main thread. This only
85+
affects detection of process termination, not communication.
8686
"""
8787
class _ThreadLocal(threading.local):
8888
_watcher = None
@@ -128,42 +128,40 @@ def _poll(self):
128128
def set_child_watcher(self, watcher):
129129
if sys.platform == "win32" or threading.current_thread() == threading.main_thread():
130130
return super().set_child_watcher(watcher)
131-
else:
132-
assert watcher is None or isinstance(watcher, asyncio.AbstractChildWatcher)
133131

134-
if self._thread_local._watcher:
135-
self._thread_local._watcher.close()
136-
self._thread_local._watcher = watcher
132+
assert watcher is None or isinstance(watcher, asyncio.AbstractChildWatcher)
133+
134+
if self._thread_local._watcher:
135+
self._thread_local._watcher.close()
136+
self._thread_local._watcher = watcher
137137

138138
def new_event_loop(self):
139139
return asyncio.ProactorEventLoop() if sys.platform == "win32" else asyncio.SelectorEventLoop()
140140

141-
def get_event_loop(self):
142-
print("GET EVENT LOOP")
143-
return super().get_event_loop()
144-
145141
def set_event_loop(self, loop):
146-
print("SET EVENT LOOP", threading.current_thread())
147142
super().set_event_loop(loop)
148143

149144
if sys.platform != "win32" and threading.current_thread() != threading.main_thread():
150-
print("ATTACHING EVENT LOOP")
151145
self.get_child_watcher().attach_loop(loop)
152146

153147

154-
def run_in_background(coroutine):
148+
def run_in_background(coroutine, _policy_lock=threading.Lock()):
155149
"""
156150
Runs ``coroutine(future)`` in a new event loop on a background thread.
157151
158152
Blocks and returns the *future* result as soon as it is resolved.
159153
The coroutine and all remaining tasks continue running in the background
160154
until it is complete.
155+
156+
Note: This installs an event loop policy for the entire process.
161157
"""
162158
assert asyncio.iscoroutinefunction(coroutine)
163159

164160
future = concurrent.futures.Future()
165161

166-
asyncio.set_event_loop_policy(EventLoopPolicy())
162+
with _policy_lock:
163+
if not isinstance(asyncio.get_event_loop_policy(), EventLoopPolicy):
164+
asyncio.set_event_loop_policy(EventLoopPolicy())
167165

168166
def background():
169167
loop = asyncio.new_event_loop()

docs/engine.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Example: Let Stockfish play against itself, 100 milliseconds per move.
5656
5757
await engine.quit()
5858
59-
chess.engine.setup_event_loop()
59+
asyncio.set_event_loop_policy(chess.engine.EventLoopPolicy())
6060
asyncio.run(main())
6161
6262
.. autoclass:: chess.engine.EngineProtocol
@@ -166,7 +166,7 @@ Example:
166166
167167
await engine.quit()
168168
169-
chess.engine.setup_event_loop()
169+
asyncio.set_event_loop_policy(chess.engine.EventLoopPolicy())
170170
asyncio.run(main())
171171
172172
.. autoclass:: chess.engine.EngineProtocol
@@ -216,7 +216,7 @@ Example: Stream information from the engine and stop on an arbitrary condition.
216216
217217
await engine.quit()
218218
219-
chess.engine.setup_event_loop()
219+
asyncio.set_event_loop_policy(chess.engine.EventLoopPolicy())
220220
asyncio.run(main())
221221
222222
.. autoclass:: chess.engine.EngineProtocol
@@ -269,7 +269,7 @@ Option(name='Hash', type='spin', default=16, min=1, max=131072, var=[])
269269
# Set an option.
270270
await engine.configure({"Hash": 32})
271271
272-
chess.engine.setup_event_loop()
272+
asyncio.set_event_loop_policy(chess.engine.EventLoopPolicy())
273273
asyncio.run(main())
274274
275275
.. autoclass:: chess.engine.EngineProtocol
@@ -362,4 +362,4 @@ Reference
362362
.. autoclass:: chess.engine.SimpleAnalysisResult
363363
:members:
364364

365-
.. autofunction:: chess.engine.setup_event_loop
365+
.. autofunction:: chess.engine.EventLoopPolicy

0 commit comments

Comments
 (0)