An open API service indexing awesome lists of open source software.

https://github.com/esptoolkit/esp-worker

High-level task management for FreeRTOS so you can spawn work units, extend stacks into PSRAM and await completion with joins.
https://github.com/esptoolkit/esp-worker

async embedded esp32 iot process task thread worker

Last synced: 18 days ago
JSON representation

High-level task management for FreeRTOS so you can spawn work units, extend stacks into PSRAM and await completion with joins.

Awesome Lists containing this project

README

          

# ESPWorker

ESPWorker is a C++17 helper library for ESP32 projects that want FreeRTOS power without the boilerplate. It wraps task creation, joins, diagnostics, PSRAM stacks, and lifecycle events into a simple API that works with both Arduino-ESP32 and ESP-IDF.

## CI / Release / License
[![CI](https://github.com/ESPToolKit/esp-worker/actions/workflows/ci.yml/badge.svg)](https://github.com/ESPToolKit/esp-worker/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/ESPToolKit/esp-worker?sort=semver)](https://github.com/ESPToolKit/esp-worker/releases)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)

## Features
- Works with FreeRTOS tasks while keeping `std::function`/lambda ergonomics.
- Joinable workers with runtime diagnostics (`JobDiag`) and cooperative destruction.
- Pull worker-pool metrics (`WorkerDiag`) including counts and runtime stats.
- Optional PSRAM stacks (`spawnExt`) for memory hungry jobs.
- Thread-safe event and error callbacks so firmware can log or react centrally.
- Configurable defaults and guardrails (max workers, priorities, affinities).

## Examples
Quick start:

```cpp
#include

ESPWorker worker;

void setup() {
Serial.begin(115200);

worker.init({
.maxWorkers = 4,
.stackSizeBytes = 4096,
.priority = 1,
.coreId = tskNO_AFFINITY,
.enableExternalStacks = true,
});

worker.onEvent([](WorkerEvent event) {
Serial.printf("[worker] %s\n", worker.eventToString(event));
});
worker.onError([](WorkerError error) {
Serial.printf("[worker][error] %s\n", worker.errorToString(error));
});

WorkerResult result = worker.spawn([]() {
Serial.println("[worker] running");
vTaskDelay(pdMS_TO_TICKS(250));
}, {
.stackSizeBytes = 16 * 1024,
.priority = 3,
.name = "sensor-task",
});

if (result) {
result.handler->wait(pdMS_TO_TICKS(1000)); // or destroy() for long-lived loops
}

worker.deinit();
}
```

Need deterministic cleanup? Store the handler and call `destroy()` when shutting down:

```cpp
WorkerResult job = worker.spawn([](){ /* ... */ });
if (job) {
// Stop the task cooperatively
job.handler->destroy();
}
```

Check the runnable examples under `examples/`:
- `examples/basic_worker` – spawns workers, waits for completion, prints diagnostics.
- `examples/psram_stack` – uses `spawnExt` to place heavy stacks in PSRAM.

## Gotchas
- Always call `worker.init()` once before spawning tasks. Each ESPWorker instance controls its own limits.
- Call `worker.deinit()` during shutdown/reset paths. It is safe before `init()` and safe to call repeatedly.
- `spawn` creates persistent FreeRTOS tasks; remember to end the lambda (return) or `destroy()` the handler to reclaim slots.
- Errors such as `MaxWorkersReached`, `TaskCreateFailed`, or `ExternalStackUnsupported` are reported in the returned `WorkerResult` _and_ via the error callback.
- PSRAM stack requests fail fast with `ExternalStackUnsupported` when caps-based task allocation is unavailable, PSRAM is missing, or external stacks are disabled.

## API Reference
- `void init(const ESPWorker::Config& config)` – sets defaults (max workers, default stack-bytes/priority/core, PSRAM allowance).
- `void deinit()` / `bool isInitialized() const` – explicit teardown and lifecycle state checks; `deinit()` is idempotent and safe pre-init.
- `WorkerResult spawn(TaskCallback cb, const WorkerConfig& config = {})` – create a worker. The returned handler provides `wait()` and `destroy()` helpers plus per-job diagnostics.
- `WorkerResult spawnExt(...)` – identical to `spawn` but forces PSRAM stacks using `xTaskCreatePinnedToCoreWithCaps(...)`.
- `size_t activeWorkers() const` / `void cleanupFinished()` – query or prune finished tasks.
- `WorkerDiag getDiag() const` – aggregated counts and runtime stats across the pool.
- `void onEvent(EventCallback cb)` / `void onError(ErrorCallback cb)` – receive lifecycle signals (`Created → Started → Completed/Destroyed`) and fatal issues.
- `const char* eventToString(...)` / `errorToString(...)` – convert enums to printable text for logging.

`WorkerConfig` (per job) and `ESPWorker::Config` (global defaults) expose priority, stack size bytes, core affinity, external stack usage, and an optional name that shows up in diagnostics and watchdog dumps.
Stack sizes are expressed in bytes.

## Restrictions
- Intended for ESP32-class boards where FreeRTOS and PSRAM are available; other architectures are untested.
- Requires C++17 support (`-std=gnu++17`) and should not be called from ISR context.
- Each worker consumes RAM proportional to its stack; keep `maxWorkers` and per-job stacks aligned with your heap budget.

## Tests
A native host test suite is still being assembled. For now rely on the `examples/` sketches (build with PlatformIO or Arduino IDE) to verify integration, and consider adding regression tests when contributing changes.

## License
ESPWorker is released under the [MIT License](LICENSE.md).

## ESPToolKit
- Check out other libraries:
- Hang out on Discord:
- Support the project:
- Visit the website: