ImFusion C++ SDK 4.5.0
ImFusion::TaskManager Class Referencethreadsafe

#include <ImFusion/Stream/TaskManager.h>

Manages asynchronous tasks with result storage using a thread pool. More...

Detailed Description

Manages asynchronous tasks with result storage using a thread pool.

TaskManager provides a simple way to execute functions asynchronously and track their completion. Each task is assigned a unique TaskId that can be used to wait for completion or retrieve results. Tasks are executed on a fixed-size thread pool for efficient resource utilization.

Unlike Threading::ThreadPool, which returns raw std::future objects that the caller must manage, TaskManager retains ownership of results and provides a higher-level API for tracking completion status, waiting for individual or all tasks, and retrieving results by ID.

In addition to executing new tasks, TaskManager can also track existing std::future objects, allowing you to combine futures from different sources and wait for them together. Deferred futures (created with std::launch::deferred) are considered immediately ready (isReady() returns true) but are evaluated lazily — the actual computation runs when the result is requested via takeResult()/takeAllResults() or explicitly forced via waitAll()/waitFor().

Features:

  • Execute functions asynchronously using a thread pool
  • Track existing std::future objects from external sources
  • Result storage for non-void tasks, retrievable by task ID
  • Wait for individual tasks or all tasks to complete
  • Query task completion status
Note
Results are stored until explicitly taken with takeResult() or the TaskManager is destroyed. For long-running applications, use takeResult() to retrieve and free completed results.

Example usage running a single task many times:

TaskManager mgr{8}; // Uses 8 parallel threads
std::string basename = "/path/to/folder/data_prefix_";
auto loadData = [](const std::string& filepath) -> std::unique_ptr<SharedImageSet> {
// load data from file
data = ...
return data;
};
// Load a large number of data, but only run 8 parallel loading tasks in the thread pool
for (int i = 0; i < 100; i++)
mgr.addTask(loadData, basename + std::to_string(i) + ".bin");
mgr.waitAll();
void waitAll()
Blocks until all tasks have completed.
std::vector< T > takeAllResults(std::vector< TaskId > *outTaskIds=nullptr)
Retrieves and removes all stored results of the specified type from tasks that have already completed...
Definition TaskManager.h:297
TaskManager(int numThreads=std::max< int >(1, static_cast< int >(std::thread::hardware_concurrency())))
Creates a TaskManager with a thread pool.
TaskId addTask(Func &&func, Args &&... args)
Adds an async task to be executed on the thread pool.
Definition TaskManager.h:204
T to_string(T... args)

More complex example with different types of tasks and futures:

TaskManager mgr; // Uses hardware_concurrency threads
// Task with return value
auto id1 = mgr.addTask([] { return computeResult(); });
// Void task
auto id2 = mgr.addTask([] { performWork(); });
// Add an existing future from another source
std::future<Data> externalFuture = someAsyncOperation();
auto id3 = mgr.addFuture(std::move(externalFuture));
// Add a deferred future (evaluated lazily on takeResult/waitAll/waitFor)
auto deferredFuture = std::async(std::launch::deferred, [] { return 42; });
auto id4 = mgr.addFuture(std::move(deferredFuture));
// Wait for specific task and take result
mgr.waitFor(id1);
std::optional<int> result = mgr.takeResult<int>(id1);
// Wait for all tasks including the external future
mgr.waitAll();
std::optional<Data> data = mgr.takeResult<Data>(id3);
T async(T... args)
std::optional< T > takeResult(TaskId taskId)
Retrieves and removes the stored result for a completed task.
Definition TaskManager.h:273
TaskId addFuture(std::future< T > &&future)
Adds an existing future to be tracked by the TaskManager.
Definition TaskManager.h:229
void waitFor(TaskId taskId)
Blocks until the specified task has completed.
Note
Threadsafe class: Member functions can be called concurrently from any thread.

Classes

class  TaskId
 Opaque identifier for a task managed by TaskManager. More...

Public Member Functions

 TaskManager (int numThreads=std::max< int >(1, static_cast< int >(std::thread::hardware_concurrency())))
 Creates a TaskManager with a thread pool.
 TaskManager (const std::string threadNamePrefix)
 Creates a TaskManager with default number of threads.
 TaskManager (int numThreads, const std::string threadNamePrefix)
 Creates a TaskManager with given number of threads and specified prefix for thread names.
template<typename Func, typename... Args>
TaskId addTask (Func &&func, Args &&... args)
 Adds an async task to be executed on the thread pool.
template<typename T>
TaskId addFuture (std::future< T > &&future)
 Adds an existing future to be tracked by the TaskManager.
bool allReady ()
 Checks if all tasks are ready (completed or available for immediate evaluation).
void waitAll ()
 Blocks until all tasks have completed.
bool isReady (TaskId taskId)
 Checks if a specific task is ready (completed or available for immediate evaluation).
void waitFor (TaskId taskId)
 Blocks until the specified task has completed.
template<typename T>
std::optional< T > takeResult (TaskId taskId)
 Retrieves and removes the stored result for a completed task.
template<typename T>
std::vector< T > takeAllResults (std::vector< TaskId > *outTaskIds=nullptr)
 Retrieves and removes all stored results of the specified type from tasks that have already completed.
int numThreads () const
 Returns the number of threads in the thread pool.

Constructor & Destructor Documentation

◆ TaskManager() [1/2]

ImFusion::TaskManager::TaskManager ( int numThreads = std::max< int >(1, static_cast< int >(std::thread::hardware_concurrency())))
explicit

Creates a TaskManager with a thread pool.

Parameters
numThreadsNumber of worker threads. Defaults to hardware concurrency.

◆ TaskManager() [2/2]

ImFusion::TaskManager::TaskManager ( const std::string threadNamePrefix)
explicit

Creates a TaskManager with default number of threads.

Parameters
threadNamePrefixPrefix for thread names in the thread pool (
See also
ThreadPool::setThreadNames).

Member Function Documentation

◆ addTask()

template<typename Func, typename... Args>
TaskId ImFusion::TaskManager::addTask ( Func && func,
Args &&... args )
inline

Adds an async task to be executed on the thread pool.

Works for both void and non-void return types.

◆ addFuture()

template<typename T>
TaskId ImFusion::TaskManager::addFuture ( std::future< T > && future)
inline

Adds an existing future to be tracked by the TaskManager.

Async futures are moved to finished once ready. Deferred futures are considered to be "ready-for-evaluation" and evaluated lazily on takeResult()/waitAll()/waitFor().

Note
In multi-threaded contexts, new tasks might have been enqueued immediately after the call.

◆ allReady()

bool ImFusion::TaskManager::allReady ( )

Checks if all tasks are ready (completed or available for immediate evaluation).

Deferred futures are considered ready but are not evaluated by this method.

Note
The result may be outdated immediately after the call in multi-threaded contexts.

◆ waitAll()

void ImFusion::TaskManager::waitAll ( )

Blocks until all tasks have completed.

Evaluates all deferred futures and waits for all async tasks to finish.

◆ isReady()

bool ImFusion::TaskManager::isReady ( TaskId taskId)

Checks if a specific task is ready (completed or available for immediate evaluation).

Deferred futures are considered ready but are not evaluated by this method. Returns true for unknown task IDs (they are not running).

Note
The result may be outdated immediately after the call in multi-threaded contexts.

◆ waitFor()

void ImFusion::TaskManager::waitFor ( TaskId taskId)

Blocks until the specified task has completed.

Evaluates the deferred future if applicable. Returns immediately for unknown task IDs.

◆ takeResult()

template<typename T>
std::optional< T > ImFusion::TaskManager::takeResult ( TaskId taskId)
inline

Retrieves and removes the stored result for a completed task.

Evaluates the deferred future if it has not been consumed yet. This transfers ownership of the result to the caller and frees the internal storage.

Returns
The result value, or std::nullopt if the task ID is unknown, the task hasn't completed, the result was already taken, or the type doesn't match.

◆ takeAllResults()

template<typename T>
std::vector< T > ImFusion::TaskManager::takeAllResults ( std::vector< TaskId > * outTaskIds = nullptr)
inline

Retrieves and removes all stored results of the specified type from tasks that have already completed.

Evaluates deferred futures of matching type that have not been consumed yet. This transfers ownership of all matching results to the caller and frees the internal storage.

Parameters
outTaskIdsOutput parameter that will be filled with the task IDs corresponding to each result.
Returns
A vector of result values. Only tasks with results of type T are included.

The documentation for this class was generated from the following file:
  • ImFusion/Stream/TaskManager.h
Search Tab / S to search, Esc to close