Fifolock
Fifolock is a Python library providing flexible, low-level synchronization primitives for `asyncio` applications. It implements first-in-first-out (FIFO) ordered locks, ensuring requests are granted strictly in the order they are made. The current version is 0.0.20. The project appears to have an infrequent release cadence, with the last significant activity several years ago.
Common errors
-
My asyncio.Lock doesn't seem to respect the order of acquisition; some tasks get the lock before others that requested it earlier.
cause Standard `asyncio.Lock` prior to Python 3.10 did not guarantee FIFO acquisition order. Even with fairness guarantees in newer Python, specific scenarios might require the explicit FIFO offered by `FifoLock`.fixIf strict FIFO ordering is a critical requirement, `FifoLock` is designed for this. Replace `asyncio.Lock` with `fifolock.FifoLock` and define appropriate `asyncio.Future` subclasses as lock modes. -
My application deadlocks when using a Read/Write lock built with FifoLock, or I get `RuntimeError: release unlocked lock`.
cause Improper implementation of the `is_compatible` method for your custom lock modes or incorrect usage of the `async with` statement leading to unintended lock states. This is especially common with multiple interacting lock types (e.g., Read and Write).fixCarefully review the `is_compatible` logic for each of your lock 'modes'. Ensure that the conditions for compatibility (what other locks can be held simultaneously) are correctly defined. Verify that `async with lock(Mode)` blocks are properly exited.
Warnings
- gotcha FifoLock is explicitly designed to be non-reentrant. Attempting to acquire a lock a second time from within the same coroutine that already holds it will result in a deadlock or unexpected behavior.
- gotcha Configurable lock 'modes' (like a semaphore) require dynamic class creation. This pattern, where a new class is defined at runtime, can be unusual for Python developers and might feel less intuitive than instance-based configuration.
- gotcha FifoLock, like most `asyncio` primitives, is not thread-safe. It should not be used for synchronizing OS threads; use primitives from Python's `threading` module for that purpose.
- deprecated The project has not seen significant updates in several years (last commit 7 years ago). While functional, it might not fully leverage or be optimized for newer features and changes in Python's `asyncio` module since its last release (e.g., changes introduced in Python 3.10+).
Install
-
pip install fifolock
Imports
- FifoLock
import fifolock
from fifolock import FifoLock
Quickstart
import asyncio
from fifolock import FifoLock
class Mutex(asyncio.Future):
@staticmethod
def is_compatible(holds):
return not holds[Mutex]
lock = FifoLock()
async def access_resource(task_id):
print(f"Task {task_id}: Requesting lock")
async with lock(Mutex):
print(f"Task {task_id}: Lock acquired, accessing resource...")
await asyncio.sleep(0.1) # Simulate work
print(f"Task {task_id}: Resource released.")
async def main():
tasks = [access_resource(i) for i in range(5)]
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())