| 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 |
|
|
|
|
|
|