Skip to content

Instantly share code, notes, and snippets.

@NiklasRosenstein
Last active December 28, 2017 20:40
Show Gist options
  • Save NiklasRosenstein/e8b494a4d79519d74751f2c4cc79923d to your computer and use it in GitHub Desktop.
Save NiklasRosenstein/e8b494a4d79519d74751f2c4cc79923d to your computer and use it in GitHub Desktop.
This is just hacked together real quick, not 100% production proven.
import asyncio
class RLock(asyncio.Lock):
"""
A reentrant lock for Python coroutines.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._task = None
self._depth = 0
@asyncio.coroutine
def acquire(self):
if self._task is None or self._task != asyncio.Task.current_task():
yield from super().acquire()
self._task = asyncio.Task.current_task()
assert self._depth == 0
self._depth += 1
def release(self):
if self._depth > 0:
self._depth -= 1
if self._depth == 0:
super().release()
self._task = None
@NiklasRosenstein
Copy link
Author

I'm not sure why, but we need to use the @coroutine decorator for RLock.acquire() instead of the async keyword, as otherwise we'll get this error when using with await lock:

rc/player.py", line 323, in queue_song
    with await self.lock:
  File "/usr/lib/python3.5/asyncio/locks.py", line 74, in __await__
    yield from self.acquire()
TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment