Vix.cpp v2.8.5 is here Read the blog
Skip to content

API Reference ​

The ThreadPool module public API is available in:

cpp
#include <vix/threadpool/all.hpp>

All public symbols belong to:

cpp
namespace vix::threadpool

The module requires C++20.

This page is a compact reference to the public types, functions, enums, constants, and headers. For behavior, lifecycle rules, and examples, follow the links to the dedicated documentation pages.

Main entry points ​

The primary user-facing API consists of:

APIPurpose
ThreadPoolConcurrent worker pool
ExecutorAbstract execution interface
InlineExecutorExecute work synchronously on the caller thread
ThreadPoolExecutorExecutor adapter around a ThreadPool
ExecutorRefNon-owning executor reference
TaskOptionsPer-task execution options
Future<T>Observe an asynchronous result
Promise<T>Complete a Future manually
TaskHandle<T>Future plus task ID and cancellation source
ScopeStructured tracking of spawned work
TaskGroupManual task accounting and coordination
PeriodicTaskPeriodic callback submission
LatchOne-shot synchronization counter
BarrierReusable participant synchronization
parallel_forParallel numeric range
parallel_for_eachParallel element iteration
parallel_mapParallel transformation
parallel_reduceParallel reduction
parallel_pipelineConcurrent independent stages

ThreadPool ​

Header:

cpp
#include <vix/threadpool/ThreadPool.hpp>

Main type:

cpp
vix::threadpool::ThreadPool

Construction:

cpp
ThreadPool();
explicit ThreadPool(std::size_t threads);
explicit ThreadPool(ThreadPoolConfig config);

The pool starts automatically during construction.

Copying and moving are disabled.

Lifecycle ​

cpp
bool start();
void shutdown() noexcept;
void wait_idle();

bool running() const noexcept;
bool idle() const;

Fire-and-forget submission ​

cpp
bool post(
  Executor::Task task,
  TaskOptions options = {}
);

Executor::Task is:

cpp
using Task = std::function<void()>;

Future-producing submission ​

cpp
template <class Fn>
auto submit(
  Fn&& fn,
  TaskOptions options = {}
) -> Future<Result>;

Result is inferred from invoking the callable with no arguments.

Cancellable task handles ​

cpp
template <class Fn>
auto handle(
  Fn&& fn,
  TaskOptions options = {}
) -> TaskHandle<Result>;

A pre-reserved task ID can also be supplied:

cpp
template <class Fn>
auto handle_with_id(
  TaskId id,
  Fn&& fn,
  TaskOptions options = {}
) -> TaskHandle<Result>;

Periodic work ​

cpp
PeriodicTask schedule_every(
  PeriodicTask::Callback callback,
  PeriodicTaskConfig config = {}
);

The returned PeriodicTask is not started automatically.

Runtime information ​

cpp
ThreadPoolMetrics metrics() const;
ThreadPoolStats stats() const;

const ThreadPoolConfig& config() const noexcept;

std::size_t thread_count() const noexcept;
std::size_t pending() const;

Queue control ​

cpp
std::size_t clear();

clear() removes queued tasks that have not started.

See Lifecycle and Shutdown before using it with Future-producing tasks.

Task IDs ​

cpp
TaskId next_task_id() noexcept;

This reserves and returns the next pool task ID without submitting work.

See Thread Pool.

Executor ​

Header:

cpp
#include <vix/threadpool/Executor.hpp>

Abstract interface:

cpp
class Executor
{
public:
  using Task = std::function<void()>;

  virtual bool post(
    Task task,
    TaskOptions options = {}
  ) = 0;

  virtual void shutdown() noexcept = 0;
  virtual void wait_idle() = 0;

  virtual bool running() const noexcept = 0;
  virtual bool idle() const = 0;

  virtual ThreadPoolMetrics metrics() const = 0;
  virtual ThreadPoolStats stats() const = 0;
};

Implementations include:

text
ThreadPool
InlineExecutor
ThreadPoolExecutor

See Executors.

ExecutorRef ​

Header:

cpp
#include <vix/threadpool/Executor.hpp>

ExecutorRef is a non-owning reference to an Executor.

Construction:

cpp
ExecutorRef() noexcept;
ExecutorRef(Executor& executor) noexcept;

Important operations:

cpp
bool valid() const noexcept;
explicit operator bool() const noexcept;

Executor& get() const noexcept;

bool post(
  Executor::Task task,
  TaskOptions options = {}
) const;

void shutdown() const noexcept;
void wait_idle() const;

bool running() const noexcept;
bool idle() const;

ThreadPoolMetrics metrics() const;
ThreadPoolStats stats() const;

The referenced executor must outlive the ExecutorRef.

InlineExecutor ​

Header:

cpp
#include <vix/threadpool/InlineExecutor.hpp>

Type:

cpp
vix::threadpool::InlineExecutor

It implements Executor by executing posted work synchronously on the calling thread.

Primary operations:

cpp
bool post(
  Executor::Task task,
  TaskOptions options = {}
);

void shutdown() noexcept;
void wait_idle();

bool running() const noexcept;
bool idle() const;

ThreadPoolMetrics metrics() const;
ThreadPoolStats stats() const;

See Executors.

ThreadPoolExecutor ​

Header:

cpp
#include <vix/threadpool/ThreadPoolExecutor.hpp>

Adapter around an existing ThreadPool.

Construction:

cpp
ThreadPoolExecutor() noexcept;
explicit ThreadPoolExecutor(ThreadPool& pool) noexcept;

