Skip to content

0.2.0

Choose a tag to compare

@x42005e1f x42005e1f released this 13 Sep 04:09
95ab3c3

Added

  • eventlet and gevent support.
  • aiologic.PLock as a primitive lock, i.e. the fastest exclusive lock that does not do checks in release() methods.
  • aiologic.REvent as a reusable event, i.e. an event that supports the clear() method (async-aware alternative to threading.Event).
  • aiologic.ResourceGuard for ensuring that a resource is only used by a single task at a time (thread-safe alternative to anyio.ResourceGuard).
  • release() method to aiologic.Semaphore and aiologic.BoundedSemaphore.
  • max_value parameter to aiologic.Semaphore to allow creating an instance of aiologic.BoundedSemaphore without importing it.
  • waiting property to all primitives that returns the length of waiting queue (number of waiting threads and tasks).
  • Non-blocking (non-waiting) mode for asynchronous lock acquiring methods. In this mode, it is guaranteed that there is no context switching even with checkpoints enabled (they are ignored). Unlike synchronous methods, lock acquiring is done on behalf of an asynchronous task. It is enabled by passing blocking=False.
  • The ability to specify the library used via environment variables, local thread fields, context variables.
  • Patch for the threading module that fixes the race in Thread.join() on PyPy. Automatically applied when creating an instance of the threading event.
  • Patch for the eventlet module that adds the necessary methods to support it. Automatically applied when creating an instance of eventlet event.
  • Optional dependencies to guarantee support for third-party libraries (by specifying the minimum supported version).

Changed

  • Checkpoints are now optional. They can be enabled or disabled via environment variables or context variables. They are enabled by default for Trio.
  • _as_thread and _as_task suffixes are replaced by green_ and async_ prefixes. Other options were considered, but only such prefixes ensure that the two different APIs are equal in convenience.
  • aiologic.Lock and aiologic.RLock no longer support upgrading from synchronous to asynchronous access, which avoids some issues in complex scenarios.
  • put() and aput() methods in aiologic.SimpleQueue are replaced by the common put() method (without blocking and timeout parameters).
  • aiologic.SimpleQueue now throws its own aiologic.QueueEmpty exception instead of queue.Empty.
  • aiologic.lowlevel.ThreadEvent is renamed to aiologic.lowlevel.GreenEvent and aiologic.lowlevel.TaskEvent is renamed to aiologic.lowlevel.AsyncEvent.
  • set() method of low-level events now returns bool: True if called for the first time, False otherwise.
  • Identification functions are changed due to support for new libraries. aiologic.lowlevel.current_thread() now returns a threading.Thread instance instead of its identifier, and a new function aiologic.lowlevel.current_thread_ident() has been added to get the identifier instead. The old aiologic.lowlevel.current_token() and aiologic.lowlevel.current_task() are now differentiated by library type (current_green_ and current_async_). Additional functions with the _ident suffix have also been added to get an identifier instead of an object.

Removed

  • aiologic.ParkingLot: now each primitive uses its own lightweight code to handle the waiting queue.
  • aiologic.lowlevel.AsyncioEvent and aiologic.lowlevel.TrioEvent: they are now private.
  • aiologic.lowlevel.Flags.markers: it is now private.

Fixed

  • In very rare cases, notification methods (notify(), release(), and so on) did not notify newcomers due to a race, causing a hang. Now they are fully thread-safe.
  • aiologic.Condition now uses timestamps for wakeups, which provides expected behavior in complex scenarios (and eliminates resource starvation). The same is implemented in aiologic.REvent.
  • The threading event now calls lock.acquire(blocking=False) instead of lock.acquire(timeout=timeout) on a negative timeout, which is consistent with the behavior of threading.Event.
  • The default_factory() call in aiologic.lowlevel.Flag.get() is now performed outside the except block, which simplifies stack traces.
  • Eager imports are replaced by lazy imports, so that only necessary ones are imported at runtime. This avoids some issues related to incompatibility of library versions.