carb::tasking::ITasking
Defined in carb/tasking/ITasking.h
-
struct ITasking
Defines a tasking plugin interface, acquired with carb::Framework::acquireInterface() when carb.tasking.plugin is loaded.
ITasking is started automatically on plugin startup. It uses default TaskingDesc, see getDefaultTaskingDesc().
Several ISettings keys exist to provide debug behavior and to override default startup behavior (but do not override a TaskingDesc provided to ITasking::changeParameters()).
- Thread Safety
Unless otherwise specified, all functions in this interface can be called from multiple threads simultaneously.
Public Functions
-
void yieldUntilCounter(RequiredObject counter)
Yields execution to another task until counter reaches its target value.
Tasks invoking this call can resume on different thread. If the task must resume on the same thread, use PinGuard.
Note
deprecated Use wait() instead.
- Parameters
counter – The counter to check.
-
bool timedYieldUntilCounter(RequiredObject counter, uint64_t timeoutNs)
Yields execution to another task until counter reaches its target value or the timeout period elapses.
Tasks invoking this call can resume on different thread. If the task must resume on the same thread, use PinGuard.
Note
Deprecated: Use wait_for() or wait_until() instead.
- Parameters
counter – The counter to check.
timeoutNs – The number of nanoseconds to wait. Pass kInfinite to wait forever or 0 to try immediately without waiting.
- Returns
true if the counter period has completed; false if the timeout period elapses.
-
inline bool checkCounter(Counter *c)
Checks if counter is at the counter’s target value.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
c – The counter to check.
- Returns
true
if the counter is at the target value;false
otherwise.
-
inline uint32_t getCounterValue(Counter *counter)
Retrieves the current value of the target.
Note! Because of the threaded nature of counters, this value may have changed by another thread before the function returns.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
counter – The counter.
- Returns
The current value of the counter.
-
inline uint32_t getCounterTarget(Counter *counter)
Gets the target value for the Counter.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
counter – The counter to check.
- Returns
The target value of the counter.
-
inline uint32_t fetchAddCounter(Counter *counter, uint32_t value)
Atomically adds a value to the counter and returns the value held previously.
The fetchAdd operation on the counter will be atomic, but this function as a whole is not atomic.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
counter – The counter.
value – The value to add to the counter.
- Returns
The value of the counter before the addition.
-
inline uint32_t fetchSubCounter(Counter *counter, uint32_t value)
Atomically subtracts a value from the counter and returns the value held previously.
The fetchSub operation on the counter will be atomic, but this function as a whole is not atomic.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
counter – The counter.
value – The value to subtract from the counter.
- Returns
The value of the counter before the addition.
-
inline void storeCounter(Counter *counter, uint32_t value)
Atomically replaces the current value with desired on a counter.
The store operation on the counter will be atomic, but this function as a whole is not atomic.
Note
Deprecated: The Counter interface is deprecated.
- Parameters
counter – The counter.
value – The value to load into to the counter.
-
bool waitForTask(TaskContext task)
Blocks the current thread/task until the given Task has completed.
Similar to yieldUntilCounter() but does not require a Counter object.
Note
Deprecated: Use wait() instead.
- Parameters
task – The TaskContext to wait on
- Returns
true if the wait was successful; false if the TaskContext has already expired or was invalid.
-
bool try_wait(RequiredObject req)
Checks the object specified in
req
to see if it is signaled.- Parameters
req – The RequiredObject object to check.
- Returns
true
if the object is signaled;false
if the object is invalid or not signaled.
-
void wait(RequiredObject req)
Blocks the calling thread or task until
req
is signaled.- Parameters
req – The RequiredObject object to check.
-
template<class Rep, class Period>
bool wait_for(std::chrono::duration<Rep, Period> dur, RequiredObject req) Blocks the calling thread or task until
req
is signaled ordur
has elapsed.- Parameters
dur – The duration to wait for.
req – The RequiredObject object to check.
- Returns
true
if the object is signaled;false
if the object is invalid or not signaled, ordur
elapses.
-
template<class Clock, class Duration>
bool wait_until(std::chrono::time_point<Clock, Duration> when, RequiredObject req) Blocks the calling thread or task until
req
is signaled or the clock reacheswhen
.- Parameters
when – The time_point to wait until.
req – The RequiredObject object to check.
- Returns
true
if the object is signaled;false
if the object is invalid or not signaled, orwhen
is reached.
-
void waitSemaphore(Semaphore *sema)
Waits on a semaphore until it has been signaled.
If the semaphore has already been signaled, this function returns immediately.
- Parameters
sema – The semaphore to wait on.
Requests shared access on a SharedMutex object.
Use unlockSharedMutex() to release the shared lock. SharedMutex is not recursive.
- Parameters
mutex – The SharedMutex object.
Requests exclusive access on a SharedMutex object.
Use unlockSharedMutex() to release the exclusive lock. SharedMutex is not recursive.
- Parameters
mutex – The SharedMutex object.
-
void waitConditionVariable(ConditionVariable *cv, Mutex *m)
Waits on a ConditionVariable object until it is notified.
Prefer using the helper function, waitConditionVariablePred().
The given Mutex must match the Mutex passed in by all other threads/tasks waiting on the ConditionVariable, and must be locked by the current thread/task. While waiting, the Mutex is unlocked. When the thread/task is notified the Mutex is re-locked before returning to the caller. ConditionVariables are allowed to spuriously wake up, so best practice is to check the variable in a loop and sleep if the variable still does not match desired.
- Parameters
cv – The ConditionVariable to wait on.
m – The Mutex that is locked by the current thread/task.
-
void yieldUntilCounterPinThread(RequiredObject counter)
Yields execution to another task until
counter == value
.Task invoking this call will resume on the same thread due to thread pinning. Thread pinning is not efficient. See pinToCurrentThread() for details.
- Parameters
counter – The counter to check.
-
template<class Pred>
inline void waitConditionVariablePred(ConditionVariable *cv, Mutex *m, Pred &&pred) Checks
pred
in a loop until it returns true, and waits on a ConditionVariable ifpred
returns false.- Parameters
cv – The ConditionVariable to wait on
m – The Mutex associated with the ConditionVariable. Must be locked by the calling thread/task.
pred – A function-like predicate object in the form
bool(void)
. waitConditionVariablePred() returns whenpred
returns true.
-
template<class Pred>
inline bool timedWaitConditionVariablePred(ConditionVariable *cv, Mutex *m, uint64_t timeoutNs, Pred &&pred) Checks
pred
in a loop until it returns true or the timeout period expires, and waits on a ConditionVariable ifpred
returns false.- Parameters
cv – The ConditionVariable to wait on
m – The Mutex associated with the ConditionVariable. Must be locked by the calling thread/task.
timeoutNs – The relative timeout period in nanoseconds. Specify kInfinite to wait forever or 0 to test immediately without waiting.
pred – A function-like predicate object in the form
bool(void)
. waitConditionVariablePred() returns whenpred
returns true.
- Returns
true
if the predicate returnedtrue
;false
if the timeout period expired
-
template<class Callable, class ...Args>
auto awaitSyncTask(Priority priority, Callable &&f, Args&&... args) Executes a task synchronously.
Note
To ensure that the task executes in task context, the function is called directly if already in task context. If called from non-task context,
f
is executed by a call to addTask() but this function does not return until the subtask is complete.- Parameters
priority – The priority of the task to execute. Only used if not called in task context.
f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value.
args – Arguments to pass to
f
.
- Returns
The return value of
f
.
-
template<class Callable, class ...Args>
auto addTask(Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Runs the given function-like object as a task.
- Parameters
priority – The priority of the task to execute.
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
inline TaskContext addTask(TaskDesc desc, Counter *counter)
Adds a task to the internal queue.
Note
Deprecated: The other addTask() (and variant) functions accept lambdas and function-like objects, and are designed to simplify adding tasks and add tasks succinctly. Prefer using those functions.
- Parameters
desc – The TaskDesc describing the task.
counter – A counter to associate with this task. It will be incremented by 1. When the task completes, it will be decremented.
- Returns
A TaskContext that can be used to refer to this task
-
template<class Callable, class ...Args>
auto addThrottledTask(Semaphore *throttler, Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Runs the given function-like object as a task when a Semaphore is signaled.
- Parameters
throttler – (optional) A Semaphore used to throttle the number of tasks that can run concurrently. The task waits until the semaphore is signaled (released) before starting, and then signals the semaphore after the task has executed.
priority – The priority of the task to execute.
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
template<class Callable, class ...Args>
auto addSubTask(RequiredObject requiredObject, Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Runs the given function-like object as a task once a Counter reaches its target.
- Parameters
requiredObject – (optional) An object convertible to RequiredObject (such as a task or Future). that will, upon completing, trigger the execution of this task.
priority – The priority of the task to execute.
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
template<class Callable, class ...Args>
auto addThrottledSubTask(RequiredObject requiredObject, Semaphore *throttler, Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Runs the given function-like object as a task once a Counter reaches its target and when a Semaphore is signaled.
- Parameters
requiredObject – (optional) An object convertible to RequiredObject (such as a task or Future). that will, upon completing, trigger the execution of this task.
throttler – (optional) A semaphore used to throttle the number of tasks that can run concurrently. Once requiredObject becomes signaled, the task waits until the semaphore is signaled (released) before starting, and then signals the semaphore after the task has executed.
priority – The priority of the task to execute.
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
template<class Callable, class Rep, class Period, class ...Args>
auto addTaskIn(const std::chrono::duration<Rep, Period> &dur, Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Adds a task to occur after a specific duration has passed.
- Parameters
dur – The duration to wait for. The task is not started until this duration elapses.
priority – The priority of the task to execute
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
template<class Callable, class Clock, class Duration, class ...Args>
auto addTaskAt(const std::chrono::time_point<Clock, Duration> &when, Priority priority, Trackers &&trackers, Callable &&f, Args&&... args) Adds a task to occur at a specific point in time.
- Parameters
when – The point in time at which to begin the task
priority – The priority of the task to execute
trackers – (optional) A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value
args – Arguments to pass to
f
- Returns
A Future based on the return type of
f
-
template<class Callable, class ...Args>
void applyRange(size_t range, Callable f, Args&&... args) Processes a range from
[0..range)
calling an invocable for each index, potentially from different threads.See the additional documentation for
applyRange
.Note
This function does not return until
f
has been called (and returned) on every index from[0..range)
.Note
Calling this function recursively will automatically scale down the parallelism in order to not overburden the system.
Note
As there is overhead to calling
f
repeatedly, it is more efficient to use applyRangeBatch() withbatchHint = 0
and af
that handles multiple indexes on one invocation.Warning
Since
f
can be called from multiple threads simultaneously, all operations it performs must be thread-safe. Additional consideration must be taken since mutable captures of any lambdas or passed inargs
will be accessed simultaneously by multiple threads so care must be taken to ensure thread safety.- Parameters
range – The number of times to call
f
.f – An invocable object (i.e. functor, lambda, [member] function ptr) that is repeatedly called until all indexes in
[0..range)
have been processed, potentially from different threads. It is invoked with parametersf(args..., index)
whereindex
is within the range[0..range)
.args – Arguments to pass to
f
-
template<class Callable, class ...Args>
void applyRangeBatch(size_t range, size_t batchHint, Callable f, Args&&... args) Processes a range from
[0..range)
calling an invocable for batches of indexes, potentially from different threads.See the additional documentation for
applyRange
.Note
This function does not return until
f
has been called (and returned) for every index from[0..range)
.Note
Calling this function recursively will automatically scale down the parallelism in order to not overburden the system.
Warning
Since
f
can be called from multiple threads simultaneously, all operations it performs must be thread-safe. Additional consideration must be taken since mutable captures of any lambdas or passed inargs
will be accessed simultaneously by multiple threads so care must be taken to ensure thread safety.- Parameters
range – The number of times to call
f
.batchHint – Ignored but retained for API compatibility.
f – An invocable object (i.e. functor, lambda, [member] function ptr) that is repeatedly called until all indexes in
[0..range)
have been processed, potentially from different threads. It is invoked with parametersf(args..., startIndex, endIndex)
where[startIndex..endIndex)
is the range of indexes that must be processed by that invocation off
. Note thatendIndex
is a past-the-end index and must not actually be processed by an invocation off
. Any return value off
is ignored.args – Arguments to pass to
f
-
template<class T, class Callable, class ...Args>
void parallelFor(T begin, T end, Callable f, Args&&... args) Processes a range from [begin..end) calling a functor for each index, potentially from different threads.
Note
This function does not return until
f
has been called (and returned) on every index from [begin..end
)Note
Calling this function recursively will automatically scale down the parallelism in order to not overburden the system.
Warning
Since
f
can be called from multiple threads simultaneously, all operations it performs must be thread-safe. Additional consideration must be taken since mutable captures of any lambdas or passed inargs
will be accessed simultaneously by multiple threads so care must be taken to ensure thread safety.- Parameters
begin – The starting value passed to
f
end – The ending value. Every T(1) step in [begin, end) is passed to
f
f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value. The index value from [begin..end) is passed as the last parameter (after any passed
args
).args – Arguments to pass to
f
-
template<class T, class Callable, class ...Args>
void parallelFor(T begin, T end, T step, Callable f, Args&&... args) Processes a stepped range from [begin..end) calling a functor for each step, potentially from different threads.
Note
This function does not return until
f
has been called (and returned) on every index from [begin..end
)Note
Calling this function recursively will automatically scale down the parallelism in order to not overburden the system.
Warning
Since
f
can be called from multiple threads simultaneously, all operations it performs must be thread-safe. Additional consideration must be taken since mutable captures of any lambdas or passed inargs
will be accessed simultaneously by multiple threads so care must be taken to ensure thread safety.- Parameters
begin – The starting value passed to
f
end – The ending value. Every
step
in [begin, end) is passed tof
step – The step size to determine every value passed to
f
f – An invocable object (i.e. functor, lambda, [member] function ptr) that optionally returns a value. The stepped value from [begin..end) is passed as the last parameter (after any passed
args
).args – Arguments to pass to
f
-
template<class Rep, class Period>
inline void sleep_for(const std::chrono::duration<Rep, Period> &dur) Causes the current thread or task to sleep for the specified time.
Note
This function is fiber-aware. If currently executing in a fiber, the fiber will be yielded until the requested amount of time has passed. If a thread is currently executing, then the thread will sleep.
- Parameters
dur – The duration to sleep for
-
template<class Clock, class Duration>
inline void sleep_until(const std::chrono::time_point<Clock, Duration> &tp) Causes the current thread or task to sleep until the specified time.
Note
This function is fiber-aware. If currently executing in a fiber, the fiber will be yielded until the requested amount of time has passed. If a thread is currently executing, then the thread will sleep.
- Parameters
tp – The absolute time point to sleep until
-
template<class T>
inline void futexWait(const std::atomic<T> &val, T compare) A fiber-safe futex implementation: if
val
equalscompare
, the thread or task sleeps until woken.Warning
Futexes are complicated and error-prone. Prefer using higher-level synchronization primitives.
- Parameters
val – The atomic value to check.
compare – The value to compare against. If
val
matches this, then the calling thread or task sleeps until futexWakeup() is called.
-
template<class T, class Rep, class Period>
inline bool futexWaitFor(const std::atomic<T> &val, T compare, std::chrono::duration<Rep, Period> dur) A fiber-safe futex implementation: if
val
equalscompare
, the thread or task sleeps until woken or the timeout period expires.Warning
Futexes are complicated and error-prone. Prefer using higher-level synchronization primitives.
- Parameters
val – The atomic value to check.
compare – The value to compare against. If
val
matches this, then the calling thread or task sleeps until futexWakeup() is called.dur – The maximum duration to wait.
- Returns
true
ifval
doesn’t matchcompare
or if futexWakeup() was called;false
if the timeout period expires.
-
template<class T, class Clock, class Duration>
inline bool futexWaitUntil(const std::atomic<T> &val, T compare, std::chrono::time_point<Clock, Duration> when) A fiber-safe futex implementation: if
val
equalscompare
, the thread or task sleeps until woken or the specific time is reached.Warning
Futexes are complicated and error-prone. Prefer using higher-level synchronization primitives.
- Parameters
val – The atomic value to check.
compare – The value to compare against. If
val
matches this, then the calling thread or task sleeps until futexWakeup() is called.when – The clock time to wait until.
- Returns
true
ifval
doesn’t matchcompare
or if futexWakeup() was called;false
if the clock time is reached.
-
template<class T>
inline unsigned futexWakeup(const std::atomic<T> &val, unsigned count) Wakes threads or tasks waiting in futexWait(), futexWaitFor() or futexWaitUntil().
Warning
Futexes are complicated and error-prone. Prefer using higher-level synchronization primitives.
- Parameters
val – The same
val
passed to futexWait(), futexWaitFor() or futexWaitUntil().count – The number of threads or tasks to wakeup. To wake all waiters use
UINT_MAX
.
- Returns
The number of threads or tasks that were waiting and are now woken.
-
void bindTrackers(RequiredObject requiredObject, Trackers &&trackers)
Binds any number of Tracker objects to the given RequiredObject.
Effectively allows adding trackers to a given object.
Previously this was only achievable through a temporary task:
The previous method wasted time in that one of the task threads would eventually have to pop the task from the queue and run an empty function. Calling// Old way: a task that would bind `taskGroup` to `requiredObject` tasking->addSubTask(requiredObject, Priority::eDefault, { taskGroup }, []{}); // New way: direct binding: tasking->bindTrackers(requiredObject, { taskGroup });
bindTrackers()
does not waste this time.However, there are some “disadvantages.” The
addSubTask()
method would allocate a TaskContext, return a Future, and could be canceled. These features were seldom needed, hence this function.- Parameters
requiredObject – An object convertible to RequiredObject (such as a task or Future). The given
trackers
will be bound to this required object.trackers – A
std::initializer_list
of zero or more Tracker objects. Note that this must be a temporary object. The Tracker objects can be used to determine task completion or to provide input/output parameters to the task system.
-
template<class T, std::enable_if_t<std::is_convertible<T, const char*>::value, bool> = false>
inline void nameTask(TaskContext task, T &&name) Sets a name for a task for debugging purposes, similar to how threads can be named.
This function is optimized for a literal string: passing a literal string as
name
does not copy the string but instead retains the pointer as it is guaranteed to never change. Passing a non-literal string will result in a copy.The task name is visible in the debugger as debug information for a task.
Retrieving the task name can be accomplished through getTaskDebugInfo().
- Thread Safety
It is safe to set a task name from multiple threads, though inadvisable. Reading the task name via getTaskDebugInfo() while it is being changed in a different thread is not strongly ordered and may result in an empty string being read, or random bytes as the name string, but will not result in a crash.
Note
It is often easier to name the task as it’s created by passing a task name as a Tracker object to addTask() or the other task creation functions.
- Template Parameters
T – A type that is convertible to
const char*
. Seename
below.- Parameters
task – The TaskContext to name. If this is not a valid task, or the task has already completed or has been cancelled, nothing happens.
name – Either a
const char*
(dynamic string) or aconst char (&)[N]
(literal string) as the string name. May benullptr
to un-set a task name. Dynamic strings will be copied before the call returns. Literal strings will be retained by pointer value.
Public Members
-
void (*changeParameters)(TaskingDesc desc)
Changes the parameters under which the ITasking interface functions.
This may stop and start threads, but will not lose any tasks in progress or queued.
- Thread Safety
It is unsafe to add any additional tasks while calling this function. The caller must ensure that no new tasks are added until this function returns.
Note
This function reloads all registered IFiberEvents interfaces so they will start receiving notifications. However, if this is the only change desired it is recommended to use reloadFiberEvents() instead.
Warning
Calling this function from within a task context causes undefined behavior.
- Param desc
The tasking plugin descriptor.
-
const TaskingDesc &(*getDesc)()
Get TaskingDesc the plugin currently running with.
- Return
The tasking plugin descriptor.
-
Counter *(*createCounter)()
Creates a Counter with target value of zero.
Warning
Prefer using CounterWrapper instead.
- Return
The counter created.
-
Counter *(*createCounterWithTarget)(uint32_t target)
Creates a counter with a specific target value.
Warning
Prefer using CounterWrapper instead.
- Param target
The target value of the counter. Yielding on this counter will wait for this target.
- Return
The counter created.
-
void (*addTasks)(TaskDesc *tasks, size_t taskCount, Counter *counter)
Adds a group of tasks to the internal queue.
- Param tasks
The tasks to queue.
- Param taskCount
The number of tasks.
- Param counter
A counter to associate with the task group as a whole. Initially it incremented by taskCount. When each task completes, it will be decremented by 1.
-
void (*yield)()
Yields execution.
Task invoking this call will be put in the very end of task queue, priority is ignored.
-
bool (*pinToCurrentThread)()
Causes the currently executing TaskContext to be “pinned” to the thread it is currently running on.
This function causes the current thread to be the only task thread that can run the current task. This is necessary in some cases where thread specificity is required (those these situations are NOT recommended for tasks): holding a mutex, or using thread-specific data, etc. Thread pinning is not efficient (the pinned thread could be running a different task causing delays for the current task to be resumed, and wakeTask() must wait to return until the pinned thread has been notified) and should therefore be avoided.
Call unpinFromCurrentThread() to remove the pin, allowing the task to run on any thread.
Warning
Do not call this function directly; instead use PinGuard.
Note
All calls to pin a thread will issue a warning log message.
Note
It is assumed that the task is allowed to move to another thread during the pinning process, though this may not always be the case. Only after pinToCurrentThread() returns will a task be pinned. Therefore, make sure to call pinToCurrentThread() before any operation that requires pinning.
- Return
true if the task was already pinned; false if the task was not pinned or if not called from Task Context (i.e. getTaskContext() would return kInvalidTaskContext)
-
bool (*unpinFromCurrentThread)()
Un-pins the currently executing TaskContext from the thread it is currently running on.
Warning
Do not call this function directly; instead use PinGuard.
- Return
true if the task was successfully un-pinned; false if the task was not pinned or if not called from Task Context (i.e. getTaskContext() would return kInvalidTaskContext)
-
Mutex *(*createMutex)()
Creates a non-recursive mutex.
Note
Both createMutex() and createRecursiveMutex() return a Mutex object; it is up to the creator to ensure that the Mutex object is used properly. A Mutex created with createMutex() will call
std::terminate()
if recursively locked.Warning
Prefer using MutexWrapper instead.
- Return
The created non-recursive mutex.
-
bool (*timedLockMutex)(Mutex *mutex, uint64_t timeoutNs)
Locks a mutex or waits for the timeout period to expire.
Note
Attempting to recursively lock a mutex created with createMutex() will abort. Use a mutex created with createRecursiveMutex() to support recursive locking.
- Param mutex
The mutex to lock.
- Param timeoutNs
The relative timeout in nanoseconds. Specify kInfinite to wait forever or 0 to try locking without waiting.
- Return
true if the calling thread/fiber now has ownership of the mutex; false if the timeout period expired.
-
void (*sleepNs)(uint64_t nanoseconds)
Sleeps for the given number of nanoseconds.
Prefer using sleep_for() or sleep_until()
Note
This function is fiber-aware. If currently executing in a fiber, the fiber will be yielded until the requested amount of time has passed. If a thread is currently executing, then the thread will sleep.
- Param nanoseconds
The amount of time to yield/sleep, in nanoseconds.
-
TaskContext (*getTaskContext)()
If the calling thread is running in “task context”, that is, a fiber executing a task previously queued with addTask(), this function returns a handle that can be used with suspendTask() and wakeTask().
- Return
kInvalidTaskContext if the calling thread is not running within “task context”; otherwise, a TaskContext handle is returned that can be used with suspendTask() and wakeTask(), as well as anywhere a RequiredObject is used.
-
bool (*suspendTask)()
Suspends the current task.
Does not return until wakeTask() is called with the task’s TaskContext (see getTaskContext()).
Note
to avoid race-conditions between wakeTask() and suspendTask(), a wakeTask() that occurs before suspendTask() has been called will cause suspendTask() to return true immediately without waiting.
- Return
true when wakeTask() is called. If the current thread is not running in “task context” (i.e. getTaskContext() would return kInvalidTaskContext), then this function returns false immediately.
-
bool (*wakeTask)(TaskContext task)
Wakes a task previously suspended with suspendTask().
wakeTask() cannot be called on the current task context (false will be returned). Additional situations that will log (as a warning) and return false:
The task context given already has a pending wake
The task has finished
The task context given is sleeping or otherwise waiting on an event (cannot be woken)
The given TaskContext is not valid
Note
to avoid race-conditions between wakeTask() and suspendTask(), a wakeTask() that occurs before suspendTask() has been called will cause suspendTask() to return true immediately without waiting. The wakeTask() function returns immediately and does not wait for the suspended task to resume.
- Param task
The TaskContext (returned by getTaskContext()) for the task suspended with suspendTask().
- Return
true if the task was woken properly. false if a situation listed above occurs.
-
Semaphore *(*createSemaphore)(unsigned value)
Creates a fiber-aware semaphore primitive.
A semaphore is a gate that lets a certain number of tasks/threads through. This can also be used to throttle tasks (see addThrottledTask()). When the count of a semaphore goes negative tasks/threads will wait on the semaphore.
Note
Semaphore can be used for Throttling tasks.
Warning
Prefer using SemaphoreWrapper instead.
- Param value
The starting value of the semaphore. Limited to INT_MAX. 0 means that any attempt to wait on the semaphore will block until the semaphore is released.
- Return
A Semaphore object. When finished, dispose of the semaphore with destroySemaphore().
-
void (*destroySemaphore)(Semaphore *sema)
Destroys a semaphore object created by createSemaphore()
- Param sema
The semaphore to destroy.
-
void (*releaseSemaphore)(Semaphore *sema, unsigned count)
Releases (or posts, or signals) a semaphore.
If a task/thread is waiting on the semaphore when it is released, the task/thread is un-blocked and will be resumed. If no tasks/threads are waiting on the semaphore, the next task/thread that attempts to wait will resume immediately.
- Param sema
The semaphore to release.
- Param count
The number of tasks/threads to release.
-
bool (*timedWaitSemaphore)(Semaphore *sema, uint64_t timeoutNs)
Waits on a semaphore until it has been signaled or the timeout period expires.
If the semaphore has already been signaled, this function returns immediately.
- Param sema
The semaphore to wait on.
- Param timeoutNs
The relative timeout period in nanoseconds. Specify kInfinite to wait forever, or 0 to test immediately without waiting.
- Return
true if the semaphore count was decremented; false if the timeout period expired.
Creates a fiber-aware SharedMutex primitive.
A SharedMutex (also known as a read/write mutex) allows either multiple threads/tasks to share the primitive, or a single thread/task to own the primitive exclusively. Threads/tasks that request ownership of the primitive, whether shared or exclusive, will be blocked until they can be granted the access level requested. SharedMutex gives priority to exclusive access, but will not block additional shared access requests when exclusive access is requested.
Warning
Prefer using SharedMutexWrapper instead.
- Return
A SharedMutex object. When finished, dispose of the SharedMutex with destroySharedMutex().
Requests shared access on a SharedMutex object with a timeout period.
Use unlockSharedMutex() to release the shared lock. SharedMutex is not recursive.
- Param mutex
The SharedMutex object.
- Param timeoutNs
The relative timeout period in nanoseconds. Specify kInfinite to wait forever or 0 to test immediately without waiting.
- Return
true if the shared lock succeeded; false if timed out.
Requests exclusive access on a SharedMutex object with a timeout period.
Use unlockSharedMutex() to release the exclusive lock. SharedMutex is not recursive.
- Param mutex
The SharedMutex object.
- Param timeoutNs
The relative timeout period in nanoseconds. Specify kInfinite to wait forever or 0 to test immediately without waiting.
- Return
true if the exclusive lock succeeded; false if timed out.
Releases a shared or an exclusive lock on a SharedMutex object.
- Param mutex
The SharedMutex object.
Destroys a SharedMutex previously created with createSharedMutex().
- Param mutex
The SharedMutex object to destroy.
-
ConditionVariable *(*createConditionVariable)()
Creates a fiber-aware ConditionVariable primitive.
ConditionVariable is a synchronization primitive that, together with a Mutex, blocks one or more threads or tasks until a condition becomes true.
Warning
Prefer using ConditionVariableWrapper instead.
- Return
The ConditionVariable object. Destroy with destroyConditionVariable() when finished.
-
void (*destroyConditionVariable)(ConditionVariable *cv)
Destroys a previously-created ConditionVariable object.
- Param cv
The ConditionVariable to destroy
-
bool (*timedWaitConditionVariable)(ConditionVariable *cv, Mutex *m, uint64_t timeoutNs)
Waits on a ConditionVariable object until it is notified or the timeout period expires.
Prefer using the helper function, timedWaitConditionVariablePred().
The given Mutex must match the Mutex passed in by all other threads/tasks waiting on the ConditionVariable, and must be locked by the current thread/task. While waiting, the Mutex is unlocked. When the thread/task is notified the Mutex is re-locked before returning to the caller. ConditionVariables are allowed to spuriously wake up, so best practice is to check the variable in a loop and sleep if the variable still does not match desired.
- Param cv
The ConditionVariable to wait on.
- Param m
The Mutex that is locked by the current thread/task.
- Param timeoutNs
The relative timeout period in nanoseconds. Specify kInfinite to wait forever or 0 to test immediately without waiting.
- Return
true if the condition variable was notified; false if the timeout period expired.
-
void (*notifyConditionVariableOne)(ConditionVariable *cv)
Wakes one thread/task currently waiting on the ConditionVariable.
Note
Having the Mutex provided to waitConditionVariable() locked while calling this function is recommended but not required.
- Param cv
The condition variable to notify
-
void (*notifyConditionVariableAll)(ConditionVariable *cv)
Wakes all threads/tasks currently waiting on the ConditionVariable.
Note
Having the Mutex provided to waitConditionVariable() locked while calling this function is recommended but not required.
- Param cv
The condition variable to notify
-
bool (*changeTaskPriority)(TaskContext ctx, Priority newPrio)
Changes a tasks priority.
Note
This can be used to change a task to execute on the main thread when it next resumes when using Priority::eMain. If called from within the context of the running task, the task immediately suspends itself until resumed on the main thread with the next call to executeMainTasks(), at which point this function will return.
- Param ctx
The TaskContext returned by getTaskContext() or Future::task_if().
- Param newPrio
The Priority to change the task to.
- Return
true
if the priority change took effect;false
if the TaskContext is invalid.
-
void (*executeMainTasks)()
Executes all tasks that have been queued with Priority::eMain until they finish or yield.
Note
Scheduled tasks (addTaskIn() / addTaskAt()) with Priority::eMain will only be executed during the next executeMainTasks() call after the requisite time has elapsed.
-
Mutex *(*createRecursiveMutex)()
Creates a recursive mutex.
Note
Both createMutex() and createRecursiveMutex() return a Mutex object; it is up to the creator to ensure that the Mutex object is used properly. A Mutex created with createMutex() will call
std::terminate()
if recursively locked.Warning
Prefer using RecursiveMutexWrapper instead.
- Return
The created recursive mutex.
-
bool (*tryCancelTask)(TaskContext task)
Attempts to cancel an outstanding task.
If the task has already been started, has already been canceled or has completed,
false
is returned.If
true
is returned, then the task is guaranteed to never start, but every other side effect is as if the task completed. That is, any Counter objects that were passed to addTask() will be decremented; any blocking calls to waitForTask() will returntrue
. The Future object for this task will no longer wait, but any attempt to read a non-void
value from it will callstd::terminate()
. If the addTask() call provided a TaskDesc::cancel member, it will be called in the context of the calling thread and will finish before tryCancelTask() returns true.- Param task
The TaskContext returned by getTaskContext() or Future::task_if().
- Return
true
if the task was successfully canceled and state reset as described above.false
if the task has cannot be canceled because it has already started, already been canceled or has already finished.
-
TaskStorageKey (*allocTaskStorage)(TaskStorageDestructorFn fn)
Attempts to allocate task storage, which is similar to thread-local storage but specific to a task.
Allocates a “key” for Task Storage. A value can be stored at this key location (“slot”) that is specific to each task. When the task finishes,
fn
is executed for any non-nullptr
value stored in that slot.Values can be stored in the Task Storage slot with setTaskStorage() and getTaskStorage().
When Task Storage is no longer needed, use freeTaskStorage() to return the slot to the system.
Warning
The number of slots are very limited. If no slots are available, kInvalidTaskStorageKey is returned.
- Param fn
(Optional) A destructor function called when a task finishes with a non-
nullptr
value in the allocated slot. The value stored with setTaskStorage() is passed to the destructor. If a destructor is not desired,nullptr
can be passed.- Return
An opaque TaskStorageKey representing the slot for the requested Task Storage data. If no slots are available, kInvalidTaskStorageKey is returned.
-
void (*freeTaskStorage)(TaskStorageKey key)
Frees a Task Storage slot.
Note
Any associated destructor function registered with allocTaskStorage() will not be called for any data present in currently running tasks. Once freeTaskStorage() returns, the destructor function registered with allocTaskStorage() will not be called for any data on any tasks.
- Param key
The Task Storage key previously allocated with allocTaskStorage().
-
bool (*setTaskStorage)(TaskStorageKey key, void *value)
Stores a value at a slot in Task Storage for the current task.
The destructor function passed to allocTaskStorage() will be called with any non-
nullptr
values remaining in Task Storage at the associatedkey
when the task finishes.Warning
This function can only be called from task context, otherwise
false
is returned.- Param key
The Task Storage key previously allocated with allocTaskStorage().
- Param value
A value to store at the Task Storage slot described by
key
for the current task only.- Return
true
if the value was stored;false
otherwise.
-
void *(*getTaskStorage)(TaskStorageKey key)
Retrieves a value at a slot in Task Storage for the current task.
The destructor function passed to allocTaskStorage() will be called with any non-
nullptr
values remaining in Task Storage at the associatedkey
when the task finishes.Warning
This function can only be called from task context, otherwise
nullptr
is returned.- Param key
The Task Storage key previously allocated with allocTaskStorage().
- Return
The value previously passed to setTaskStorage(), or
nullptr
if not running in task context or a value was not previously passed to setTaskStorage() for the current task.
-
bool (*getTaskDebugInfo)(TaskContext task, TaskDebugInfo *out)
Retrieves debug information about a specific task.
Note
This information is intended for debug only and should not affect application state or decisions in the application.
Warning
Since carb.tasking is an inherently multi-threaded API, the values presented as task debug information may have changed in a worker thread in the short amount of time between when they were generated and when they were read by the application. As such, the debug information was true at a previous point in time and should not be considered necessarily up-to-date.
- Param task
The TaskContext to retrieve information about.
- Param out
[out] A structure to fill with debug information about
task
. The TaskDebugInfo::sizeOf field must be pre-filled by the caller. May benullptr
to determine iftask
is valid.- Return
true
if the TaskContext was valid andout
(if non-nullptr
) was filled with known information abouttask
.false
ifout
specified an unknown size ortask
does not refer to a valid task.
-
bool (*walkTaskDebugInfo)(TaskDebugInfo &info, TaskDebugInfoFn fn, void *context)
Walks all current tasks and calls a callback function with debug info for each.
Note
This information is intended for debug only and should not affect application state or decisions in the application.
Warning
Since carb.tasking is an inherently multi-threaded API, the values presented as task debug information may have changed in a worker thread in the short amount of time between when they were generated and when they were read by the application. As such, the debug information was true at a previous point in time and should not be considered necessarily up-to-date.
- Param info
A structure to fill with debug information about tasks encountered during the walk. The TaskDebugInfo::sizeOf field must be pre-filled by the caller.
- Param fn
A function to call for each task encountered. The function is called repeatedly with a different task each time, until all tasks have been visited or the callback function returns
false
.- Param context
Application-specific context information that is passed directly to each invocation of
fn
.
-
void (*reloadFiberEvents)()
Instructs ITasking to reload all IFiberEvents interfaces.
The IFiberEvents interface is used by ITasking to notify listeners that are interested in fiber-switch events. All IFiberEvents interfaces are queried from the carb::Framework by ITasking only at startup, or when changeParameters() is called, or when
reloadFiberEvents()
is called.Unlike changeParameters(), this function is safe to call from within a task, or from multiple threads simultaneously, and tasks can be added while this function is executing.
Note
This function is a task system synchronization point, requiring all task threads to synchronize and pause before reloading IFiberEvents interfaces. Generally this happens rapidly, but if a task thread is busy, the entire tasking system will wait for the task to finish or enter a wait state before reloading IFiberEvents interfaces.
Public Static Functions
-
static inline constexpr carb::InterfaceDesc getInterfaceDesc() noexcept
Returns information about this interface.
Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.
- Returns
The carb::InterfaceDesc struct with information about this interface.
-
static inline constexpr carb::InterfaceDesc getLatestInterfaceDesc() noexcept
Returns information about the latest version of this interface.
Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.
- Returns
The carb::InterfaceDesc struct with information about the latest version of this interface.