TaskGraph API Reference
The TaskGraph class manages the DAG (Directed Acyclic Graph) of tasks and their dependencies.
Class Overview
namespace hts {
class TaskGraph {
public:
TaskGraph();
~TaskGraph();
// Task Creation
std::shared_ptr<Task> add_task(DeviceType device, const std::string& name = "");
std::shared_ptr<Task> add_task(const TaskConfig& config);
// Task Removal
bool remove_task(uint64_t task_id);
// Dependencies
Error add_dependency(uint64_t predecessor_id, uint64_t successor_id);
Error remove_dependency(uint64_t predecessor_id, uint64_t successor_id);
// Queries
bool has_dependency(uint64_t successor_id, uint64_t predecessor_id) const;
std::vector<uint64_t> get_predecessors(uint64_t task_id) const;
std::vector<uint64_t> get_successors(uint64_t task_id) const;
std::shared_ptr<Task> get_task(uint64_t task_id) const;
// Graph Properties
size_t num_tasks() const;
size_t num_dependencies() const;
std::vector<uint64_t> topological_sort() const;
std::vector<uint64_t> get_critical_path() const;
std::vector<uint64_t> find_orphan_tasks() const;
// Validation
Error validate() const;
bool has_cycles() const;
std::vector<uint64_t> detect_cycles() const;
// Execution Info
std::vector<uint64_t> get_ready_tasks() const;
bool is_task_ready(uint64_t task_id) const;
bool is_task_completed(uint64_t task_id) const;
bool is_task_failed(uint64_t task_id) const;
// Reset
void reset();
void reset_task_status();
};
} // namespace hts2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Constructor
TaskGraph()
Creates an empty task graph.
TaskGraph graph;Task Creation Methods
add_task()
Adds a new task to the graph.
std::shared_ptr<Task> add_task(DeviceType device, const std::string& name = "");
std::shared_ptr<Task> add_task(const TaskConfig& config);2
Parameters:
device: The device type (CPU or GPU)name: Optional human-readable name for the taskconfig: Task configuration structure
Returns:
- Shared pointer to the created Task
TaskConfig Structure:
struct TaskConfig {
std::string name; // Task name
DeviceType device = DeviceType::CPU; // Device type
int priority = 0; // Priority (higher = more important)
size_t memory_requirement = 0; // Memory in bytes
std::chrono::milliseconds timeout{0}; // Execution timeout
};2
3
4
5
6
7
Example:
// Simple task creation
auto cpu_task = graph.add_task(DeviceType::CPU, "PreprocessData");
auto gpu_task = graph.add_task(DeviceType::GPU, "GPUCompute");
// Task with configuration
TaskConfig config;
config.name = "ComplexTask";
config.device = DeviceType::GPU;
config.priority = 10;
config.memory_requirement = 256 * 1024 * 1024; // 256 MB
config.timeout = std::chrono::seconds(30);
auto task = graph.add_task(config);2
3
4
5
6
7
8
9
10
11
12
13
Task Removal Methods
remove_task()
Removes a task from the graph.
bool remove_task(uint64_t task_id);Parameters:
task_id: ID of the task to remove
Returns:
trueif task was removed,falseif not found
Example:
auto task = graph.add_task(DeviceType::CPU, "TemporaryTask");
if (graph.remove_task(task->id())) {
std::cout << "Task removed" << std::endl;
}2
3
4
Note: Removing a task also removes all its dependencies.
Dependency Methods
add_dependency()
Adds a dependency between two tasks.
Error add_dependency(uint64_t predecessor_id, uint64_t successor_id);Parameters:
predecessor_id: ID of the task that must complete firstsuccessor_id: ID of the task that depends on the predecessor
Returns:
Errorobject indicating success or failure
Example:
auto taskA = graph.add_task(DeviceType::CPU, "TaskA");
auto taskB = graph.add_task(DeviceType::GPU, "TaskB");
Error err = graph.add_dependency(taskA->id(), taskB->id());
if (!err.ok()) {
std::cerr << "Failed to add dependency: " << err.message() << std::endl;
}2
3
4
5
6
7
Errors:
CycleDetected: Adding this dependency would create a cycleTaskNotFound: One or both task IDs are invalid
remove_dependency()
Removes a dependency between two tasks.
Error remove_dependency(uint64_t predecessor_id, uint64_t successor_id);Parameters:
predecessor_id: ID of the predecessor tasksuccessor_id: ID of the successor task
Returns:
Errorobject indicating success or failure
has_dependency()
Checks if a dependency exists between two tasks.
bool has_dependency(uint64_t successor_id, uint64_t predecessor_id) const;Parameters:
successor_id: ID of the successor taskpredecessor_id: ID of the predecessor task
Returns:
trueif dependency exists,falseotherwise
Example:
if (graph.has_dependency(taskB->id(), taskA->id())) {
std::cout << "TaskB depends on TaskA" << std::endl;
}2
3
Query Methods
get_predecessors()
Gets all predecessor tasks of a given task.
std::vector<uint64_t> get_predecessors(uint64_t task_id) const;Parameters:
task_id: ID of the task
Returns:
- Vector of predecessor task IDs
Example:
auto predecessors = graph.get_predecessors(taskB->id());
std::cout << "TaskB has " << predecessors.size() << " predecessors" << std::endl;
for (uint64_t pred_id : predecessors) {
auto pred_task = graph.get_task(pred_id);
std::cout << " - " << pred_task->get_name() << std::endl;
}2
3
4
5
6
get_successors()
Gets all successor tasks of a given task.
std::vector<uint64_t> get_successors(uint64_t task_id) const;Parameters:
task_id: ID of the task
Returns:
- Vector of successor task IDs
get_task()
Gets a task by its ID.
std::shared_ptr<Task> get_task(uint64_t task_id) const;Parameters:
task_id: ID of the task
Returns:
- Shared pointer to the Task, or nullptr if not found
Graph Property Methods
num_tasks()
Returns the number of tasks in the graph.
size_t num_tasks() const;Example:
std::cout << "Total tasks: " << graph.num_tasks() << std::endl;num_dependencies()
Returns the number of dependencies in the graph.
size_t num_dependencies() const;topological_sort()
Returns a topological ordering of tasks.
std::vector<uint64_t> topological_sort() const;Returns:
- Vector of task IDs in execution order
Example:
auto order = graph.topological_sort();
std::cout << "Execution order:" << std::endl;
for (uint64_t task_id : order) {
auto task = graph.get_task(task_id);
std::cout << " " << task->get_name() << std::endl;
}2
3
4
5
6
get_critical_path()
Returns the critical path (longest dependency chain).
std::vector<uint64_t> get_critical_path() const;Returns:
- Vector of task IDs on the critical path
Example:
auto critical_path = graph.get_critical_path();
std::cout << "Critical path length: " << critical_path.size() << " tasks" << std::endl;2
find_orphan_tasks()
Finds tasks with no predecessors or successors.
std::vector<uint64_t> find_orphan_tasks() const;Returns:
- Vector of orphan task IDs
Validation Methods
validate()
Validates the entire graph.
Error validate() const;Returns:
Errorobject indicating success or failure
Checks:
- No cycles exist
- All tasks have valid configurations
- All dependencies reference valid tasks
- No orphan tasks (optional warning)
Example:
Error err = graph.validate();
if (!err.ok()) {
std::cerr << "Graph validation failed: " << err.message() << std::endl;
}2
3
4
has_cycles()
Checks if the graph contains cycles.
bool has_cycles() const;Returns:
trueif cycles exist,falseotherwise
detect_cycles()
Detects and returns all cycles in the graph.
std::vector<uint64_t> detect_cycles() const;Returns:
- Vector of task IDs forming a cycle (empty if no cycles)
Execution Info Methods
get_ready_tasks()
Gets all tasks that are ready for execution.
std::vector<uint64_t> get_ready_tasks() const;Returns:
- Vector of task IDs that are ready (all predecessors completed)
is_task_ready()
Checks if a task is ready for execution.
bool is_task_ready(uint64_t task_id) const;Returns:
trueif all predecessors completed,falseotherwise
is_task_completed()
Checks if a task has completed successfully.
bool is_task_completed(uint64_t task_id) const;is_task_failed()
Checks if a task has failed.
bool is_task_failed(uint64_t task_id) const;Reset Methods
reset()
Resets the entire graph (removes all tasks and dependencies).
void reset();reset_task_status()
Resets only task statuses without removing tasks or dependencies.
void reset_task_status();Example:
// First execution
scheduler.init(&graph);
scheduler.execute();
scheduler.wait_for_completion();
// Reset statuses for re-execution
graph.reset_task_status();
// Re-execute
scheduler.init(&graph);
scheduler.execute();
scheduler.wait_for_completion();2
3
4
5
6
7
8
9
10
11
12
Complete Example
#include <hts/task_graph.hpp>
using namespace hts;
int main() {
TaskGraph graph;
// Create tasks
auto load_data = graph.add_task(DeviceType::CPU, "LoadData");
auto preprocess = graph.add_task(DeviceType::CPU, "Preprocess");
auto gpu_compute = graph.add_task(DeviceType::GPU, "GPUCompute");
auto save_results = graph.add_task(DeviceType::CPU, "SaveResults");
// Configure tasks
load_data->set_cpu_function(load_data_func);
preprocess->set_cpu_function(preprocess_func);
gpu_compute->set_gpu_function(gpu_kernel);
save_results->set_cpu_function(save_func);
// Add dependencies
graph.add_dependency(load_data->id(), preprocess->id());
graph.add_dependency(preprocess->id(), gpu_compute->id());
graph.add_dependency(gpu_compute->id(), save_results->id());
// Validate
Error err = graph.validate();
if (!err.ok()) {
std::cerr << "Invalid graph: " << err.message() << std::endl;
return 1;
}
// Inspect
std::cout << "Tasks: " << graph.num_tasks() << std::endl;
std::cout << "Dependencies: " << graph.num_dependencies() << std::endl;
auto critical_path = graph.get_critical_path();
std::cout << "Critical path: " << critical_path.size() << " tasks" << std::endl;
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Related Pages
- Scheduler API — Scheduler reference
- TaskBuilder API — TaskBuilder reference
- Task Graph Guide — Task guide