mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-128340: add thread safe handle for loop.call_soon_threadsafe
(#128369)
Adds `_ThreadSafeHandle` to be used for callbacks scheduled with `loop.call_soon_threadsafe`.
This commit is contained in:
parent
657d7b77e5
commit
7e8c571604
4 changed files with 151 additions and 1 deletions
|
@ -113,6 +113,34 @@ class Handle:
|
|||
self._loop.call_exception_handler(context)
|
||||
self = None # Needed to break cycles when an exception occurs.
|
||||
|
||||
# _ThreadSafeHandle is used for callbacks scheduled with call_soon_threadsafe
|
||||
# and is thread safe unlike Handle which is not thread safe.
|
||||
class _ThreadSafeHandle(Handle):
|
||||
|
||||
__slots__ = ('_lock',)
|
||||
|
||||
def __init__(self, callback, args, loop, context=None):
|
||||
super().__init__(callback, args, loop, context)
|
||||
self._lock = threading.RLock()
|
||||
|
||||
def cancel(self):
|
||||
with self._lock:
|
||||
return super().cancel()
|
||||
|
||||
def cancelled(self):
|
||||
with self._lock:
|
||||
return super().cancelled()
|
||||
|
||||
def _run(self):
|
||||
# The event loop checks for cancellation without holding the lock
|
||||
# It is possible that the handle is cancelled after the check
|
||||
# but before the callback is called so check it again after acquiring
|
||||
# the lock and return without calling the callback if it is cancelled.
|
||||
with self._lock:
|
||||
if self._cancelled:
|
||||
return
|
||||
return super()._run()
|
||||
|
||||
|
||||
class TimerHandle(Handle):
|
||||
"""Object returned by timed callback registration methods."""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue