API reference

pika follows semver. pika is currently at a 0.X version which means that minor versions may break the API. pika gives no guarantees about ABI stability. The ABI may change even in patch versions.

The API reference is a work in progress. While the reference is being expanded, the More resources section contains useful links to high level overviews and low level API descriptions of std::execution.

The following headers are part of the public API. Any other headers are internal implementation details.

These headers are part of the public API, but are currently undocumented.

  • pika/async_rw_mutex.hpp

  • pika/barrier.hpp

  • pika/condition_variable.hpp

  • pika/cuda.hpp

  • pika/execution.hpp

  • pika/latch.hpp

  • pika/mpi.hpp

  • pika/mutex.hpp

  • pika/runtime.hpp

  • pika/semaphore.hpp

  • pika/thread.hpp

All functionality in a namespace containing detail and all macros prefixed with PIKA_DETAIL are implementation details and may change without warning at any time. All functionality in a namespace containing experimental may change without warning at any time. However, the intention is to stabilize those APIs over time.

pika/init.hpp

The pika/init.hpp header provides functionality to manage the pika runtime.

#include <pika/execution.hpp>
#include <pika/init.hpp>

#include <fmt/printf.h>

int main(int argc, char* argv[])
{
    pika::start(argc, argv);

    // The pika runtime is now active and we can schedule work on the default thread pool
    pika::this_thread::experimental::sync_wait(
        pika::execution::experimental::schedule(
            pika::execution::experimental::thread_pool_scheduler{}) |
        pika::execution::experimental::then([]() { fmt::print("Hello from the pika runtime\n"); }));

    pika::finalize();
    pika::stop();

    return 0;
}
void pika::start(int argc, const char *const *argv, init_params const &params = init_params())

Start the runtime.

No task is created on the runtime.

Parameters:
  • argc -- number of arguments in argv

  • argv -- array of arguments. The first element is ignored.

Pre:

(argc == 0 && argv == nullptr) || (argc >= 1 && argv != nullptr)

Pre:

the runtime is not initialized

Post:

the runtime is running

int pika::stop()

Stop the runtime.

Waits until pika::finalize has been called and there is no more activity on the runtime. See pika::wait. The runtime can be started again after calling pika::stop. Must be called from outside the runtime.

Returns:

the return value of the callable passed to pika::start, if any. If none was passed, returns 0.

Pre:

the runtime is initialized

Pre:

the calling thread is not a pika task

Post:

the runtime is not initialized

void pika::finalize()

Signal the runtime that it may be stopped.

Until pika::finalize has been called, pika::stop will not return. This function exists to distinguish between the runtime being idle but still expecting work to be scheduled on it and the runtime being idle and ready to be shutdown. Unlike @pika::stop, pika::finalize can be called from within or outside the runtime.

Pre:

the runtime is initialized

void pika::wait()

Wait for the runtime to be idle.

Waits until the runtime is idle. This includes tasks scheduled on the thread pools as well as non-tasks such as CUDA kernels submitted through pika facilities. Can be called from within the runtime, in which case the calling task is ignored when determining idleness.

Pre:

the runtime is initialized

Post:

all work submitted before the call to wait is completed

void pika::resume()

Resume the runtime.

Resumes the runtime by waking all worker threads on all thread pools.

Pre:

the calling thread is not a pika task

Pre:

runtime is suspended or running

Post:

runtime is running

void pika::suspend()

Suspend the runtime.

Waits until the runtime is idle and suspends worker threads on all thread pools. Work can be scheduled on the runtime even when it is suspended, but no progress will be made.

Pre:

the calling thread is not a pika task

Pre:

runtime is running or suspended

Post:

runtime is suspended

bool pika::is_runtime_initialized() noexcept

Returns true when the runtime is initialized, false otherwise.

Returns true while in a pika::init call, or between calls of pika::start and pika::stop, otherwise false.

Added in 0.22.0.

struct init_params

pika/execution.hpp

The pika/execution.hpp header provides functionality related to std::execution.

constexpr split_tuple_t pika::execution::experimental::split_tuple = {}

Splits a sender of a tuple into a tuple of senders.

