Skip to content

Instantly share code, notes, and snippets.

@vcokltfre
Last active January 15, 2024 16:28
Show Gist options
  • Save vcokltfre/38c484fb4000836536e77ce806c27b6b to your computer and use it in GitHub Desktop.
Save vcokltfre/38c484fb4000836536e77ce806c27b6b to your computer and use it in GitHub Desktop.
from asyncio import Lock
from typing import Callable, Coroutine, ParamSpec, TypeVar, cast, overload
_locks: dict[str, Lock] = {}
P = ParamSpec("P")
T = TypeVar("T")
@overload
def synchronised(name: str) -> Callable[[Callable[P, Coroutine[None, None, T]]], Callable[P, Coroutine[None, None, T]]]:
...
@overload
def synchronised(name: Callable[P, Coroutine[None, None, T]]) -> Callable[P, Coroutine[None, None, T]]:
...
def synchronised(
name: str | Callable[P, Coroutine[None, None, T]]
) -> Callable[[Callable[P, Coroutine[None, None, T]]], Callable[P, Coroutine[None, None, T]]] | Callable[P, Coroutine[None, None, T]]:
if isinstance(name, str):
def inner(func: Callable[P, Coroutine[None, None, T]]) -> Callable[P, Coroutine[None, None, T]]:
nonlocal name
name = cast(str, name)
_locks[name] = Lock()
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
nonlocal name
name = cast(str, name)
await _locks[name].acquire()
value = await func(*args, **kwargs)
_locks[name].release()
return value
return wrapper
return inner
func = name
name = name.__name__
name = name or func.__name__
_locks[name] = Lock()
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
nonlocal name
name = cast(str, name)
await _locks[name].acquire()
value = await func(*args, **kwargs)
_locks[name].release()
return value
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment