Inherits from: Task
The If
class provides a conditional control flow task in the task framework. It evaluates a
condition and then executes either a "then" task or an "else" task based on the result. This enables
building complex task workflows with conditional branching while maintaining the signal-based
communication patterns of the framework.
class If : public Task {
public:
// Type definition for condition functions
using ConditionFunction = std::function;
// Constructor
explicit If(ConditionFunction condition);
// Configuration methods (fluent interface)
If& then(Task* task);
If& else_(Task* task);
// Execution methods
void execute(const ArgumentPack& args = {});
std::future executeAsync(const ArgumentPack& args = {});
private:
ConditionFunction m_condition;
std::shared_ptr m_thenTask;
std::shared_ptr m_elseTask;
};
Signal | Type | Description | Arguments |
---|---|---|---|
started |
Simple | Emitted when execution begins | None |
finished |
Simple | Emitted when execution completes | None |
conditionEvaluated |
Simple | Emitted after condition evaluation | None |
branchSelected |
Data | Reports which branch was selected | bool (result), string (branch name) |
thenExecuted |
Simple | Emitted when the then branch completes | None |
elseExecuted |
Simple | Emitted when the else branch completes | None |
noBranchExecuted |
Simple | Emitted when no branch task was available | None |
log , warn , error |
Data | Standard logging signals | string (message) |
// Creating a conditional task
If checkValue([](const ArgumentPack& args) {
// Condition that evaluates whether the first argument > 10
if (args.empty()) return false;
return args.get(0) > 10;
});
// Configure the branches
MyTask highValueTask("Process high value");
MyTask lowValueTask("Process low value");
checkValue->then(&highValueTask)
->else_(&lowValueTask);
// Connect to signals
checkValue.connectData("branchSelected", [](const ArgumentPack& args) {
bool result = args.get(0);
std::string branch = args.get(1);
std::cout << "Selected branch: " << branch
<< " (condition: " << (result ? "true" : "false") << ")" << std::endl;
});
// Create arguments
ArgumentPack args;
args.add(15); // This will cause the then branch to execute
// Execute the conditional task
checkValue->execute(args);
The condition function determines which branch is executed. Here are several examples:
// Simple condition based on arguments
auto condition1 = [](const ArgumentPack& args) {
return args.get(0) > 10;
};
// Condition that captures external state
int threshold = 5;
auto condition2 = [threshold](const ArgumentPack& args) {
return args.get(0) > threshold;
};
// Condition that doesn't use arguments
auto condition3 = [](const ArgumentPack&) {
return std::time(nullptr) % 2 == 0; // Condition based on current time
};
// Condition that uses a component's state
auto counter = std::make_shared(0, 0, 100);
auto condition4 = [counter](const ArgumentPack&) {
return counter->getValue() > 50;
};
The If task supports asynchronous execution for non-blocking operations:
// Create arguments
ArgumentPack args;
args.add(5); // This will cause the else branch to execute
// Execute asynchronously
std::future future = conditionalTask->executeAsync(args);
// Do other work while the conditional task executes
// ...
// Wait for completion when needed
future.wait();
Conditional tasks can be nested to create complex decision trees:
// Create outer condition
auto outerCondition = std::make_shared([](const ArgumentPack& args) {
return args.get(0) > 0;
});
// Create inner condition (for positive numbers)
auto innerCondition = std::make_shared([](const ArgumentPack& args) {
return args.get(0) > 10;
});
// Configure inner condition
auto highValueTask = std::make_shared("High value");
auto mediumValueTask = std::make_shared("Medium value");
innerCondition->then(highValueTask)
->else_(mediumValueTask);
// Configure outer condition
auto negativeValueTask = std::make_shared("Negative value");
outerCondition->then(innerCondition) // Use inner condition as the then branch
->else_(negativeValueTask);
// Execute the nested conditions
ArgumentPack args;
args.add(15); // Will execute highValueTask
outerCondition->execute(args);
The If task integrates seamlessly with the ThreadPool for parallel conditional execution:
// Create a thread pool
auto pool = std::make_shared();
// Create multiple conditional tasks
for (int i = 0; i < 5; i++) {
// Create condition
auto task = std::make_shared([](const ArgumentPack& args) {
return args.get(0) % 2 == 0; // Check if value is even
});
// Configure branches
auto thenTask = std::make_shared("EvenProcessor-" + std::to_string(i));
auto elseTask = std::make_shared("OddProcessor-" + std::to_string(i));
task->then(thenTask)
->else_(elseTask);
// Add to thread pool with arguments
pool->add(std::make_shared([task, i]() {
ArgumentPack args;
args.add(i);
task->execute(args);
}));
}
// Execute all tasks in parallel
pool->exec();