Template Class Job

Inheritance Relationships

Base Type

Class Documentation

template<typename Result = void>
class Job : public portal::JobBase

C++20 coroutine type for asynchronous parallel work with optional return value.

Job<T> is the primary coroutine type for the Portal Framework’s work-stealing scheduler. Jobs integrate with the Scheduler for parallel execution, support nested parallelism via co_await, and participate in fork-join synchronization via Counter.

Lifecycle:

  1. Job created suspended (via co_return from job function)

  2. Dispatched to Scheduler via wait_for_job() or dispatch_job()

  3. Executed on worker thread (may suspend/resume on different threads)

  4. Result retrieved via result() or automatic in co_await

Thread Safety:

  • Jobs can migrate between worker threads when suspended/resumed

  • Result storage is thread-safe (accessed only after completion)

  • Multiple threads can co_await the same job (scheduler handles synchronization)

Example (Simple Job):

Job<int> compute_sum(int a, int b)
{
    co_return a + b;
}

auto result = scheduler.wait_for_job(compute_sum(10, 32)); // result = 42

Example (Nested Jobs - Parent/Child):

Job<int> child_work(int value)
{
    // Simulate work
    co_return value * 2;
}

Job<int> parent_work()
{
    // Dispatch child and co_await result
    auto child = child_work(21);
    int child_result = co_await child; // Suspends parent, child executes, parent resumes with result
    co_return child_result; // Returns 42
}

auto final = scheduler.wait_for_job(parent_work());

Example (Fork-Join Parallelism):

Job<void> process_chunk(int chunk_id)
{
    // Process chunk...
    co_return;
}

Job<void> parallel_process()
{
    Counter counter{};

    // Dispatch 4 jobs in parallel
    for (int i = 0; i < 4; i++)
        scheduler.dispatch_job(process_chunk(i), JobPriority::Normal, &counter); // Counter is automatically incremented

    // Wait for all chunks to complete
    scheduler.wait_for_counter(&counter);

    co_return;
}

See also

jobs::Scheduler for dispatch methods

See also

jobs::Counter for fork-join synchronization

See also

Task for lightweight coroutines without scheduler overhead

Note

Jobs must be dispatched to scheduler before going out of scope

Note

Nested jobs (child co_awaited by parent) automatically chain: parent resumes when child completes

Template Parameters:

Result – Return type (use void for jobs without return values)

Public Types

using promise_type = ResultPromise<Result>
using handle_type = std::coroutine_handle<promise_type>

Public Functions

inline std::expected<Result, JobResultStatus> result()

Retrieve the job’s result value.

Returns:

Expected containing result or JobResultStatus if job incomplete

inline Job(handle_type result_handle)
inline Job(Job &&other) noexcept
inline Job &operator=(Job &&other) noexcept
inline ~Job() override