Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TaskLocal

Per-task values: TaskLocal<T> gives every task its own copy of a variable.

Source: runtime/async/task_local.pep

TaskLocal

[Shared] struct TaskLocal<T>

A variable with a separate value in every task, the task counterpart of ThreadLocal<T>.

Each task that calls set stores its own value, which is released when the task finishes. A task starts with no value, including one started by a task that has one: values are not inherited. Tasks that take turns on one worker thread each see their own value, which a ThreadLocal cannot give them.

Code that does not run in a task (before async.run, or on a plain Thread) has one value per thread, as with a ThreadLocal.

For a thread-safe T (a number, a [Shared] struct), get returns the calling task’s value (the default of T, zero or null, until it sets one). For any other T, such as a String, the value is reached through a with block, with (var value = local.enter()) { ... }, and get is a compile error; set then takes a new value (a constructor call, a string literal, copy(x)).

A TaskLocal is [Shared], so one object can be used from every task and thread; it is usually a module-scope variable. Destroying one releases only the caller’s value, so destroy it only after the tasks that used it have finished.

Type parameters

  • T — the type of the per-task value

See also

  • ThreadLocal

Example

import async;

const request_id = async.TaskLocal<long>();

handle(id: long) {
    request_id.set(id);
    async.yield_now();   # the other tasks run meanwhile
    assert(request_id.get() == id, "still this task's id");
}

main(): int {
    async.run(() => {
        var tasks = Array<async.Task<void>>();
        for (var id in [1, 2, 3]) {
            tasks.append(async.spawn<void>(() => {
                handle(id);
            }));
        }
        for (var task in tasks) {
            task.join();
        }
    });
    return 0;
}

Constructor

TaskLocal()

construct()

Creates a task-local variable. No task has a value yet.

Panics

  • if the operating system has no thread-local keys left

Methods

get

get(): T

Returns the calling task’s value.

For a struct T the caller gets its own reference. Only for a thread-safe T: for any other T, use with (var value = local.enter()).

Returns

  • the value this task last stored, or the default of T (zero or null) if it has not stored one

set

set([Move] value: T)

Stores value as the calling task’s value, replacing (and, for a struct T, releasing) the one it held. Other tasks’ values are not affected.

For a T that is not thread-safe, value must be a new value (a constructor call, a string literal, copy(x)), which the compiler checks.

Parameters

  • value — the new value for this task

enter

enter(): TaskLocalGuard<T>

Returns the guard that a with block enters to reach the calling task’s value: with (var value = local.enter()) { ... }. The body runs with the value bound; the else block runs when this task has no value (for a struct T).

Returns

  • the guard; its enter() returns this task’s value

Example

const trail = async.TaskLocal<Array<String>>();

note(step: String) {
    if (!trail.is_set()) {
        trail.set(Array<String>());
    }
    with (var steps = trail.enter()) {
        steps.append(step.copy());
    }
}

is_set

is_set(): bool

Reports whether the calling task has stored a value since it started or last called clear().

Returns

  • true if this task has a value

clear

clear()

Removes the calling task’s value, releasing it for a struct T. get() returns the default of T afterwards.

TaskLocalGuard

[Isolated] struct TaskLocalGuard<T>

The access to a task’s TaskLocal<T> value that a with block holds: enter() returns the value. Get one from TaskLocal.enter().

A guard is [Isolated]: it can only be the scope of a with header, and the compiler checks the block with the confinement rule (see Mutex).

Type parameters

  • T — the type of the per-task value

Constructor

TaskLocalGuard()

construct(local: TaskLocal<T>)

Creates the guard for the calling task’s value of local; the same as local.enter().

Parameters

  • local — the task-local variable

Methods

enter

enter(): T

Returns the calling task’s value, for the with header to bind.

Returns

  • this task’s value, or the default of T (null for a struct) when it has none

exit

exit()

Does nothing: the value stays with the task.