Skip to main content

A multi-threaded async runtime

Project description

TonIO

TonIO is a multi-threaded async runtime for free-threaded Python, built in Rust on top of the mio crate, and inspired by tinyio and trio.

Warning: TonIO is currently a work in progress and very pre-alpha state. The APIs are subtle to breaking changes.

Note: TonIO is available on free-threaded Python and on Unix systems only.

In a nutshell

import tonio

def wait_and_add(x: int) -> int:
    yield tonio.sleep(1)
    return x + 1

def foo():
    four, five = yield tonio.spawn(wait_and_add(3), wait_and_add(4))
    return four, five

out = tonio.run(foo())
assert out == (4, 5)

Usage

Entrypoint

Every TonIO program consist of an entrypoint, which should be passed to the run method:

import tonio

def main():
    yield
    print("Hello world")

tonio.run(main())

TonIO also provides a main decorator, thus we can rewrite the previous example as:

import tonio

@tonio.main
def main():
    yield
    print("Hello world")

main()

Runtime options

Both run and main accept options, specifically:

option name description default
context enable contextvars usage in coroutines False
threads Number of runtime threads # of CPU cores
threads_blocking Maximum number of blocking threads 128
threads_blocking_timeout Idle timeout for blocking threads (in seconds) 30

Events

The core object in TonIO is Event. It's basically a wrapper around an atomic boolean flag, initialised with False. Event provides the following methods:

  • is_set(): return the value of the flag
  • set(): set the flag to True
  • clear(): set the flag to False
  • wait(timeout=None): returns a coroutine you can yield on that unblocks when the flag is set to True or the timeout expires. Timeout is seconds.
  • __call__(timeout=None): same of wait, but returns a coroutine you can await on.
import tonio

@tonio.main
def main():
    event = tonio.Event()

    def setter():
        yield tonio.sleep(1)
        event.set()

    tonio.spawn(setter())
    yield event.wait()

Spawning tasks

TonIO provides the spawn method to schedule new coroutines onto the runtime:

import tonio

def doubv(v):
    yield
    return v * 2

@tonio.main
def main():
    parallel = tonio.spawn(doubv(2), doubv(3))
    v3 = yield doubv(4)
    v1, v2 = yield parallel
    print([v1, v2, v3])

Coroutines passed to spawn get schedule onto the runtime immediately. Using yield on the return value of spawn just waits for the coroutines to complete and retreive the results.

Blocking tasks

TonIO provides the spawn_blocking method to schedule blocking operations onto the runtime:

import tonio

def read_file(path):
    with open(file, "r") as f:
        return f.read()

@tonio.main
def main():
    file_data = yield tonio.spawn_blocking(read_file, "sometext.txt")

Scopes and cancellations

TonIO provides a scope context, that lets you cancel work spawned within it:

import tonio

def slow_push(target, sleep):
    yield tonio.sleep(sleep)
    target.append(True)

@tonio.main
def main():
    values = []
    with tonio.scope() as scope:
        scope.spawn(_slow_push(values, 0.1))
        scope.spawn(_slow_push(values, 2))
        yield tonio.sleep(0.2)
        scope.cancel()
    yield scope()
    assert len(values) == 1

When you yield on the scope, it will wait for all the spawned coroutines to end. If the scope was canceled, then all the pending coroutines will be canceled.

Note: the colored version of scope, doesn't require to be awaited, as it will yield on exit.

Time-related functions

  • tonio.time.time(): a function returning the runtime's clock
  • tonio.time.sleep(delay): a coroutine you can yield on to sleep (delay is in seconds)
  • tonio.time.timeout(coro, timeout): a coroutine you can yield on returning a tuple (output, success). If the coroutine succeeds in the given time then the pair (output, True) is returned. Otherwise this will return (None, False).

Note: time.sleep is also exported to the main tonio module.

Synchronization primitives

Synchronization primitives are exposed in the tonio.sync module.

Lock

Implements a classic mutex, or a non-reentrant, single-owner lock for coroutines:

import tonio
import tonio.sync

@tonio.main
def main():
    # counter can't go above 1
    counter = 0

    def _count(lock):
        nonlocal counter
        with (yield lock()):
            counter += 1
            yield
            counter -= 1
    
    lock = tonio.sync.Lock()
    yield tonio.spawn(*[_count(lock) for _ in range(10)])

Semaphore

A semaphore for coroutines:

import tonio
import tonio.sync

@tonio.main
def main():
    # counter can't go above 2
    counter = 0

    def _count(lock):
        nonlocal counter
        with (yield lock()):
            counter += 1
            yield
            counter -= 1
    
    lock = tonio.sync.Semaphore(2)
    yield tonio.spawn(*[_count(lock) for _ in range(10)])

Barrier

A barrier for coroutines:

import tonio
import tonio.sync

@tonio.main
def main():
    barrier = tonio.sync.Barrier(3)
    count = 0

    def _start_at_3():
        nonlocal count
        count += 1
        i = yield barrier.wait()
        assert count == 3
        return i

    yield tonio.spawn(*[_start_at_3() for _ in range(3)])

Channels

Multi-producer multi-consumer channels for inter-coroutine communication.
The tonio.sync.channel module provides both a channel and unbounded constructors:

import tonio
import tonio.sync
import tonio.sync.channel as channel

def producer(sender, barrier, offset):
    for i in range(20):
        message = offset + 1
        yield sender.send(message)
    yield barrier.wait()

def consumer(receiver):
    while True:
        try:
            message = yield receiver.receive()
            print(message)
        except Exception:
            break

@tonio.main
def main():
    def close(sender, barrier):
        yield barrier.wait()
        sender.close()

    sender, receiver = channel.channel(2)
    barrier = tonio.sync.Barrier(3)
    yield tonio.spawn(*[
        producer(sender, barrier, 100),
        producer(sender, barrier, 200),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        close(sender, barrier),
    ])

Network module

Network primitives are exposed under the tonio.net module.

Low-level sockets

The tonio.net.socket module provides TonIO's basic low-level networking API.
Generally, the API exposed by this module mirrors the standard library socket module.

TonIO socket objects are overall very similar to the standard library socket objects, with the main difference being that blocking methods become coroutines.

import tonio
from toio.net import socket

def server():
    sock = socket.socket()
    with sock:
        yield sock.bind(('127.0.0.1', 8000))
        sock.listen()

        while True:
            client, _ = yield sock.accept()
            tonio.spawn(server_handle(client))

def server_handle(connection):
    with connection:
        # receive some data
        data = yield connection.recv(4096)

def client():
    sock = socket.socket()
    with sock:
        yield sock.connect(('127.0.0.1', 8000))
        yield sock.send("message")

Using async/await notation

All TonIO primitives ships with an async/await syntax compatible variant under the tonio.colored module.

Warning: despite the fact TonIO supports async and await notations, it's not compatible with any asyncio object like futures and tasks.

import tonio.colored as tonio

@tonio.main
async def main():
    event = tonio.Event()

    async def setter():
        await tonio.sleep(1)
        event.set()

    tonio.spawn(setter())
    await event()

The only major syntax difference between the yield and async/await notation is around with blocks:

from tonio.sync import Lock

lock = Lock()

def yield_lock():
    with (yield lock()):
        # do something

async def async_lock():
    async with lock:
        # do something

Also, the colored module provides the additional yield_now awaitable function, a quick way to define a suspension point:

import tonio.colored as tonio

@tonio.main
async def main():
    await tonio.yield_now()
    print("hello world")

License

TonIO is released under the BSD License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tonio-0.1.0a4.tar.gz (36.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_x86_64.whl (570.7 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ x86-64

tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_armv7l.whl (632.6 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_aarch64.whl (525.7 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (356.5 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (360.8 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARMv7l

tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (341.9 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

tonio-0.1.0a4-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (385.9 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

tonio-0.1.0a4-cp314-cp314t-macosx_11_0_arm64.whl (308.0 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

tonio-0.1.0a4-cp314-cp314t-macosx_10_12_x86_64.whl (329.2 kB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

File details

Details for the file tonio-0.1.0a4.tar.gz.

File metadata

  • Download URL: tonio-0.1.0a4.tar.gz
  • Upload date:
  • Size: 36.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tonio-0.1.0a4.tar.gz
Algorithm Hash digest
SHA256 2f6d4942758f73b01a9d2a10b28fa218ffc551ab4667177c340a72778246eb9e
MD5 736c235283204739dcc50c06e0d2ceda
BLAKE2b-256 3495af6edd4ae19f68017b1e21706c2455abb3f7ae3a3df520ab762db672179e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4.tar.gz:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 4e7292d88d5b11e2ac2bc615df1ff706dd83d30561a9f6cd597a40e760814cf6
MD5 597e6cf9a7d7b578f930c7922d549604
BLAKE2b-256 2cedb71e8e1b801cdd575f8662365036e9f7246415a81f1a79dee845080f652b

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 d883c4bb192298322f075c52db42440cbb12a29e2329277d264e96a9499acfb8
MD5 c5fe73a45ecf9c1f9f25c3c332f66e52
BLAKE2b-256 abf6921381cb282199e0e1ff09e743487480cd53d7aa9a2237bf8ebd57e3e5eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 fe1bde444c67f82f2dae5cc69eb1472dc123bbf8f3337a88e9ca8e652cedded8
MD5 7585fd84127d0b9d84ac0800627ae0a6
BLAKE2b-256 fe4ec99052549ed7e37ca494ed4d80af3eba126b1b11e5e01e42c74ac8691ec5

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-musllinux_1_1_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c4e0aff45c6bf70ad56fd017e3da6a1677489d5698bebdb9d96e9b10d0afcb12
MD5 413c446784c80c6f186455a1c4dfde37
BLAKE2b-256 53448d4a8355068a0169cd44228d4f3af6c588d905705f11b6e50d872a49c1fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 bf7b69764bd262636f678ca05a63f67f6888aa6ef2cd99926cff3534e795ac5b
MD5 dba40604f5fc59f0fcac4741f3c2e9e1
BLAKE2b-256 fe6a14f71a9433701a2d7f648021a132864fb2d08c45cdff8256427b77aa0dc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 63d13fd60aa205ff2036141002f4cb0be6c068733e7ff1cf79d72a308e20f7bf
MD5 27d216079869b2c190762f3e46f2ac41
BLAKE2b-256 63be18a19de296b13f0e2372c0c65230a074aff166b1a1ceca0ab29f69401391

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 caf5221c709099d7f3b9ae91ebbcb8f7815a9a3815c43487c236e9e535e0a32f
MD5 86695782423dc1946614fc5dc9512ce8
BLAKE2b-256 7626bc110284a70fbb3c89218eeb3f0c261e1b88cf8b7640f94d91fe8d98ee7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13fcaf7b4415af3490da704ac4c3ca48d23be85c93c9ee52d3ee8ccb03d268fd
MD5 8deb4741e8af1af3e97b0a61210e773d
BLAKE2b-256 cbcbe6b34f6beaeaefbeae9d7da8be5f9dd22a497248d817479023eccec04f52

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tonio-0.1.0a4-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.1.0a4-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b5e6b2e60005266691a699121a66d3f03d0f777afd19cbe4503a31f6e3690c3d
MD5 cb9fe1eaa40071a688b61be23ec7089e
BLAKE2b-256 58c0cce6082f40799cd57e1f87ce147479e952de6cdfb534f5039d3c1cdcad7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.1.0a4-cp314-cp314t-macosx_10_12_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page