Skip to content

Global Interpreter Lock

Pydust provides two functions for managing GIL state: py.nogil and py.gil.

No GIL / Allow Threads

The py.nogil function allows Pydust code to release the Python GIL. This allows Python threads to continue to make progress while Zig code is running.

Each call to py.nogil() must have a corresponding acquire() call.

See the Python documentation for more information.

1
2
3
4
5
6
7
8
9
pub fn sleep(args: struct { millis: u64 }) void {
    std.time.sleep(args.millis * 1_000_000);
}

pub fn sleep_release(args: struct { millis: u64 }) void {
    const nogil = py.nogil();
    defer nogil.acquire();
    std.time.sleep(args.millis * 1_000_000);
}
def test_gil():
    now = time.time()
    with ThreadPoolExecutor(10) as pool:
        for _ in range(10):
            # Sleep for 100ms
            pool.submit(gil.sleep, 100)

    # This should take ~10 * 100ms. Add some leniency and check for >900ms.
    duration = time.time() - now
    assert duration > 0.9


def test_gil_release():
    now = time.time()
    with ThreadPoolExecutor(10) as pool:
        for _ in range(10):
            pool.submit(gil.sleep_release, 100)

    # This should take ~1 * 100ms. Add some leniency and check for <500ms.
    duration = time.time() - now
    assert duration < 0.5

Acquire GIL

The py.gil function allows Pydust code to re-acquire the Python GIL before calling back into Python code. This can be particularly useful with Zig or C libraries that make use of callbacks.

Each call to py.gil() must have a corresponding release() call.

See the Python documentation for more information.