Skip to content

Instantly share code, notes, and snippets.

Trio event loop notes

Event loop steps

These are the steps of the Trio event loop:

  1. Compute timeout (0 if still tasks in runq i.e. the list of tasks ready to resume, else clock.deadline_to_sleep_time(deadlines.next_deadline()))
  2. Wait for IO events or timeout (events = io_manager.get_events(timeout)) – this is the actual select()-like call.
  3. Events are "processed" i.e. scheduled into the relevant task (io_manager.process_events(events) which calls _core.reschedule(self._registered[key], outcome.Value(event)) i.e. added to runq)
  4. Deadlines are expired (deadlines.expire(clock.current_time()), which effectively calls task.reschedule(Cancelled) (via the task's abort function) i.e. adds the task to the runq)
@arthur-tacca
arthur-tacca / trio_event_cancel_idea.py
Created August 26, 2026 15:11
Trio Event and memory channel where cancellation always succeeds
"""Implementation of Trio event and chnanel types where cancellation always succeeds.
See: https://github.com/python-trio/trio/issues/2973
"""
import attr
from collections import deque
import trio
from typing import Generic, Optional, TypeVar
@arthur-tacca
arthur-tacca / abort.dart
Last active April 9, 2026 13:31
Proof of concept for Dart cancel token class
// Moved to:
// https://github.com/arthur-tacca/dart-cancel-examples/blob/main/lib/abort.dart
@arthur-tacca
arthur-tacca / dart_cancel_tokens.md
Last active August 16, 2026 13:39
Proposal to Add Cancellation Tokens to Dart
@arthur-tacca
arthur-tacca / taskgroups.py
Last active March 21, 2024 15:56
Possible modifications to asyncio.TaskGroup class
# Adapted with permission from the EdgeDB project;
# license: PSFL.
__all__ = ("TaskGroup",)
from . import events
from . import exceptions
from . import tasks
@arthur-tacca
arthur-tacca / trio_cancel_race.py
Created March 14, 2024 12:30
Demo of trio task waking without exception from `await trio.something()` despite being in a recently-cancelled cancel scope
# Question: if we cancel a scope, and another task is active in that scope, is it *guaranteed* that
# it will raise CancelledError when it next wakes? (Even if it is already queued to wake for some
# other reason.)
#
# The answer, at least in practice, is no: in this example, send_and_cancel() sends some data to
# a memory channel then cancels a scope, and then receive() (which is running in that scope) wakes
# with the first value that was sent.
#
# On my computer, this code produces the following output:
#
@arthur-tacca
arthur-tacca / asyncio_taskgroup_missed_cleanup.py
Created March 3, 2024 19:32
Illustration of missed cleanup in an asyncio task group
# Illustration of missed cleanup in an asyncio task group due to the way it
# cancels a task that has not started by never running it at all. See issue:
# https://github.com/python/cpython/issues/116048
#
# When run on my computer, I usually get the output:
#
# Total connections created: 3300
# Connections left unclosed: 0
#
# i.e., all connections that were created were cleaned up. But sometimes I get:
@arthur-tacca
arthur-tacca / stream_results_nursery.py
Last active March 23, 2024 10:41
Results-gathering nursery wrapper, using aioresult.ResultCapture for the results
# aioresult variant of StreamResultsNursery
# Original idea by smurfix: https://gist.github.com/smurfix/0130817fa5ba6d3bb4a0f00e4d93cf86
# Fixed non-aioresult version: https://gist.github.com/arthur-tacca/6c676a21d0dcc0582edb50c9c2aa3e3c
from collections import deque
import math
from aioresult import ResultCapture
import trio
@arthur-tacca
arthur-tacca / wrap.py
Last active February 14, 2024 17:08 — forked from m-u-xyz/wrap.py
Trio: results-gathering nursery wrapper
# Original idea by smurfix: https://gist.github.com/smurfix/0130817fa5ba6d3bb4a0f00e4d93cf86
# aioresult variant: https://gist.github.com/arthur-tacca/5c717ae68ac037e72ae45fd1e9ca1345
from collections import deque
import math
import trio
class StreamResultsNursery:
def __init__(self, max_running_tasks=math.inf):
@arthur-tacca
arthur-tacca / trio_result_capture.py
Last active February 12, 2024 13:31
ResultCapture class for Trio - now adapted into aioresult: https://github.com/arthur-tacca/aioresult
#
# -- An improved version of this code is now in the aioresult library --
#
# https://github.com/arthur-tacca/aioresult
#
#
# - aioresult has a ResultCapture class similar to the one below
# - It also has a Future class that allows manually setting the result, which shares a base class with ResultCapture
# - There is a utility function with a similar effect to StartableResultCapture below (but much simpler)
# - There are utility functions wait_any(), wait_all() and to_channel() (which also work with Future instances)