FastLED 3.10.8
Loading...
Searching...
No Matches
executor.h
Go to the documentation of this file.
1#pragma once
2
42
43#include "fl/task/promise.h"
45#include "fl/task/scheduler.h"
46#include "fl/stl/singleton.h"
47#include "fl/task/task.h"
48#include "platforms/await.h"
49#include "fl/stl/cstddef.h" // for size_t
50#include "fl/stl/stdint.h" // for u8
51#include "fl/stl/vector.h"
52#include "fl/stl/noexcept.h"
53
54namespace fl {
55namespace task {
56
64enum class ExecFlags : u8 {
65 TASKS = 1 << 0,
66 COROUTINES = 1 << 1,
67 SYSTEM = 1 << 2,
68 ALL = (1 << 0) | (1 << 1) | (1 << 2)
69};
70
72 return static_cast<ExecFlags>(static_cast<u8>(a) | static_cast<u8>(b));
73}
74
76 return (static_cast<u8>(a) & static_cast<u8>(b)) != 0;
77}
78
79namespace detail {
83} // namespace detail
84
86class Runner {
87public:
88 virtual ~Runner() FL_NO_EXCEPT = default;
89
91 virtual void update() FL_NO_EXCEPT = 0;
92
94 virtual bool has_active_tasks() const FL_NO_EXCEPT = 0;
95
97 virtual size_t active_task_count() const FL_NO_EXCEPT = 0;
98};
99
101class Executor {
102public:
104
107
110
113
115 bool has_active_tasks() const FL_NO_EXCEPT;
116
118 size_t total_active_tasks() const FL_NO_EXCEPT;
119
120private:
122};
123
136void run(fl::u32 microseconds = 1000, ExecFlags flags = ExecFlags::ALL) FL_NO_EXCEPT;
137
145void yield_system(fl::u32 microseconds) FL_NO_EXCEPT;
146
147
148
152
156
192template<typename T>
194 // Handle invalid promises
195 if (!p.valid()) {
196 return PromiseResult<T>(Error("Invalid promise"));
197 }
198
199 // If already completed, return immediately
200 if (p.is_completed()) {
201 if (p.is_resolved()) {
202 return PromiseResult<T>(p.value());
203 } else {
204 return PromiseResult<T>(p.error());
205 }
206 }
207
208 // Track recursion depth to prevent infinite loops
209 int& await_depth = detail::await_depth_tls();
210 if (await_depth > 10) {
211 return PromiseResult<T>(Error("await_top_level recursion limit exceeded - possible infinite loop"));
212 }
213
214 ++await_depth;
215
216 // Wait for promise to complete while pumping async tasks
217 int pump_count = 0;
218 const int max_pump_iterations = 10000; // Safety limit
219
220 while (!p.is_completed() && pump_count < max_pump_iterations) {
221 // Update the promise first (in case it's not managed by async system)
222 p.update();
223
224 // Check if completed after update
225 if (p.is_completed()) {
226 break;
227 }
228
229 // Platform-agnostic async pump and yield
230 run(1000);
231
232 ++pump_count;
233 }
234
235 --await_depth;
236
237 // Check for timeout
238 if (pump_count >= max_pump_iterations) {
239 return PromiseResult<T>(Error("await_top_level timeout - promise did not complete"));
240 }
241
242 // Return the result
243 if (p.is_resolved()) {
244 return PromiseResult<T>(p.value());
245 } else {
246 return PromiseResult<T>(p.error());
247 }
248}
249
250} // namespace task
251} // namespace fl
252
253// ============================================================================
254// Await API Comparison: await() vs await_top_level()
255// ============================================================================
256//
257// FastLED provides two await functions for different contexts:
258//
259// 1. fl::task::await() - For coroutines (ESP32/Host only)
260// - Zero CPU overhead (true OS-level blocking)
261// - Must be called from fl::task::coroutine() context
262// - Suspends coroutine thread until promise completes
263// - Platform support: ESP32 (FreeRTOS), Host/Stub (std::thread)
264//
265// 2. fl::task::await_top_level() - For main loop/top-level code (All platforms)
266// - High CPU usage (busy-wait with run(1000))
267// - Safe to call from Arduino loop() or main()
268// - NOT safe in promise callbacks or nested async operations
269// - Platform support: All platforms
270//
271// **When to use which?**
272// - In fl::task::coroutine(): Use fl::task::await() for zero CPU waste
273// - In Arduino loop() or main(): Use fl::task::await_top_level()
274// - Other platforms without coroutine support: Use fl::task::await_top_level()
275//
276// ============================================================================
277
278
279
280namespace fl {
281namespace task {
282
315template<typename T>
317 Promise<T> p,
318 fl::u32 timeout_ms = fl::platforms::kAwaitDefaultTimeoutMs) FL_NO_EXCEPT {
319 return fl::platforms::await(p, timeout_ms);
320}
321
322} // namespace task
323} // namespace fl
size_t total_active_tasks() const FL_NO_EXCEPT
Get total number of active tasks across all runners.
fl::vector< Runner * > mRunners
Definition executor.h:121
void register_runner(Runner *r) FL_NO_EXCEPT
Register a runner.
bool has_active_tasks() const FL_NO_EXCEPT
Check if there are any active tasks.
void unregister_runner(Runner *r) FL_NO_EXCEPT
Unregister a runner.
static Executor & instance() FL_NO_EXCEPT
void update_all() FL_NO_EXCEPT
Update all registered runners.
Task executor (singleton) — manages registered runners.
Definition executor.h:101
Promise class that provides fluent .then() and .catch_() semantics This is a lightweight wrapper arou...
Definition promise.h:58
Result type for promise operations.
virtual ~Runner() FL_NO_EXCEPT=default
virtual size_t active_task_count() const FL_NO_EXCEPT=0
Get number of active tasks (for debugging/monitoring)
virtual bool has_active_tasks() const FL_NO_EXCEPT=0
Check if this runner has active tasks.
virtual void update() FL_NO_EXCEPT=0
Update this runner (called during task pumping)
Generic task runner interface.
Definition executor.h:86
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
int & await_depth_tls() FL_NO_EXCEPT
Get reference to thread-local await recursion depth.
void yield_system(fl::u32 microseconds) FL_NO_EXCEPT
OS-level yield only: same behavior as run(us, ExecFlags::SYSTEM).
size_t active_tasks() FL_NO_EXCEPT
Get the number of active tasks across all systems.
PromiseResult< T > await(Promise< T > p, fl::u32 timeout_ms=fl::platforms::kAwaitDefaultTimeoutMs) FL_NO_EXCEPT
Await promise completion in a coroutine (Trampoline to platform implementation)
Definition executor.h:316
void run(fl::u32 microseconds, ExecFlags flags) FL_NO_EXCEPT
Run selected task subsystems.
bool has_tasks() FL_NO_EXCEPT
Check if any systems have active tasks.
ExecFlags operator|(ExecFlags a, ExecFlags b) FL_NO_EXCEPT
Definition executor.h:71
ExecFlags
Flags controlling which subsystems run() pumps.
Definition executor.h:64
bool operator&(ExecFlags a, ExecFlags b) FL_NO_EXCEPT
Definition executor.h:75
PromiseResult< T > await_top_level(Promise< T > p) FL_NO_EXCEPT
Synchronously wait for a promise to complete (ONLY safe in top-level contexts)
Definition executor.h:193
unsigned char u8
Definition stdint.h:131
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
Base definition for an LED controller.
Definition crgb.hpp:179
Promise-based fluent API for FastLED - standalone async primitives.
Task scheduler — manages timer and frame-based tasks.