Important operations:

cpp
void reset(ThreadPool& pool) noexcept;
void reset() noexcept;

bool valid() const noexcept;
explicit operator bool() const noexcept;

bool post(
  Executor::Task task,
  TaskOptions options = {}
);

void shutdown() noexcept;
void wait_idle();

bool running() const noexcept;
bool idle() const;

ThreadPoolMetrics metrics() const;
ThreadPoolStats stats() const;

ThreadPool* pool() noexcept;
const ThreadPool* pool() const noexcept;

The adapter does not own the referenced pool.

Executor traits ​

Header:

cpp
#include <vix/threadpool/ExecutorTraits.hpp>

Detection traits:

cpp
HasPost<Executor, Fn>
HasSubmit<Executor, Fn>
HasSubmitWithOptions<Executor, Fn>
HasShutdown<Executor>
HasWaitIdle<Executor>

Convenience constants:

cpp
has_post_v<Executor, Fn>
has_submit_v<Executor, Fn>
has_submit_with_options_v<Executor, Fn>
has_shutdown_v<Executor>
has_wait_idle_v<Executor>

Executor-shape traits:

cpp
IsBasicExecutor<Executor, Fn>
IsFutureExecutor<Executor, Fn>

is_basic_executor_v<Executor, Fn>
is_future_executor_v<Executor, Fn>

ThreadPoolConfig ​

Header:

cpp
#include <vix/threadpool/ThreadPoolConfig.hpp>

Fields:

cpp
struct ThreadPoolConfig
{
  std::size_t thread_count;
  std::size_t max_thread_count;
  std::size_t max_queue_size;

  TaskPriority default_priority;

  bool allow_dynamic_growth;
  bool drain_on_shutdown;
  bool swallow_task_exceptions;

  std::chrono::microseconds idle_wait;
  std::chrono::milliseconds default_timeout;
};

Helpers:

cpp
ThreadPoolConfig normalized() const noexcept;

static std::size_t default_thread_count() noexcept;

Current defaults:

text
thread_count           hardware concurrency or 1
max_thread_count       hardware concurrency or 1
max_queue_size         0
default_priority       normal
allow_dynamic_growth   false
drain_on_shutdown      true
swallow_task_exceptions true
idle_wait              0 us
default_timeout        0 ms

Some configuration fields are currently stored but are not wired into the high-level runtime behavior.

See Configuration.

TaskOptions ​

Header:

cpp
#include <vix/threadpool/TaskOptions.hpp>

Fields:

cpp
struct TaskOptions
{
  TaskPriority priority;
  Timeout timeout;
  Deadline deadline;
  CancellationToken cancellation;
  WorkerId affinity;

  bool allow_after_stop;
  bool detached;

  std::uint32_t flags;
};

Factories:

cpp
TaskOptions::with_priority(TaskPriority);
TaskOptions::with_timeout(Timeout);
TaskOptions::with_deadline(Deadline);
TaskOptions::with_cancellation(CancellationToken);
TaskOptions::with_affinity(WorkerId);

Inspection:

cpp
bool has_affinity() const noexcept;
bool has_timeout() const noexcept;
bool has_deadline() const noexcept;
bool has_cancellation() const noexcept;

bool should_skip_before_run() const noexcept;

Setters:

cpp
TaskOptions& set_priority(TaskPriority);
TaskOptions& set_timeout(Timeout);
TaskOptions& set_deadline(Deadline);
TaskOptions& set_cancellation(CancellationToken);
TaskOptions& set_affinity(WorkerId);
TaskOptions& set_detached(bool);
TaskOptions& set_allow_after_stop(bool);

See Tasks and Options.

Task identifiers ​

Header:

cpp
#include <vix/threadpool/TaskId.hpp>

Type:

cpp
using TaskId = std::uint64_t;

Invalid value:

cpp
inline constexpr TaskId invalid_task_id = 0;

Helper:

cpp
bool is_valid_task_id(TaskId id) noexcept;

Worker identifiers ​

Header:

cpp
#include <vix/threadpool/WorkerId.hpp>

Type:

cpp
using WorkerId = std::uint32_t;

Invalid value:

cpp
inline constexpr WorkerId invalid_worker_id = 0;

Helper:

cpp
bool is_valid_worker_id(WorkerId id) noexcept;

See Worker Affinity.

TaskPriority ​

Header:

cpp
#include <vix/threadpool/TaskPriority.hpp>

Values:

cpp
enum class TaskPriority : std::int32_t
{
  lowest = -2,
  low = -1,
  normal = 0,
  high = 1,
  highest = 2
};

Helpers:

cpp
std::int32_t to_priority_value(
  TaskPriority priority
) noexcept;

bool priority_higher_than(
  TaskPriority lhs,
  TaskPriority rhs
) noexcept;

const char* to_string(
  TaskPriority priority
) noexcept;

See Priorities.

TaskStatus ​

Header:

cpp
#include <vix/threadpool/TaskStatus.hpp>

Values:

cpp
enum class TaskStatus : std::uint8_t
{
  created = 0,
  queued = 1,
  running = 2,
  completed = 3,
  failed = 4,
  cancelled = 5,
  timed_out = 6,
  rejected = 7
};

Helpers:

cpp
bool is_terminal(TaskStatus status) noexcept;
bool is_active(TaskStatus status) noexcept;
const char* to_string(TaskStatus status) noexcept;

See Task Results and Status.

TaskResult ​

Header:

