An open API service indexing awesome lists of open source software.

https://github.com/x42005e1f/aiologic

GIL-powered* locking library for Python
https://github.com/x42005e1f/aiologic

anyio async async-await asyncio concurrency eventlet gevent greenlet library locking mypy python synchronization thread-safety threading trio

Last synced: 6 days ago
JSON representation

GIL-powered* locking library for Python

Awesome Lists containing this project

README

        

..
SPDX-FileCopyrightText: 2024 Ilya Egorov <[email protected]>
SPDX-License-Identifier: CC-BY-4.0

.. role:: mod(literal)
.. role:: func(literal)
.. role:: data(literal)
.. role:: const(literal)
.. role:: class(literal)
.. role:: meth(literal)
.. role:: attr(literal)
.. role:: type(literal)
.. role:: exc(literal)
.. role:: obj(literal)

========
aiologic
========

.. badges-start-marker

|pypi-dw| |pypi-impl| |pypi-pyv| |pypi-types|

.. |pypi-dw| image:: https://img.shields.io/pypi/dw/aiologic
:target: https://pypistats.org/packages/aiologic
:alt:
.. |pypi-impl| image:: https://img.shields.io/pypi/implementation/aiologic
:target: #features
:alt:
.. |pypi-pyv| image:: https://img.shields.io/pypi/pyversions/aiologic
:target: #features
:alt:
.. |pypi-types| image:: https://img.shields.io/pypi/types/aiologic
:target: #features
:alt:

.. badges-end-marker

.. description-start-marker

**aiologic** is a locking library for tasks synchronization and their
communication. It provides primitives that are both *async-aware* and
*thread-aware*, and can be used for interaction between:

- async codes (async <-> async) in one thread as regular async primitives
- async codes (async <-> async) in multiple threads (!)
- async code and sync one (async <-> sync) in one thread (!)
- async code and sync one (async <-> sync) in multiple threads (!)
- sync codes (sync <-> sync) in one thread as regular sync primitives
- sync codes (sync <-> sync) in multiple threads as regular sync primitives

Let's take a look at the example:

.. code:: python

import asyncio

from threading import Thread

import aiologic

lock = aiologic.Lock()

async def func(i: int, j: int) -> None:
print(f"thread={i} task={j} start")

async with lock:
await asyncio.sleep(1)

print(f"thread={i} task={j} end")

async def main(i: int) -> None:
await asyncio.gather(func(i, 0), func(i, 1))

Thread(target=asyncio.run, args=[main(0)]).start()
Thread(target=asyncio.run, args=[main(1)]).start()

It prints something like this:

.. code-block::

thread=0 task=0 start
thread=1 task=0 start
thread=0 task=1 start
thread=1 task=1 start
thread=0 task=0 end
thread=1 task=0 end
thread=0 task=1 end
thread=1 task=1 end

As you can see, tasks from different event loops are all able to acquire
:class:`aiologic.Lock`. In the same case if you use :class:`asyncio.Lock`, it
will raise a :exc:`RuntimeError`. And :class:`threading.Lock` will cause a
deadlock.

.. description-end-marker

Features
========

.. features-start-marker

* Python 3.8+ support
* `CPython `_ and `PyPy `_ support
* `Pickling `_ and `weakrefing
`_ support
* Cancellation and timeouts support
* Optional `Trio-style checkpoints `_:

* enabled by default for Trio itself
* disabled by default for all others

* Only one checkpoint per asynchronous call:

* exactly one context switch if checkpoints are enabled
* zero or one context switch if checkpoints are disabled

* Fairness wherever possible (with some caveats)
* Thread-safety wherever possible
* Lock-free implementation
* Bundled stub files

Synchronization primitives:

* Flags
* Events: one-time, reusable, and countdown
* Barriers: single-use, and cyclic
* Semaphores: counting, and bounded
* Capacity limiters: borrowable, and reentrant
* Locks: primitive, bounded, ownable, and reentrant
* `Readers-writer locks (external) `_
* Condition variables
* Resource guards

Communication primitives:

* Queues: FIFO, LIFO, and priority

Supported concurrency libraries:

* `asyncio `_, `curio `_, `trio `_, and `anyio
`_ (coroutine-based)
* `eventlet `_, and `gevent `_ (greenlet-based)
* `threading `_
(thread-based)

All synchronization and communication primitives are implemented entirely on
effectively atomic operations, which gives `an incredible speedup on PyPy
`_ compared
to alternatives from the :mod:`threading` module. All this works because of
GIL, but per-object locks also ensure that `the same operations are still
atomic `_, so
aiologic also works when running in a `free-threaded mode `_.

.. features-end-marker

Installation
============

.. installation-start-marker

Install from `PyPI `_ (recommended):

.. code:: console

pip install aiologic

Or from `Anaconda `_ (stable):

.. code:: console

conda install conda-forge::aiologic

Or from `GitHub `_ (latest):

.. code:: console

pip install git+https://github.com/x42005e1f/aiologic.git

You can also use other package managers, such as `mamba `_ or `uv `_.

.. installation-end-marker

Documentation
=============

Read the Docs: https://aiologic.readthedocs.io (official)

DeepWiki: https://deepwiki.com/x42005e1f/aiologic (AI generated)

Communication channels
======================

GitHub Discussions: https://github.com/x42005e1f/aiologic/discussions

Feel free to post your questions and ideas here.

Support
=======

If you like aiologic and want to support its development, star `its repository
on GitHub `_.

.. image:: https://starchart.cc/x42005e1f/aiologic.svg?variant=adaptive
:target: https://starchart.cc/x42005e1f/aiologic

License
=======

.. license-start-marker

The aiologic library is `REUSE-compliant `_ and is offered under multiple licenses:

* All original source code is licensed under `ISC `_.
* All original test code is licensed under `0BSD `_.
* All documentation is licensed under `CC-BY-4.0 `_.
* All configuration is licensed under `CC0-1.0 `_.

For more accurate information, check the individual files.

.. license-end-marker