87 std::uint8_t num_user_threads = 0;
88 std::uint8_t num_threads = 0;
89 std::uint16_t main_queue_size = 256;
90 std::uint16_t normal_queue_size = 1024;
91 std::uint16_t worker_queue_size = 32;
92 std::uint64_t job_steal_rng_seed = 0u;
124 InitializationToken
Initialize(
const JobSystemMemoryRequirements& memory_requirements = {},
void*
const memory =
nullptr)
noexcept;
290 template<typename T, typename... Args>
338 template<typename Closure>
396 template<typename ConditionFn>
405 }
while (condition());
483 return data.
size >=
sizeof(T) ?
static_cast<T*
>(data.
ptr) :
nullptr;
486 template<
typename T,
typename... Args>
491 JobAssert(data.
size >=
sizeof(T),
"Attempting to store an object too large to fit within a task's storage buffer.");
493 new (data.
ptr) T(std::forward<Args>(args)...);
499 TaskEmplaceData<T>(
task, data);
505 TaskDataAs<T>(
task)->~T();
508 template<
typename Closure>
519 new (private_data) Closure(std::forward<Closure>(
function));
549 static Splitter EvenSplit(
const std::size_t total_num_items, std::size_t num_groups_per_thread = 1u)
551 if (num_groups_per_thread < 1u)
553 num_groups_per_thread = 1u;
567 return Splitter{max_data_size /
sizeof(T)};
607 template<
typename F,
typename S>
608 Task*
ParallelFor(
const std::size_t start,
const std::size_t count, S&& splitter, F&& fn,
Task* parent =
nullptr)
611 [=, splitter = std::move(splitter), fn = std::move(fn)](
Task*
const task) {
612 if (count > 1u && splitter(count))
614 const std::size_t left_count = count / 2;
615 const std::size_t right_count = count - left_count;
623 for (std::size_t offset = 0u; offset < count; ++offset)
625 fn(
task, start + offset);
632 template<
typename Splitter,
typename Reducer>
636 [=, splitter = std::move(splitter), reduce = std::move(reduce)](
Task*
const task) {
644 std::size_t count_left = count;
645 while (count_left > 1)
647 const std::size_t stride = count_left / 2;
649 const auto ReduceRange = [stride, &reduce](
Task*
const sub_task,
const std::size_t index) {
650 reduce(sub_task, index, index + stride);
655 if ((count_left & 1) != 0)
657 reduce(
task, start, start + count_left - 1);
701 template<
typename T,
typename F,
typename S>
705 std::size_t(0), count, std::move(splitter), [data, fn = std::move(fn)](
Task*
const task,
const std::size_t index) {
706 fn(
task, data + index);
728 template<
typename... F>
732 [=](
Task*
const parent_task)
mutable {
Assertion macro for this library.
#define JobAssert(expr, msg)
Token type used for other subsystems that rely on the job system to verify that the Job system has be...
void * taskReservePrivateUserData(Task *const task, const std::size_t num_bytes, const std::size_t alignment) noexcept
void * taskGetPrivateUserData(Task *const task, const std::size_t alignment) noexcept
QueueType taskQType(const Task *task) noexcept
bool mainQueueTryRunTask(void) noexcept
TaskData TaskGetData(Task *const task, const std::size_t alignment) noexcept
Returns you the user-data buffer you way write to get data into your TaskFn.
std::size_t size
The size of the buffer.
void * ptr
The start of the buffer you may write to.
void TaskSubmitAndWait(Task *const self, const QueueType queue=QueueType::NORMAL) noexcept
Same as calling taskSubmit followed by waitOnTask.
void WaitOnTask(const Task *const task) noexcept
Waits until the specified task is done executing. This function will block but do work while being bl...
void(*)(Task *) TaskFn
The signature of the type of function for a single Task.
T * TaskDataAs(Task *const task) noexcept
Grabs the user-data pointer as the T you specified. No safety is guaranteed, this is just a dumb cast...
void TaskAddContinuation(Task *const self, Task *const continuation, const QueueType queue=QueueType::NORMAL) noexcept
A 'continuation' is a task that will be added to a queue after the 'self' Task has finished running.
InitializationToken Initialize(const JobSystemMemoryRequirements &memory_requirements={}, void *const memory=nullptr) noexcept
Sets up the Job system and creates all the worker threads. The thread that calls 'Job::Initialize' is...
Task * ParallelInvoke(Task *const parent, F &&... fns)
Invokes each passed in function object in parallel.
void YieldTimeSlice() noexcept
Asks the OS to yield this threads execution to another thread on the current cpu core.
std::uint16_t NumWorkers() noexcept
Returns the number of workers created by the system. This function can be called by any thread concur...
QueueType
Determines which threads the task will be allowed to run on.
@ MAIN
Tasks in this queue will only be run by the main thread.
@ NORMAL
Tasks in this queue will run on either the main or worker threads.
@ WORKER
Tasks in this queue will never run on the main thread.
Task * TaskMake(const TaskFn function, Task *const parent=nullptr) noexcept
Creates a new Task that should be later submitted by calling 'TaskSubmit'.
const char * ProcessorArchitectureName() noexcept
An implementation defined name for the CPU architecture of the device. This function can be called by...
void TaskSetData(Task *const task, const T &data)
Copies 'data' into the user-data buffer by calling the T copy constructor.
void SetupUserThread()
Must be called in the callstack of the thread to be setup.
void Shutdown() noexcept
This will deallocate any memory used by the system and shutdown any threads created by 'bfJob::initia...
Task * ParallelFor(const std::size_t start, const std::size_t count, S &&splitter, F &&fn, Task *parent=nullptr)
Parallel for algorithm, splits the work up recursively splitting based on the splitter passed in.
void TaskEmplaceData(Task *const task, Args &&... args)
Calls the constructor of T on the user-data buffer.
WorkerID CurrentWorker() noexcept
The current id of the current thread. This function can be called by any thread concurrently.
void TaskIncRef(Task *const task) noexcept
Increments the task's ref count preventing it from being garbage collected.
std::uint16_t WorkerID
The id type of each worker thread.
bool IsMainThread() noexcept
Allows for querying if we are currently executing in the main thread.
void PauseProcessor() noexcept
CPU pause instruction to indicate when you are in a spin wait loop.
void TaskDecRef(Task *const task) noexcept
Decrements the task's ref count allow it to be garbage collected.
void TickMainQueue(ConditionFn &&condition) noexcept
Runs tasks from the main queue as long as there are tasks available and condition returns true.
std::size_t NumSystemThreads() noexcept
Makes some system calls to grab the number threads / processors on the device. This function can be c...
void TaskSubmit(Task *const self, const QueueType queue=QueueType::NORMAL) noexcept
Submits the task to the specified queue.
void TaskDestructData(Task *const task)
Helper for calling destructor on the task's user data.
Task * ParallelReduce(const std::size_t start, const std::size_t count, Splitter &&splitter, Reducer &&reduce, Task *parent=nullptr)
bool TaskIsDone(const Task *const task) noexcept
Returns the done status of the task.
The runtime configuration for the Job System.
A buffer for user-data you can write to, maybe large enough to store task data inline.
The memory requirements for a given configuration JobSystemCreateOptions.
JobSystemMemoryRequirements(const JobSystemCreateOptions &options={}) noexcept
std::size_t alignment
The base alignment the pointer should be.
const JobSystemCreateOptions options
The options used to create the memory requirements.
std::size_t byte_size
The number of bytes the job system needed.
static Splitter EvenSplit(const std::size_t total_num_items, std::size_t num_groups_per_thread=1u)
Splits work evenly across the threads depending on the number of workers.
static constexpr Splitter MaxDataSize(const std::size_t max_data_size)
constexpr bool operator()(const std::size_t count) const
static constexpr Splitter MaxItemsPerTask(const std::size_t max_items)