cpp
#include <vix/threadpool/TaskResult.hpp>

Values:

cpp
enum class TaskResult : std::uint8_t
{
  none = 0,
  success = 1,
  failure = 2,
  cancelled = 3,
  timeout = 4,
  rejected = 5
};

Helpers:

cpp
bool is_success(TaskResult result) noexcept;
bool is_failure(TaskResult result) noexcept;
const char* to_string(TaskResult result) noexcept;

Future<T> ​

Header:

cpp
#include <vix/threadpool/Future.hpp>

Type:

cpp
template <class T>
class Future;

Important API:

cpp
using value_type = T;

bool valid() const noexcept;
explicit operator bool() const noexcept;

void wait() const;
bool ready() const;

template <class Rep, class Period>
std::future_status wait_for(
  const std::chrono::duration<Rep, Period>& timeout
) const;

template <class Clock, class Duration>
std::future_status wait_until(
  const std::chrono::time_point<Clock, Duration>& timeout
) const;

T get();

TaskStatus status() const;
TaskResult result() const;
ThreadPoolErrc error() const;

Future<void> is supported through the same template interface with get() returning void.

Futures are move-only.

See Futures and Promises.

Promise<T> ​

Header:

cpp
#include <vix/threadpool/Promise.hpp>

Type:

cpp
template <class T>
class Promise;

Important API:

cpp
using value_type = T;

bool valid() const noexcept;

Future<T> get_future();

void set_value(T value);

template <class... Args>
void emplace_value(Args&&... args);

void set_exception(std::exception_ptr exception);
void set_current_exception();

void set_error(ThreadPoolErrc error);

std::shared_ptr<SharedState<T>> state() const noexcept;

Promise<void> provides:

cpp
Future<void> get_future();

void set_value();
void set_exception(std::exception_ptr exception);
void set_current_exception();
void set_error(ThreadPoolErrc error);

Promises are move-only.

See Futures and Promises.

SharedState<T> ​

Header:

cpp
#include <vix/threadpool/SharedState.hpp>

SharedState<T> is the shared synchronization and result storage used internally by Promise<T> and Future<T>.

It stores:

text
readiness
value
exception
ThreadPoolErrc
TaskStatus
TaskResult
retrieval state

It is publicly available for advanced integrations, but ordinary application code should normally use Promise<T> and Future<T> rather than manipulating shared state directly.

TaskHandle<T> ​

Header:

cpp
#include <vix/threadpool/TaskHandle.hpp>

Important API:

cpp
using value_type = T;

TaskId id() const noexcept;

bool valid() const noexcept;
explicit operator bool() const noexcept;

void cancel() noexcept;
bool cancelled() const noexcept;

bool ready() const;
void wait() const;
T get();

TaskStatus status() const;
TaskResult result() const;
ThreadPoolErrc error() const;

Future<T>& future() noexcept;
const Future<T>& future() const noexcept;

CancellationSource& cancellation_source() noexcept;
const CancellationSource& cancellation_source() const noexcept;

TaskHandle is move-only.

See Task Handles.

CancellationToken ​

Header:

cpp
#include <vix/threadpool/CancellationToken.hpp>

Important API:

cpp
CancellationToken() noexcept;

bool can_cancel() const noexcept;

bool cancelled() const noexcept;
bool is_cancelled() const noexcept;
bool stop_requested() const noexcept;

bool can_continue() const noexcept;

void reset() noexcept;

A default token is disconnected.

See Cancellation.

CancellationSource ​

Header:

cpp
#include <vix/threadpool/CancellationSource.hpp>

Important API:

cpp
CancellationSource();

CancellationToken token() const noexcept;

void request_cancel() noexcept;

bool cancelled() const noexcept;
bool is_cancelled() const noexcept;

bool valid() const noexcept;

void reset();

reset() creates a new cancellation state. Previously created tokens remain attached to the old state.

CancellationState ​

Header:

cpp
#include <vix/threadpool/CancellationToken.hpp>

Low-level shared cancellation state:

cpp
class CancellationState
{
public:
  void request_cancel() noexcept;
  bool cancelled() const noexcept;
};

Applications should normally use CancellationSource and CancellationToken.

Timeout ​

Header:

cpp
#include <vix/threadpool/Timeout.hpp>

Type:

cpp
class Timeout

Duration type:

cpp
using duration = std::chrono::milliseconds;

Construction and factories:

cpp
Timeout() noexcept;
explicit Timeout(duration value) noexcept;

static Timeout disabled() noexcept;
static Timeout milliseconds(long long value) noexcept;
static Timeout seconds(long long value) noexcept;

Inspection:

cpp
bool enabled() const noexcept;
bool disabled_value() const noexcept;

duration value() const noexcept;
long long count() const noexcept;

Elapsed-time check:

cpp
template <class Rep, class Period>
bool expired(
  const std::chrono::duration<Rep, Period>& elapsed
) const noexcept;

Comparison:

cpp
operator==
operator!=

See Timeouts.

Deadline ​

Header:

cpp
#include <vix/threadpool/Deadline.hpp>

Clock types:

cpp
using clock = std::chrono::steady_clock;
using time_point = clock::time_point;

Construction and factories:

cpp
Deadline() noexcept;
explicit Deadline(time_point time) noexcept;

static Deadline disabled() noexcept;
static Deadline from_timeout(Timeout timeout) noexcept;

template <class Rep, class Period>
static Deadline after(
  const std::chrono::duration<Rep, Period>& duration
) noexcept;

