iLOVE2D's picture
Upload 2846 files
5374a2d verified
import threading
from functools import wraps
from contextlib import nullcontext
def atomic(lock=None):
"""
threading safe decorator, it can be used to decorate a function or receive a lock:
1. directly decorate a function: @atomic
2. receive a lock: @atomic(lock=shared_lock)
"""
lock = lock or threading.Lock()
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
with lock:
return func(*args, **kwargs)
return wrapper
return decorator if not callable(lock) else decorator(lock)
def atomic_method(func):
"""
threading safe decorator for class methods.
If there are self._lock in the instance, it will use the lock. Otherwise, use nullcontext for execution.
"""
@wraps(func)
def wrapper(self, *args, **kwargs):
context = getattr(self, "_lock", nullcontext())
with context:
return func(self, *args, **kwargs)
return wrapper