Skip to content

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

enum class Type { ONCE, FOREVER };
enum class State : uint8_t { IDLE, RUNNING, FINALIZING };

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

#ifdef MYCILA_JSON_SUPPORT
void toJson(const JsonObject& root) const;
#endif

TaskManager

Constructor

explicit TaskManager(const char* name);

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

#ifdef MYCILA_JSON_SUPPORT
void toJson(const JsonObject& root) const;
#endif

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.