Skip to content

Commit 1bf7680

Browse files
committed
chore: more optimizations for async Lock
1 parent c2d3681 commit 1bf7680

File tree

1 file changed

+26
-33
lines changed

1 file changed

+26
-33
lines changed

robotcode/utils/async_tools.py

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,7 @@ class Lock:
422422

423423
def __init__(self) -> None:
424424
self._waiters: Optional[Deque[asyncio.Future[Any]]] = None
425-
self._locked = False
426-
self._lock = threading.RLock()
425+
self._locked = [False] # make locked atomic according to GIL
427426
self._locker: Optional[asyncio.Task[Any]] = None
428427

429428
async def __aenter__(self) -> None:
@@ -443,20 +442,23 @@ def __repr__(self) -> str:
443442

444443
@property
445444
def locked(self) -> bool:
446-
return self._locked
445+
return self._locked[0]
446+
447+
def _set_locked(self, value: bool) -> None:
448+
self._locked[0] = value
449+
self._locker = asyncio.current_task() if value else None
447450

448451
async def acquire(self) -> bool:
449-
with self._lock:
450-
if not self._locked and (self._waiters is None or all(w.cancelled() for w in self._waiters)):
451-
self._locked = True
452-
self._locker = asyncio.current_task()
453-
return True
452+
if not self.locked and (self._waiters is None or all(w.cancelled() for w in self._waiters)):
453+
self._set_locked(True)
454+
455+
return True
454456

455-
if self._waiters is None:
456-
self._waiters = deque()
457+
if self._waiters is None:
458+
self._waiters = deque()
457459

458-
fut = create_sub_future()
459-
self._waiters.append(fut)
460+
fut = create_sub_future()
461+
self._waiters.append(fut)
460462

461463
try:
462464
try:
@@ -471,39 +473,31 @@ def aaa(fut: asyncio.Future[Any]) -> None:
471473
finally:
472474
h.cancel()
473475
finally:
474-
with self._lock:
475-
self._waiters.remove(fut)
476+
self._waiters.remove(fut)
476477
except asyncio.CancelledError:
477-
if not self._locked:
478+
if not self.locked:
478479
self._wake_up_first()
479480
raise
480481

481-
with self._lock:
482-
self._locked = True
483-
self._locker = asyncio.current_task()
482+
self._set_locked(True)
484483

485484
return True
486485

487486
def release(self) -> None:
488-
with self._lock:
489-
wake_up = False
490-
if self._locked:
491-
self._locked = False
492-
self._locker = None
493-
wake_up = True
494-
495-
if wake_up:
487+
if self.locked:
488+
self._set_locked(False)
496489
self._wake_up_first()
490+
else:
491+
raise RuntimeError("Lock is not acquired.")
497492

498493
def _wake_up_first(self) -> None:
499494
if not self._waiters:
500495
return
501496

502-
with self._lock:
503-
try:
504-
fut = next(iter(self._waiters))
505-
except StopIteration:
506-
return
497+
try:
498+
fut = next(iter(self._waiters))
499+
except StopIteration:
500+
return
507501

508502
if fut.get_loop().is_running() and not fut.get_loop().is_closed():
509503
if fut.get_loop() == asyncio.get_running_loop():
@@ -532,8 +526,7 @@ def set_result(w: asyncio.Future[Any], ev: threading.Event) -> None:
532526
time.sleep(0.001)
533527
else:
534528
warnings.warn(f"Future {repr(fut)} loop is closed")
535-
with self._lock:
536-
self._waiters.remove(fut)
529+
self._waiters.remove(fut)
537530
self._wake_up_first()
538531

539532

0 commit comments

Comments
 (0)