Inspection:

cpp
bool enabled() const noexcept;
bool disabled_value() const noexcept;

time_point time() const noexcept;

bool expired() const noexcept;
bool expired_at(time_point now) const noexcept;

clock::duration remaining() const noexcept;
std::chrono::milliseconds remaining_ms() const noexcept;

Comparison:

cpp
operator==
operator!=

See Deadlines.

Scope ​

Header:

cpp
#include <vix/threadpool/Scope.hpp>

Construction:

cpp
explicit Scope(ThreadPool& pool) noexcept;

Submission:

cpp
template <class Fn>
bool spawn(
  Fn&& fn,
  TaskOptions options = {}
);

Control:

cpp
void close();

void cancel() noexcept;
bool cancelled() const noexcept;
CancellationToken cancellation_token() const noexcept;

void wait();
void wait_and_rethrow();

Inspection:

cpp
bool empty() const;
std::size_t size() const;
bool closed() const;

Scope is neither copyable nor movable.

Its destructor waits for tracked Futures and swallows exceptions.

See Scopes.

TaskGroup ​

Header:

cpp
#include <vix/threadpool/TaskGroup.hpp>

TaskGroup provides manual task accounting.

Core operations:

cpp
bool add_task(TaskId id);

void finish_task(
  TaskStatus status,
  TaskResult result,
  std::exception_ptr exception = nullptr
);

void close();

void cancel() noexcept;

void wait();
void wait_and_rethrow();

Cancellation:

cpp
CancellationToken cancellation_token() const noexcept;

CancellationSource& cancellation_source() noexcept;
const CancellationSource& cancellation_source() const noexcept;

bool cancelled() const noexcept;

State:

cpp
bool done() const;
bool closed() const;
bool empty() const;

Counters:

cpp
std::uint64_t total_tasks() const;
std::uint64_t pending_tasks() const;

std::uint64_t completed_tasks() const;
std::uint64_t failed_tasks() const;
std::uint64_t cancelled_tasks() const;
std::uint64_t timed_out_tasks() const;
std::uint64_t rejected_tasks() const;

Outcome inspection:

cpp
bool has_failure() const;
bool has_error() const;

std::exception_ptr first_exception() const;

std::vector<TaskId> task_ids() const;

TaskGroupState exposes the underlying thread-safe implementation and substantially the same accounting API.

See Task Groups.

TaskGuard ​

Header:

cpp
#include <vix/threadpool/TaskGuard.hpp>

Template:

cpp
template <class T>
class TaskGuard;

Construction:

cpp
explicit TaskGuard(
  std::atomic<T>& counter
) noexcept;

Construction increments the counter.

Destruction decrements it once unless already released.

Operations:

cpp
void release() noexcept;
bool active() const noexcept;

The type is move-constructible but not copyable.

A deduction guide allows:

cpp
std::atomic<int> active{0};

vix::threadpool::TaskGuard guard(active);

Latch ​

Header:

cpp
#include <vix/threadpool/Latch.hpp>

Construction:

cpp
explicit Latch(std::size_t count) noexcept;

Operations:

cpp
void count_down();
void count_down(std::size_t amount);

void arrive_and_wait();
void wait() const;

bool ready() const;
bool is_ready() const;

std::size_t count() const;

Latch is one-shot and neither copyable nor movable.

See Synchronization.

Barrier ​

Header:

cpp
#include <vix/threadpool/Barrier.hpp>

Construction:

cpp
explicit Barrier(
  std::size_t participants
) noexcept;

Operations:

cpp
void arrive_and_wait();
void arrive();

void wait();

void release();

std::size_t participants() const;
std::size_t remaining() const;
std::size_t generation() const;

Barrier automatically begins a new generation when all participants arrive.

It is neither copyable nor movable.

See Synchronization.

PeriodicTaskConfig ​

Header:

cpp
#include <vix/threadpool/PeriodicTask.hpp>

Fields:

cpp
struct PeriodicTaskConfig
{
  std::chrono::milliseconds interval;
  TaskOptions options;

  bool run_immediately;
  bool stop_on_post_failure;
};

Factory:

cpp
static PeriodicTaskConfig every(
  std::chrono::milliseconds interval
) noexcept;

Helpers:

cpp
static std::chrono::milliseconds normalize_interval(
  std::chrono::milliseconds value
) noexcept;

PeriodicTaskConfig normalized() const noexcept;

Default interval:

text
1000 ms

PeriodicTask ​

Header:

cpp
#include <vix/threadpool/PeriodicTask.hpp>

Callback:

cpp
using Callback = std::function<void()>;

Important lifecycle API:

cpp
bool start();

void stop() noexcept;
void join() noexcept;

bool running() const noexcept;
bool joinable() const noexcept;

Inspection:

cpp
std::uint64_t submitted_ticks() const noexcept;
std::uint64_t failed_posts() const noexcept;

const PeriodicTaskConfig& config() const noexcept;

The task is not started during construction.

See Periodic Tasks.

ParallelForOptions ​

Header:

cpp
#include <vix/threadpool/ParallelFor.hpp>

Fields:

cpp
struct ParallelForOptions
{
  std::size_t chunk_size;
  TaskOptions task_options;
};

Factory:

cpp
static ParallelForOptions with_chunk_size(
  std::size_t value
) noexcept;

A zero chunk size enables automatic calculation.

Shared helper:

cpp
std::size_t compute_parallel_chunk_size(
  std::size_t total,
  std::size_t workerCount,
  std::size_t requestedChunkSize
) noexcept;

parallel_for ​

Header:

cpp
#include <vix/threadpool/ParallelFor.hpp>

Explicit pool:

cpp
template <class Index, class Fn>
void parallel_for(
  ThreadPool& pool,
  Index first,
  Index last,
  Fn&& fn,
  ParallelForOptions options = {}
);

Temporary pool:

cpp
template <class Index, class Fn>
void parallel_for(
  Index first,
  Index last,
  Fn&& fn,
  ParallelForOptions options = {}
);

Index must be integral.

The range is:

text
[first, last)

See Parallel For.

ParallelForEachOptions ​

Header:

cpp
#include <vix/threadpool/ParallelForEach.hpp>

Fields:

cpp
struct ParallelForEachOptions
{
  std::size_t chunk_size;
  TaskOptions task_options;
};

Factory:

cpp
static ParallelForEachOptions with_chunk_size(
  std::size_t value
) noexcept;

parallel_for_each ​

Header:

cpp
#include <vix/threadpool/ParallelForEach.hpp>

Iterator range:

cpp
template <class Iterator, class Fn>
void parallel_for_each(
  ThreadPool& pool,
  Iterator first,
  Iterator last,
  Fn&& fn,
  ParallelForEachOptions options = {}
);

Container:

cpp
template <class Container, class Fn>
void parallel_for_each(
  ThreadPool& pool,
  Container& container,
  Fn&& fn,
  ParallelForEachOptions options = {}
);

Temporary-pool overloads exist for both iterator ranges and containers.

See Parallel For Each.

ParallelMapOptions ​

Header:

cpp
#include <vix/threadpool/ParallelMap.hpp>

Fields:

cpp
struct ParallelMapOptions
{
  std::size_t chunk_size;
  TaskOptions task_options;
};

Factory:

cpp
static ParallelMapOptions with_chunk_size(
  std::size_t value
) noexcept;

parallel_map ​

Header:

cpp
#include <vix/threadpool/ParallelMap.hpp>

Iterator range:

cpp
template <class Iterator, class Fn>
auto parallel_map(
  ThreadPool& pool,
  Iterator first,
  Iterator last,
  Fn&& fn,
  ParallelMapOptions options = {}
) -> std::vector<Result>;

Container:

cpp
template <class Container, class Fn>
auto parallel_map(
  ThreadPool& pool,
  Container& container,
  Fn&& fn,
  ParallelMapOptions options = {}
);

Temporary-pool overloads exist for iterator and container forms.

Output order matches input order.

See Parallel Map.

ParallelReduceOptions ​

Header:

cpp
#include <vix/threadpool/ParallelReduce.hpp>

Fields:

cpp
struct ParallelReduceOptions
{
  std::size_t chunk_size;
  TaskOptions task_options;
};

Factory:

cpp
static ParallelReduceOptions with_chunk_size(
  std::size_t value
) noexcept;

parallel_reduce ​

Header:

cpp
#include <vix/threadpool/ParallelReduce.hpp>

Iterator range:

cpp
template <class Iterator, class T, class ReduceFn>
T parallel_reduce(
  ThreadPool& pool,
  Iterator first,
  Iterator last,
  T initial,
  ReduceFn&& reduce,
  ParallelReduceOptions options = {}
);

Container:

cpp
template <class Container, class T, class ReduceFn>
T parallel_reduce(
  ThreadPool& pool,
  Container& container,
  T initial,
  ReduceFn&& reduce,
  ParallelReduceOptions options = {}
);

Temporary-pool overloads are also available.

Current implementation note:

text
initial is applied to every chunk
and again to the final partial reduction

Use an identity value with the current implementation.

See Parallel Reduce.

ParallelPipelineOptions ​

Header:

cpp
#include <vix/threadpool/ParallelPipeline.hpp>

Fields:

cpp
struct ParallelPipelineOptions
{
  TaskOptions task_options;
};

parallel_pipeline ​

Header:

cpp
#include <vix/threadpool/ParallelPipeline.hpp>

Explicit pool:

cpp
template <class... Stages>
void parallel_pipeline(
  ThreadPool& pool,
  ParallelPipelineOptions options,
  Stages&&... stages
);

Default-options form:

cpp
template <class... Stages>
void parallel_pipeline(
  ThreadPool& pool,
  Stages&&... stages
);

Temporary-pool forms are also available.

Stages are independent and execute concurrently when worker capacity allows.

Their return values are discarded.

See Parallel Pipeline.

Pipeline ​

Header:

cpp
#include <vix/threadpool/ParallelPipeline.hpp>

Reusable pipeline builder:

cpp
class Pipeline

Stored stage type:

cpp
using Stage = std::function<void()>;

Construction:

cpp
Pipeline();
explicit Pipeline(
  ParallelPipelineOptions options
);

Stage registration:

cpp
template <class Fn>
Pipeline& add(Fn&& fn);

Management:

cpp
void clear();

std::size_t size() const noexcept;
bool empty() const noexcept;

Options:

cpp
const ParallelPipelineOptions& options() const noexcept;

void set_options(
  ParallelPipelineOptions options
);

Execution:

cpp
void run(ThreadPool& pool);
void run();

run() does not clear registered stages.

Convenience parallel namespace ​

Header:

cpp
#include <vix/threadpool/Parallel.hpp>

Namespace:

cpp
vix::threadpool::parallel

Convenience functions:

