Jobxx - Lightweight C++ task system

Overview

jobxx

License

Copyright (c) 2017 Sean Middleditch [email protected]

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to http://unlicense.org

Summary

Simple task and job scheduling library for C++. The library aims for reasonably good performance, low overhead, light memory usage, and for suitability for games and soft-real-time uses.

Documentation

Design

jobxx aims to be as light-weight as possible while retaining strong performance. To this end, the basic primitives of the library are few and focused on minimalism.

The core concepts of jobxx are jobs, tasks, queues, and threads. Of the four, jobxx only directly represents the first three; threads are provided by std::thread or the application.

The task is the lowest-level primitive of the core concepts. A task represents a unit of work. Tasks have no return values nor error states. If applications wish to communicate results from a task, they must use an external mechanism such as std::future. jobxx tasks are best suited for small discrete chunks of work with no failure state or individual results, though of course having a task mutate some shared state (with the appropriate care for thread-safety) is a common use case. For instance, spawning a number of tasks to mutate a large array - where each task operates on a distinct subrange of the array - is an excellent case.

A job is a collection of tasks. jobxx allows users to create a job that spawns 0 or more tasks. The job maintains a completion state which is unset while the job has 1 or more tasks that have not yet been completed. Tasks spawned by a job may themselves spawn more tasks as part of the same job, allowing a job to represent the completion state of an entire tree of tasks, sub-tasks, and continuations. An application can either poll a job's completion state or block on its completion, working on tasks (if available) while waiting, or putting the thread to sleep until the job is ready.

Scheduling tasks is performed by a queue. A queue is essentially a list of tasks that have been spawned and are ready to execute. Any number of threads may poll a queue for tasks to execute. Additionally, queues contain a mechanism for parking threads; this is a way for a thread to sleep/block until a particular queue has work available. The parking approach allows for task creation to be efficient (no need to signal the OS if there are no sleeping threads) and is extensible for future needs, such as parking a thread on a job until it completes (not yet supported).

API

The two primary points of the api are jobxx::queue and jobxx::job.

jobxx::queue

A jobxx::queue is used to spawn tasks, execute spawned tasks, to create job instances, and to wait for jobs to complete.

queue::spawn_task(delegate work) -> void

Create a new task encapsulating the work to be performed. The task is put into a pending task queue and will be executed when a thread calls queue::work_one.

queue::create_job(initializer : (context&) -> void) -> job

Creates a new job instance and then invokes initializer with a context object. Tasks spawned via this context will be added to the returned job as child tasks.

jobxx::job

A jobxx::job represents the completion state of a set of tasks. The job can be queried to see if all tasks spawned for the job have been fully executed.

job::complete() const -> bool

Returns true if there are no outstanding tasks associated with the job.

job::operator bool() const

Same as job::complete.

jobxx::context

A context allows for spawning tasks as part of a job.

context::spawn_task(delegate work) -> void

As queue::spawn_task, except that the spawned task will be associated with the context's job.

jobxx::delegate

A delegate is very similar to std::function with two primary differences. First, a delegate is guaranteed to never allocate. It is a compile-time error to attempt to store a function object (or lambda, or other invokable) into a delegate if it is too large or overly aligned.

Second, a delegate can wrap an invokable with one of two different potential signatures: () -> void or (context&) -> void. This allows for convenience when needing to construct a task which has no need for a context while still allowing for tasks which do need a context.

Note: the current incarnation of delegate only works for function objects which are trivially move-constructible and trivially destructible. This limitation is planned to be lifted in future releases.

delegate::delegate(function: () -> void)

Constructs a delegate wrapping function.

delegate::delegate(function: (context&) -> void)

Constructs a delegate wrapping function.

delegate::operator bool() const

Returns true if the delegate has been created with a function, or false for a default-constructed (empty) delegate.

delegate::operator()(ctx: context&) -> void

Executes the stored function, passing ctx to it if the stored function takes a context& parameter. It is undefined behavior to call this operator on a delegate with no stored function.

jobxx::predicate

A predicate is simple wrapper for a function reference of signature () -> bool. Note that it is only a reference type, meaning that it does not take ownership of a function object used to construct it.

predicate::predicate(pred: () -> bool)

Creates a predicate wrapping the given pred invokable.

predicate::operator bool() const

Returns true if the predicate was constructed with a function, or false if the predicate has no function reference.

predicate::operator()() -> bool

Invokes the reference function and returns its result. It is undefined behavior to call this operator on a predicate with no stored function reference.

You might also like...
C++14 coroutine-based task library for games

SquidTasks Squid::Tasks is a header-only C++14 coroutine-based task library for games. Full project and source code available at https://github.com/we

Operating system project - implementing scheduling algorithms and some system calls for XV6 OS

About XV6 xv6 is a modern reimplementation of Sixth Edition Unix in ANSI C for multiprocessor x86 and RISC-V systems. It was created for pedagogical p

Design and Implementation of kernel level threads for xv6 operating system. Adding system call related to threading environment in xv6 along with userland threading library with one to one mapping and semaphore implementation as synchronisation primitive
Lucy job system - Fiber-based job system with extremely simple API

Lucy Job System This is outdated compared to Lumix Engine. Use that instead. Fiber-based job system with extremely simple API. It's a standalone versi

Lev - Lightweight C++ wrapper for LibEvent 2 API

lev Lightweight C++ wrapper for LibEvent 2 API LibEvent is a great library. It uses a C interface which is well designed but has a learning curve. Thi

ThreadPool - Lightweight, Generic, Pure C++11 ThreadPool

