API Reference¶
The full C++ API reference is available in the C++ API section (generated by Doxygen via mkdoxy).
Class Overview¶
Mycila::TaskManager
└── holds Mycila::Task (owned via shared_ptr, or referenced)
Mycila::Task
├── Function : std::function<void(void*)> (or void() with NO_PARAMS)
├── Predicate : std::function<bool()>
└── DoneCallback : std::function<void(const Task&, uint32_t)>
Mycila::BinStatistics
└── power-of-2 histogram used by Task and TaskManager profiling
Type Aliases¶
namespace Mycila {
class Task {
public:
enum class Type { ONCE, FOREVER };
#ifndef MYCILA_TASK_MANAGER_NO_PARAMS
typedef std::function<void(void* params)> Function;
#else
typedef std::function<void()> Function;
#endif
typedef std::function<void(const Task& me, uint32_t elapsed)> DoneCallback;
typedef std::function<bool()> Predicate;
};
}
DoneCallback::elapsed is the execution time in milliseconds, measured with millis() around the task function.
Task¶
Constructors¶
Task(const char* name, Function fn); // Type::FOREVER
Task(const char* name, Type type, Function fn);
Both constructors assert() that the name and the function are non-null. Function is std::function<void(void*)>, or std::function<void()> with MYCILA_TASK_MANAGER_NO_PARAMS.
Copy semantics¶
Task stores its function in a const Function member, which deletes the copy assignment operator. The copy constructor is implicitly generated, so it compiles — but it is a shallow copy that duplicates the BinStatistics pointer:
Mycila::Task a("a", fn);
Mycila::Task b("b", fn);
b = a; // error: copy assignment operator is implicitly deleted
Mycila::Task c(a); // compiles, but double-frees _stats if profiling is enabled
Prefer declaring tasks at file scope, as members, or via TaskManager::newTask().
Destruction¶
The destructor frees the task's BinStatistics, so a profiled task must not be destroyed while still being polled by a manager.
Types¶
State describes the current execution, not the schedule: RUNNING is the task function, FINALIZING is the onDone callback plus statistics recording after the function returned, and IDLE is neither.
Configuration¶
Task& setType(Type type); // ONCE pauses the task
Task& setEnabled(bool enabled); // installs a true/false predicate
Task& setEnabledWhen(Predicate predicate); // dynamic condition
Task& setInterval(uint32_t intervalMillis); // 0 = every loop pass
Task& onDone(DoneCallback callback); // requires !NO_CALLBACKS
Task& setData(void* params); // requires !NO_PARAMS
setType() returns early when the type is unchanged, so it does not re-pause an already-ONCE task. setEnabled(false) installs a predicate that always returns false; setEnabled(true) clears the predicate. A task is enabled by default (no predicate).
Control¶
Task& pause();
Task& resume(uint32_t delayMillis = 0); // delay re-bases the interval clock
Task& requestEarlyRun(); // next run ignores the interval
Task& forceRun(); // run now, ignoring pause/enabled
bool tryRun(); // run if scheduled and due
resume() with a non-zero delay sets the interval and sets lastEndTime() to now, so the first run happens after delayMillis. resume() with no delay un-pauses without touching the interval.
Queries¶
const char* name() const;
Type type() const;
uint32_t interval() const;
uint32_t remainingTime() const; // ms until the next run
uint32_t lastEndTime() const; // 0 = never ran / early run requested
void* data() const; // requires !NO_PARAMS
bool enabled() const; // predicate result
bool paused() const;
State state() const; // IDLE, RUNNING or FINALIZING
bool running() const; // state() == RUNNING (function only)
bool active() const; // state() != IDLE (function or onDone)
bool idle() const; // state() == IDLE
bool scheduled() const; // enabled() && !paused()
bool shouldRun() const; // scheduled() && interval elapsed
bool earlyRunRequested() const; // lastEndTime() == 0
Profiling¶
void enableProfiling(uint8_t binCount = 10, uint32_t unitDividerMillis = 1);
void disableProfiling();
bool profiled() const;
const BinStatistics* statistics() const; // requires !NO_STATS
Task& log();
enableProfiling() is a no-op if statistics already exist — it never reconfigures an existing histogram. profiled() returns false and statistics() is not compiled when MYCILA_TASK_MANAGER_NO_STATS is defined.
JSON¶
TaskManager¶
Constructor¶
Managing Tasks¶
Task& newTask(const char* name, Task::Function fn); // owned
Task& newTask(const char* name, Task::Type type, Task::Function fn); // owned
void addTask(Task& task); // referenced
void removeTask(Task& task);
size_t tasks() const;
bool empty() const;
const char* name() const;
Execution¶
size_t loop(uint32_t delayMillis = 10); // returns the number of tasks executed
bool waitForAllTasksToComplete(uint32_t timeoutMs = 0) const;
bool asyncStart(uint32_t stackSize = 4096,
BaseType_t priority = -1,
BaseType_t coreID = -1,
uint32_t delay = 10,
bool wdt = false);
void asyncStop();
static bool configureWDT(uint32_t timeoutSeconds = CONFIG_ESP_TASK_WDT_TIMEOUT_S,
bool panic = true);
asyncStart() returns false without side effects if the manager is already running. asyncStop() is safe to call on a manager that was never started. configureWDT() returns true when the TWDT was initialised or successfully reconfigured, so it is safe to call on an already-running watchdog.
Control¶
State state() const; // RUNNING, PAUSING or PAUSED
bool paused() const; // state() == PAUSED
void pause(); // request; stop dispatching between two executions
void resume(); // reopen the gate; task states untouched
bool waitForPaused(uint32_t timeoutMs = 0); // wait for the confirmation, false on timeout
void pauseTasks(); // pause every task (manager keeps dispatching)
void resumeTasks(uint32_t delayMillis = 0); // resume every task
void setEnabled(bool enabled);
pause() / resume() operate on the manager's dispatch gate and never modify a task. pauseTasks() / resumeTasks() are the per-task broadcasts, which is what TaskManager::pause() / resume() actually did in v4.
Profiling¶
void enableProfiling(uint8_t taskManagerBinCount, uint8_t taskBinCount, uint32_t unitDividerMillis = 1);
void enableProfiling(uint8_t taskManagerBinCount = 12, uint32_t unitDividerMillis = 1);
void disableProfiling();
void log();
The two-argument form enableProfiling(bins, divider) configures the manager only. The three-argument form configures the manager and every task currently registered. Both allocate a histogram only if one does not already exist, so calling them again never reconfigures the bins — call disableProfiling() first if you need different parameters.
JSON¶
BinStatistics¶
Power-of-2 histogram used by the profiling subsystem.
explicit BinStatistics(uint8_t binCount, uint32_t unitDivider = 1);
uint32_t unitDivider() const;
uint8_t bins() const;
uint32_t count() const;
uint16_t bin(uint8_t index) const;
void clear();
void record(uint32_t elapsed);
#ifdef MYCILA_JSON_SUPPORT
void toJson(const JsonObject& root) const;
#endif
You normally never construct one directly — enableProfiling() creates it.
Notes on Naming and Behaviour¶
forceRun() semantics
forceRun() ignores paused() and enabled() and always executes the task. It still updates lastEndTime(), records statistics and invokes the done callback.
requestEarlyRun() semantics
requestEarlyRun() sets lastEndTime() = 0, which also makes earlyRunRequested() return true. The task still has to pass the paused() / enabled() checks.