Sender adaptor that takes a sender that sends a single, non-empty, tuple and returns a new tuple of the same size as the one sent by the input sender which contains one sender for each element in the input sender tuple. Each output sender signals completion whenever the input sender would have signalled completion. The predecessor sender must complete with exactly one tuple of at least one type.

Added in 0.12.0.

#include <pika/execution.hpp>
#include <pika/init.hpp>

#include <fmt/printf.h>

#include <chrono>
#include <thread>
#include <tuple>
#include <utility>

int main(int argc, char* argv[])
{
    namespace ex = pika::execution::experimental;
    namespace tt = pika::this_thread::experimental;

    pika::start(argc, argv);
    ex::thread_pool_scheduler sched{};

    // split_tuple can be used to process the result and its square through
    // senders, without having to pass both around together
    auto [snd, snd_squared] = ex::schedule(sched) | ex::then([]() { return 42; }) |
        ex::then([](int x) { return std::tuple(x, x * x); }) | ex::split_tuple();

    // snd and snd_squared will be ready at the same time, but can be used independently
    auto snd_print = std::move(snd) | ex::continues_on(sched) |
        ex::then([](int x) { fmt::print("x is {}\n", x); });
    auto snd_process =
        std::move(snd_squared) | ex::continues_on(sched) | ex::then([](int x_squared) {
            fmt::print("Performing expensive operations on x * x\n");
            std::this_thread::sleep_for(std::chrono::milliseconds(300));
            return x_squared / 2;
        });

    auto x_squared_processed =
        tt::sync_wait(ex::when_all(std::move(snd_print), std::move(snd_process)));
    fmt::print("The final result is {}\n", x_squared_processed);

    pika::finalize();
    pika::stop();

    return 0;
}
constexpr when_all_vector_t pika::execution::experimental::when_all_vector = {}

Returns a sender that completes when all senders in the input vector have completed.

Sender adaptor that takes a vector of senders and returns a sender that sends a vector of the values sent by the input senders. The vector sent has the same size as the input vector. An empty vector of senders completes immediately on start. When the input vector of senders contains senders that send no value the output sender sends no value instead of a vector. The senders in the input vector must send at most a single type.

Added in 0.2.0.

#include <pika/execution.hpp>
#include <pika/init.hpp>

#include <fmt/printf.h>
#include <fmt/ranges.h>

#include <cstddef>
#include <random>
#include <utility>
#include <vector>

std::size_t get_n() { return 13; }
std::size_t calculate(std::size_t i) { return (std::rand() % 4) * i * i; }

int main(int argc, char* argv[])
{
    namespace ex = pika::execution::experimental;
    namespace tt = pika::this_thread::experimental;

    pika::start(argc, argv);
    ex::thread_pool_scheduler sched{};

    // when_all_vector is like when_all, but for a dynamic number of senders
    // through a vector of senders
    auto const n = get_n();
    std::vector<ex::unique_any_sender<std::size_t>> snds;
    snds.reserve(n);
    for (std::size_t i = 0; i < n; ++i)
    {
        snds.push_back(ex::just(i) | ex::continues_on(sched) | ex::then(calculate));
    }
    auto snds_print =
        ex::when_all_vector(std::move(snds)) | ex::then([](std::vector<std::size_t> results) {
            fmt::print("Results are: {}\n", fmt::join(results, ", "));
        });
    tt::sync_wait(std::move(snds_print));

    // when_all_vector will send no value on completion if the input vector
    // contains senders sending no value
    std::vector<ex::unique_any_sender<>> snds_nothing;
    snds_nothing.reserve(n);
    for (std::size_t i = 0; i < n; ++i)
    {
        snds_nothing.push_back(ex::just(i) | ex::continues_on(sched) |
            ex::then([](auto i) { fmt::print("{}: {}\n", i, calculate(i)); }));
    }
    auto snds_nothing_done = ex::when_all_vector(std::move(snds_nothing)) |
        ex::then([]() { fmt::print("Done printing all results\n"); });
    tt::sync_wait(std::move(snds_nothing_done));

    pika::finalize();
    pika::stop();

    return 0;
}