ThreadPool Lightweight, Generic, Pure C++11 ThreadPool Rational I needed a Thread Pool for something I was writing, and I didn't see any that I liked.

A library for enabling task-based multi-threading. It allows execution of task graphs with arbitrary dependencies.

Fiber Tasking Lib This is a library for enabling task-based multi-threading. It allows execution of task graphs with arbitrary dependencies. Dependenc

A General-purpose Parallel and Heterogeneous Task Programming System
A General-purpose Parallel and Heterogeneous Task Programming System

Taskflow Taskflow helps you quickly write parallel and heterogeneous tasks programs in modern C++ Why Taskflow? Taskflow is faster, more expressive, a

A General-purpose Parallel and Heterogeneous Task Programming System
A General-purpose Parallel and Heterogeneous Task Programming System

Taskflow Taskflow helps you quickly write parallel and heterogeneous task programs in modern C++ Why Taskflow? Taskflow is faster, more expressive, an

Task System presented in
Task System presented in "Better Code: Concurrency - Sean Parent"

task_system task_system provides a task scheduler for modern C++. The scheduler manages an array of concurrent queues A task, when scheduled, is enque

A task scheduling framework designed for the needs of game developers.

Intel Games Task Scheduler (GTS) To the documentation. Introduction GTS is a C++ task scheduling framework for multi-processor platforms. It is design

A hybrid thread / fiber task scheduler written in C++ 11

Marl Marl is a hybrid thread / fiber task scheduler written in C++ 11. About Marl is a C++ 11 library that provides a fluent interface for running tas

A header-only C++ library for task concurrency
A header-only C++ library for task concurrency

transwarp Doxygen documentation transwarp is a header-only C++ library for task concurrency. It allows you to easily create a graph of tasks where eve

Directed Acyclic Graph Execution Engine (DAGEE) is a C++ library that enables programmers to express computation and data movement, as task graphs that are scheduled concurrently and asynchronously on both CPUs and GPUs.

Directed Acyclic Graph Execution Engine (DAGEE) is a C++ library that enables programmers to express computation and data movement, as tasks in a graph structure, where edges represent task dependencies

Easing the task of comparing code generated by cc65, vbcc, and 6502-gcc

6502 C compilers benchmark Easing the way to compare code generated by cc65, 6502-gcc, vbcc, and KickC. This repository contains scripts to: Compile t

C++17 and reactor mode task/timer executor

reactor A C++17 single-file header-only, based on reactor mode, It can add tasks and timers and file descriptor to reactor(one loop one thread) Simple

GPU Task Spooler - A SLURM alternative/job scheduler for a single simulation machine
GPU Task Spooler - A SLURM alternative/job scheduler for a single simulation machine

GPU Task Spooler - A SLURM alternative/job scheduler for a single simulation machine

C++ task programming with Asio executors

Futures C++ Task Programming with Asio Executors A future object represents a handle to a value that might not be available yet from an asynchronous o

OOX: Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling.

OOX Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling. Try it Requirements: Install cmake,

Owner
Sean Middleditch
Software engineer in the games industry. These are my personal works and are neither endorsed by nor related to my employer.
Sean Middleditch
A General-purpose Parallel and Heterogeneous Task Programming System

Taskflow Taskflow helps you quickly write parallel and heterogeneous tasks programs in modern C++ Why Taskflow? Taskflow is faster, more expressive, a

Taskflow 7.6k Dec 31, 2022
A General-purpose Parallel and Heterogeneous Task Programming System

Taskflow Taskflow helps you quickly write parallel and heterogeneous task programs in modern C++ Why Taskflow? Taskflow is faster, more expressive, an

Taskflow 7.6k Dec 26, 2022
Task System presented in "Better Code: Concurrency - Sean Parent"

task_system task_system provides a task scheduler for modern C++. The scheduler manages an array of concurrent queues A task, when scheduled, is enque

Pranav 31 Dec 7, 2022
A task scheduling framework designed for the needs of game developers.

Intel Games Task Scheduler (GTS) To the documentation. Introduction GTS is a C++ task scheduling framework for multi-processor platforms. It is design

null 424 Jan 3, 2023
A hybrid thread / fiber task scheduler written in C++ 11

Marl Marl is a hybrid thread / fiber task scheduler written in C++ 11. About Marl is a C++ 11 library that provides a fluent interface for running tas

Google 1.5k Jan 4, 2023
A header-only C++ library for task concurrency

transwarp Doxygen documentation transwarp is a header-only C++ library for task concurrency. It allows you to easily create a graph of tasks where eve

Christian Blume 592 Dec 19, 2022
OOX: Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling.

OOX Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling. Try it Requirements: Install cmake,

Intel Corporation 18 Oct 25, 2022
Arcana.cpp - Arcana.cpp is a collection of helpers and utility code for low overhead, cross platform C++ implementation of task-based asynchrony.

Arcana.cpp Arcana is a collection of general purpose C++ utilities with no code that is specific to a particular project or specialized technology are

Microsoft 67 Nov 23, 2022
Cpp-taskflow - Modern C++ Parallel Task Programming Library

Cpp-Taskflow A fast C++ header-only library to help you quickly write parallel programs with complex task dependencies Why Cpp-Taskflow? Cpp-Taskflow

null 4 Mar 30, 2021
EnkiTS - A permissively licensed C and C++ Task Scheduler for creating parallel programs. Requires C++11 support.

Support development of enkiTS through Github Sponsors or Patreon enkiTS Master branch Dev branch enki Task Scheduler A permissively licensed C and C++

Doug Binks 1.4k Dec 27, 2022