cpp
parallel::for_range(...)
parallel::for_each(...)
parallel::map(...)
parallel::reduce(...)
parallel::pipeline(...)

They forward to the corresponding top-level parallel APIs.

ThreadPoolMetrics ​

Header:

cpp
#include <vix/threadpool/ThreadPoolMetrics.hpp>

Fields:

cpp
struct ThreadPoolMetrics
{
  std::size_t worker_count;
  std::size_t pending_tasks;
  std::uint64_t active_tasks;

  std::size_t idle_workers;
  std::size_t busy_workers;

  std::uint64_t submitted_tasks;
  std::uint64_t completed_tasks;
  std::uint64_t failed_tasks;
  std::uint64_t cancelled_tasks;
  std::uint64_t timed_out_tasks;
  std::uint64_t rejected_tasks;
};

Helpers:

cpp
bool idle() const noexcept;

std::uint64_t finished_tasks() const noexcept;
std::uint64_t error_tasks() const noexcept;

See Metrics and Statistics.

ThreadPoolStats ​

Header:

cpp
#include <vix/threadpool/ThreadPoolStats.hpp>

Fields:

cpp
struct ThreadPoolStats
{
  std::uint64_t accepted_tasks;
  std::uint64_t rejected_tasks;

  std::uint64_t completed_tasks;
  std::uint64_t failed_tasks;
  std::uint64_t cancelled_tasks;
  std::uint64_t timed_out_tasks;

  std::uint64_t worker_wakeups;
  std::uint64_t idle_waits;

  std::chrono::nanoseconds total_execution_time;
  std::chrono::nanoseconds max_execution_time;
};

Helpers:

cpp
std::uint64_t submitted_tasks() const noexcept;
std::uint64_t finished_tasks() const noexcept;
std::uint64_t error_tasks() const noexcept;

bool empty() const noexcept;

std::chrono::nanoseconds
average_execution_time() const noexcept;

Some timing and wakeup fields are currently exposed but not populated by ThreadPool.

See Metrics and Statistics.

ThreadPoolErrc ​

Header:

cpp
#include <vix/threadpool/ThreadPoolError.hpp>

Values:

cpp
enum class ThreadPoolErrc : std::uint8_t
{
  ok = 0,
  invalid_argument = 1,
  stopped = 2,
  rejected = 3,
  queue_full = 4,
  timeout = 5,
  cancelled = 6,
  not_ready = 7,
  not_supported = 8,
  internal_error = 9
};

Helpers:

cpp
const std::error_category&
threadpool_category() noexcept;

std::error_code
make_error_code(ThreadPoolErrc error) noexcept;

bool is_ok(ThreadPoolErrc error) noexcept;
bool is_error(ThreadPoolErrc error) noexcept;

ThreadPoolErrc is registered as a standard error-code enum and can be converted to std::error_code.

See Errors.

SchedulingPolicy ​

Header:

cpp
#include <vix/threadpool/SchedulingPolicy.hpp>

Values:

cpp
enum class SchedulingPolicy : std::uint8_t
{
  round_robin = 0,
  least_loaded = 1,
  affinity = 2,
  affinity_then_least_loaded = 3
};

Default:

cpp
default_scheduling_policy()

returns:

cpp
SchedulingPolicy::affinity_then_least_loaded

Helpers:

cpp
bool uses_affinity(
  SchedulingPolicy policy
) noexcept;

bool uses_load_balancing(
  SchedulingPolicy policy
) noexcept;

const char* to_string(
  SchedulingPolicy policy
) noexcept;

See Scheduling Model.

RejectionPolicy ​

Header:

cpp
#include <vix/threadpool/RejectionPolicy.hpp>

Values:

cpp
enum class RejectionPolicy : std::uint8_t
{
  reject = 0,
  caller_runs = 1,
  discard = 2
};

Default:

cpp
default_rejection_policy()

returns:

cpp
RejectionPolicy::reject

Helpers:

cpp
bool runs_on_caller(
  RejectionPolicy policy
) noexcept;

bool discards_task(
  RejectionPolicy policy
) noexcept;

bool reports_rejection(
  RejectionPolicy policy
) noexcept;

const char* to_string(
  RejectionPolicy policy
) noexcept;

See Queue and Rejection Policies.

QueuePolicy ​

Header:

cpp
#include <vix/threadpool/QueuePolicy.hpp>

Values:

cpp
enum class QueuePolicy : std::uint8_t
{
  priority = 0,
  fifo = 1,
  lifo = 2
};

Default:

cpp
default_queue_policy()

returns:

cpp
QueuePolicy::priority

Helpers:

cpp
bool uses_priority(
  QueuePolicy policy
) noexcept;

bool is_fifo(
  QueuePolicy policy
) noexcept;

bool is_lifo(
  QueuePolicy policy
) noexcept;

const char* to_string(
  QueuePolicy policy
) noexcept;

Current runtime note: the public enum exists, but TaskQueue currently always uses priority ordering with FIFO sequence ordering for equal priorities.

See Queue and Rejection Policies.

WorkerState ​

Header:

cpp
#include <vix/threadpool/WorkerState.hpp>

Values:

cpp
enum class WorkerState : std::uint8_t
{
  created = 0,
  idle = 1,
  running = 2,
  stopping = 3,
  stopped = 4,
  failed = 5
};

Helpers:

cpp
bool is_terminal(WorkerState state) noexcept;
bool can_execute(WorkerState state) noexcept;
const char* to_string(WorkerState state) noexcept;

this_worker ​

Header:

