Skip to content

Instantly share code, notes, and snippets.

@mosquito
Created April 18, 2022 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mosquito/23b0fa53baad913aa1ce954976ecb671 to your computer and use it in GitHub Desktop.
Save mosquito/23b0fa53baad913aa1ce954976ecb671 to your computer and use it in GitHub Desktop.
RLock for asyncio
from typing import Any
import asyncio
class RLock(asyncio.Lock):
""" RLock like threading.RLock but use asyncio tasks as an ident """
def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self.loop = asyncio.get_event_loop()
self._owner: Optional[asyncio.Task] = None
self._count: int = 0
def __get_ident(self) -> int:
return id(asyncio.current_task(self.loop))
async def acquire(self) -> bool:
me = self.__get_ident()
if self._owner == me:
self._count += 1
return True
await super().acquire()
self._owner = me
self._count = 1
return True
def release(self) -> None:
me = self.__get_ident()
if self._owner != me:
raise RuntimeError("cannot release un-acquired lock")
self._count = count = self._count - 1
if not count:
self._owner = None
super().release()
if __name__ == "__main__":
async def test():
lock = RLock()
x = 1
async with lock:
x += 1
async with lock:
x += 1
assert x == 3
asyncio.run(test())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment