4.6 KiB
4.6 KiB
TaskManager
Basic Usage
Including Required Headers
#include <functional> // For std::bind
#include "TaskManager.h"
Registering Member Functions
class MyClass {
public:
void myMethod() {
Serial.println("My method called");
}
void methodWithParams(int value, String text) {
Serial.printf("Method called with %d and %s\n", value, text.c_str());
}
};
// Create an instance
MyClass myObject;
// Register member function
taskManager.registerTask("my_task", 1000,
std::bind(&MyClass::myMethod, &myObject));
// Register method with parameters
taskManager.registerTask("param_task", 2000,
std::bind(&MyClass::methodWithParams, &myObject, 42, "hello"));
Registering Lambda Functions
// Simple lambda
taskManager.registerTask("lambda_task", 3000, []() {
Serial.println("Lambda executed");
});
// Lambda with capture
int counter = 0;
taskManager.registerTask("counter_task", 4000, [&counter]() {
counter++;
Serial.printf("Counter: %d\n", counter);
});
// Lambda that calls multiple methods
taskManager.registerTask("multi_task", 5000, [&myObject]() {
myObject.myMethod();
// Do other work...
});
Registering Global Functions
void globalFunction() {
Serial.println("Global function called");
}
// Still supported for backward compatibility
taskManager.registerTask("global_task", 6000, globalFunction);
Advanced Examples
Binding to Different Object Types
class NetworkManager {
public:
void sendHeartbeat() { /* ... */ }
void checkConnection() { /* ... */ }
};
class SensorManager {
public:
void readSensors() { /* ... */ }
void calibrate() { /* ... */ }
};
NetworkManager network;
SensorManager sensors;
// Bind to different objects
taskManager.registerTask("heartbeat", 1000,
std::bind(&NetworkManager::sendHeartbeat, &network));
taskManager.registerTask("sensor_read", 500,
std::bind(&SensorManager::readSensors, &sensors));
Using std::placeholders for Complex Binding
#include <functional>
class ConfigManager {
public:
void updateConfig(int interval, bool enabled) {
Serial.printf("Updating config: interval=%d, enabled=%d\n", interval, enabled);
}
};
ConfigManager config;
// Use placeholders for complex parameter binding
using namespace std::placeholders;
taskManager.registerTask("config_update", 10000,
std::bind(&ConfigManager::updateConfig, &config, _1, _2));
Conditional Task Execution
class TaskController {
public:
bool shouldExecute() {
return millis() % 10000 < 5000; // Execute only in first 5 seconds of each 10-second cycle
}
void conditionalTask() {
if (shouldExecute()) {
Serial.println("Conditional task executed");
}
}
};
TaskController controller;
taskManager.registerTask("conditional", 1000,
std::bind(&TaskController::conditionalTask, &controller));
Benefits of Using std::bind
- Cleaner Code: No need for wrapper functions
- Direct Binding: Bind member functions directly to objects
- Parameter Passing: Easily pass parameters to bound methods
- Lambda Support: Use lambdas for complex logic
- Type Safety: Better type checking than function pointers
- Flexibility: Mix and match different callable types
Migration from Wrapper Functions
Before (with wrapper functions):
void discoverySendTask() { cluster.sendDiscovery(); }
void discoveryListenTask() { cluster.listenForDiscovery(); }
taskManager.registerTask("discovery_send", interval, discoverySendTask);
taskManager.registerTask("discovery_listen", interval, discoveryListenTask);
After (with std::bind):
taskManager.registerTask("discovery_send", interval,
std::bind(&ClusterManager::sendDiscovery, &cluster));
taskManager.registerTask("discovery_listen", interval,
std::bind(&ClusterManager::listenForDiscovery, &cluster));
Performance Considerations
std::bindcreates a callable object that may have a small overhead compared to direct function pointers- For high-frequency tasks, consider the performance impact
- The overhead is typically negligible for most embedded applications
- The TaskManager stores bound functions efficiently in a registry
Compatibility
- The new
std::bindsupport is fully backward compatible - Existing code using function pointers will continue to work
- You can mix both approaches in the same project
- All existing TaskManager methods remain unchanged