cpp
#include <vix/threadpool/this_worker.hpp>

Namespace:

cpp
vix::threadpool::this_worker

Public inspection:

cpp
bool inside() noexcept;
WorkerId id() noexcept;
std::size_t index() noexcept;
TaskId task_id() noexcept;

These functions expose the worker context associated with the current thread.

The same header also exposes low-level context management functions:

cpp
void set(
  WorkerId workerId,
  std::size_t workerIndex
) noexcept;

void set_task(TaskId taskId) noexcept;
void clear_task() noexcept;
void clear() noexcept;

Normal application code usually only needs the inspection functions.

See Worker Affinity.

Task ​

Header:

cpp
#include <vix/threadpool/Task.hpp>

Callable storage:

cpp
using TaskFunction =
  detail::MoveOnlyFunction<void()>;

Task is the low-level executable unit used by workers and the scheduler.

Important inspection:

cpp
TaskId id() const noexcept;

const TaskOptions& options() const noexcept;
TaskOptions& options() noexcept;

TaskPriority priority() const noexcept;
std::uint64_t sequence() const noexcept;

TaskStatus status() const noexcept;
TaskResult result() const noexcept;

std::exception_ptr exception() const noexcept;

bool valid() const noexcept;
bool schedulable() const noexcept;
bool done() const noexcept;

bool running() const noexcept;
bool queued() const noexcept;
bool succeeded() const noexcept;

Task also exposes lifecycle operations used by the runtime to mark and execute work.

Most application code should use ThreadPool::post(), submit(), or handle() rather than constructing low-level Tasks directly.

See Tasks and Options.

TaskCmp ​

Header:

cpp
#include <vix/threadpool/TaskCmp.hpp>

TaskCmp defines the current queue ordering:

text
higher priority first
      ↓
equal priority
      ↓
smaller sequence first

It is used by TaskQueue.

TaskQueue ​

Header:

cpp
#include <vix/threadpool/TaskQueue.hpp>

Construction:

cpp
TaskQueue() noexcept;
explicit TaskQueue(
  std::size_t maxSize
) noexcept;

Submission:

cpp
bool push(Task task);

std::size_t push_batch(
  std::vector<Task> tasks
);

Retrieval:

cpp
std::optional<Task> pop();

std::optional<Task> pop_active(
  std::atomic<std::uint64_t>& activeTasks
);

const Task* peek() const;

Queue management:

cpp
std::size_t clear();

bool empty() const;
bool full() const;

std::size_t size() const;

std::size_t max_size() const noexcept;
bool bounded() const noexcept;

void set_max_size(
  std::size_t value
) noexcept;

TaskQueue is thread-safe and currently uses TaskCmp.

SchedulerConfig ​

Header:

cpp
#include <vix/threadpool/Scheduler.hpp>

Fields:

cpp
struct SchedulerConfig
{
  std::size_t worker_count;
  std::size_t max_queue_size_per_worker;

  SchedulingPolicy scheduling_policy;
  RejectionPolicy rejection_policy;

  bool drain_on_stop;

  std::string worker_name_prefix;
};

Helper:

cpp
SchedulerConfig normalized() const;

Defaults:

text
worker_count               1
max_queue_size_per_worker  0
scheduling_policy          affinity_then_least_loaded
rejection_policy           reject
drain_on_stop              true
worker_name_prefix         vix-tp

Scheduler ​

Header:

cpp
#include <vix/threadpool/Scheduler.hpp>

Scheduler owns and selects workers.

Main lifecycle:

cpp
bool start();

void stop() noexcept;
void join() noexcept;

Submission:

cpp
bool submit(Task task);

Runtime inspection includes:

text
running state
stopping state
worker count
queue size
idle state
metrics
statistics
configuration
worker access
queue clearing

Scheduler is a low-level public runtime type.

Ordinary applications normally interact through ThreadPool.

See Architecture and Scheduling Model.

WorkerMetrics ​

Header:

cpp
#include <vix/threadpool/Worker.hpp>

Fields:

cpp
struct WorkerMetrics
{
  WorkerId id;
  std::size_t index;
  WorkerState state;

  std::size_t pending_tasks;
  std::uint64_t active_tasks;

  std::uint64_t accepted_tasks;
  std::uint64_t executed_tasks;
  std::uint64_t completed_tasks;
  std::uint64_t failed_tasks;
  std::uint64_t cancelled_tasks;
  std::uint64_t timed_out_tasks;
  std::uint64_t rejected_tasks;
  std::uint64_t idle_cycles;
};

See Metrics and Statistics.

Worker ​

Header:

cpp
#include <vix/threadpool/Worker.hpp>

Worker owns:

text
worker identity
TaskQueue
WorkerThread
task outcome counters
worker lifecycle state

Main runtime operations include:

cpp
bool start();

void stop() noexcept;
void join() noexcept;

bool submit(Task task);

It also exposes queue, state, metrics, configuration, and lifecycle inspection methods.

Worker is a low-level runtime type. Most applications should use ThreadPool.

WorkerThread ​

Header:

cpp
#include <vix/threadpool/WorkerThread.hpp>

WorkerThread owns the physical std::thread associated with a Worker.

Run function:

cpp
using RunFunction = std::function<void()>;

Main operations:

cpp
bool start(RunFunction fn);

void stop() noexcept;
void join() noexcept;

It also exposes worker identity, name, thread state, and joinability information.

This is a low-level runtime abstraction.

Version ​

Header:

cpp
#include <vix/threadpool/version.hpp>

Constants:

cpp
inline constexpr int version_major;
inline constexpr int version_minor;
inline constexpr int version_patch;

inline constexpr const char* version;

When using the umbrella header:

cpp
#include <vix/threadpool/all.hpp>

two convenience functions are also available:

cpp
const char* module_version() noexcept;
bool available() noexcept;

available() currently always returns true.

Public headers ​

The complete public module header set is:

HeaderMain API
all.hppComplete public ThreadPool API
Barrier.hppBarrier
CancellationSource.hppCancellationSource
CancellationToken.hppCancellationState, CancellationToken
Deadline.hppDeadline
Executor.hppExecutor, ExecutorRef
ExecutorTraits.hppExecutor detection traits
Future.hppFuture<T>
InlineExecutor.hppInlineExecutor
Latch.hppLatch
Parallel.hppparallel::* convenience namespace
ParallelFor.hppParallelForOptions, parallel_for
ParallelForEach.hppParallelForEachOptions, parallel_for_each
ParallelMap.hppParallelMapOptions, parallel_map
ParallelPipeline.hppParallelPipelineOptions, parallel_pipeline, Pipeline
ParallelReduce.hppParallelReduceOptions, parallel_reduce
PeriodicTask.hppPeriodicTaskConfig, PeriodicTask
Promise.hppPromise<T>
QueuePolicy.hppQueuePolicy
RejectionPolicy.hppRejectionPolicy
Scheduler.hppSchedulerConfig, Scheduler
SchedulingPolicy.hppSchedulingPolicy
Scope.hppScope
SharedState.hppSharedState<T>
Task.hppTask, TaskFunction
TaskCmp.hppTaskCmp
TaskGroup.hppTaskGroupState, TaskGroup
TaskGuard.hppTaskGuard<T>
TaskHandle.hppTaskHandle<T>
TaskId.hppTaskId, invalid_task_id
TaskOptions.hppTaskOptions
TaskPriority.hppTaskPriority
TaskQueue.hppTaskQueue
TaskResult.hppTaskResult
TaskStatus.hppTaskStatus
ThreadPool.hppThreadPool
ThreadPoolConfig.hppThreadPoolConfig
ThreadPoolError.hppThreadPoolErrc, error category helpers
ThreadPoolExecutor.hppThreadPoolExecutor
ThreadPoolMetrics.hppThreadPoolMetrics
ThreadPoolStats.hppThreadPoolStats
Timeout.hppTimeout
Worker.hppWorkerMetrics, Worker
WorkerId.hppWorkerId, invalid_worker_id
WorkerState.hppWorkerState
WorkerThread.hppWorkerThread
this_worker.hppCurrent worker context
version.hppModule version constants

For applications using several ThreadPool features:

cpp
#include <vix/threadpool/all.hpp>

For libraries that want narrower header dependencies, include the individual public headers required by the public or implementation interface.

For example:

cpp
#include <vix/threadpool/ThreadPool.hpp>
#include <vix/threadpool/TaskOptions.hpp>

The public surface contains both application-level and runtime-level abstractions.

For most application code, start with:

text
ThreadPool
TaskOptions
Future
TaskHandle
Scope
CancellationSource
Deadline
Timeout
parallel algorithms
PeriodicTask
metrics

Use these lower-level types when implementing custom execution infrastructure or advanced integrations:

text
Task
TaskQueue
TaskCmp
WorkerThread
Worker
Scheduler
SharedState
CancellationState

The high-level architecture is:

text
application
    ↓
ThreadPool
    ↓
Scheduler
    ↓
Worker
    ↓
TaskQueue
    ↓
Task

The higher-level composition APIs build on that same execution path:

text
Scope
parallel algorithms
PeriodicTask
TaskHandle
      ↓
ThreadPool
      ↓
same scheduler and workers

Current implementation notes ​

Several public types expose functionality that is broader than the behavior currently wired through ThreadPool.

The main current distinctions are:

  • TaskPriority values are lowest, low, normal, high, and highest.
  • QueuePolicy is public, but the current TaskQueue implementation always uses priority ordering with FIFO sequence ordering for equal priorities.
  • RejectionPolicy is configurable on the low-level Scheduler, but high-level ThreadPool currently constructs its Scheduler with the default reject policy.
  • caller_runs is not applied to every worker queue-full rejection path in the current implementation.
  • ThreadPoolConfig::default_timeout is currently merged into submitted task options when no task timeout is present.
  • Several other ThreadPoolConfig fields are currently exposed but not fully wired into high-level runtime behavior.
  • parallel_reduce currently applies its initial value once to every chunk and again during final combination.
  • Execution timeouts do not forcibly interrupt running C++ callables.
  • A submit() Future can currently report success even when the low-level task is later classified as timed out.
  • clear() can remove a queued result-producing task without completing its associated Future.
  • Non-draining shutdown can similarly leave queued result-producing Futures unresolved.
  • ThreadPoolStats exposes execution timing and worker-wakeup fields that are not currently populated by ThreadPool.
  • ThreadPool can currently be restarted after shutdown, retaining runtime counters and any queued work left by non-draining shutdown.

The dedicated documentation pages describe these behaviors in detail.

CMake target ​

For an installed standalone ThreadPool package:

cmake
find_package(vix_threadpool CONFIG REQUIRED)

target_link_libraries(app
  PRIVATE
    vix::threadpool
)

See CMake.

Documentation index ​

For detailed behavior, use:

Released under the MIT License.