{"id":8989,"library":"fifolock","title":"Fifolock","description":"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.","status":"active","version":"0.0.20","language":"en","source_language":"en","source_url":"https://github.com/michalc/fifolock","tags":["asyncio","lock","fifo","synchronization","concurrency","async","python3"],"install":[{"cmd":"pip install fifolock","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"The primary lock class `FifoLock` must be imported directly from the package, not via a top-level package import.","wrong":"import fifolock","symbol":"FifoLock","correct":"from fifolock import FifoLock"}],"quickstart":{"code":"import asyncio\nfrom fifolock import FifoLock\n\nclass Mutex(asyncio.Future):\n    @staticmethod\n    def is_compatible(holds):\n        return not holds[Mutex]\n\nlock = FifoLock()\n\nasync def access_resource(task_id):\n    print(f\"Task {task_id}: Requesting lock\")\n    async with lock(Mutex):\n        print(f\"Task {task_id}: Lock acquired, accessing resource...\")\n        await asyncio.sleep(0.1) # Simulate work\n        print(f\"Task {task_id}: Resource released.\")\n\nasync def main():\n    tasks = [access_resource(i) for i in range(5)]\n    await asyncio.gather(*tasks)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())","lang":"python","description":"This quickstart demonstrates a basic mutex using `FifoLock`. By defining a `Mutex` class that inherits from `asyncio.Future` and implementing `is_compatible`, you create a lock 'mode'. The `async with lock(Mutex):` statement ensures that only one coroutine can hold the mutex at a time, with acquisition in FIFO order."},"warnings":[{"fix":"Ensure your code logic does not attempt reentrant locking. If reentrancy is required, `FifoLock` is not the appropriate primitive.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Familiarize yourself with the 'Recipes' section of the GitHub README to understand how to define custom lock types (subclasses of `asyncio.Future`) and their `is_compatible` methods.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Only use `FifoLock` within a single `asyncio` event loop for coroutine synchronization. For inter-thread communication, consider `threading.Lock` or `Queue.Queue`.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Test thoroughly with your target Python and `asyncio` versions. Consider `asyncio.Lock` if FIFO is not strictly required, as it gained fairness guarantees in Python 3.10 and is actively maintained.","message":"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+).","severity":"deprecated","affected_versions":"<=0.0.20 (potentially affects compatibility with Python 3.9+)"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"If 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.","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`.","error":"My asyncio.Lock doesn't seem to respect the order of acquisition; some tasks get the lock before others that requested it earlier."},{"fix":"Carefully 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.","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).","error":"My application deadlocks when using a Read/Write lock built with FifoLock, or I get `RuntimeError: release unlocked lock`."}]}