FastLED 3.9.15
Loading...
Searching...
No Matches
executor.h
Go to the documentation of this file.
1#pragma once
2
44
45#include "fl/task/promise.h"
47#include "fl/task/scheduler.h"
48#include "fl/stl/singleton.h"
49#include "fl/task/task.h"
50#include "platforms/await.h"
51#include "fl/stl/cstddef.h" // for size_t
52#include "fl/stl/stdint.h" // for u8
53#include "fl/stl/vector.h"
54#include "fl/stl/noexcept.h"
55
56namespace fl {
57namespace task {
58
66enum class ExecFlags : u8 {
67 TASKS = 1 << 0,
68 COROUTINES = 1 << 1,
69 SYSTEM = 1 << 2,
70 ALL = (1 << 0) | (1 << 1) | (1 << 2)
71};
72
74 return static_cast<ExecFlags>(static_cast<u8>(a) | static_cast<u8>(b));
75}
76
77inline bool operator&(ExecFlags a, ExecFlags b) {
78 return (static_cast<u8>(a) & static_cast<u8>(b)) != 0;
79}
80
81namespace detail {
84int& await_depth_tls();
85} // namespace detail
86
88class Runner {
89public:
90 virtual ~Runner() FL_NOEXCEPT = default;
91
93 virtual void update() = 0;
94
96 virtual bool has_active_tasks() const = 0;
97
99 virtual size_t active_task_count() const = 0;
100};
101
103class Executor {
104public:
105 static Executor& instance();
106
108 void register_runner(Runner* r);
109
111 void unregister_runner(Runner* r);
112
114 void update_all();
115
117 bool has_active_tasks() const;
118
120 size_t total_active_tasks() const;
121
122private:
124};
125
138void run(fl::u32 microseconds = 1000, ExecFlags flags = ExecFlags::ALL);
139
140
141
144size_t active_tasks();
145
148bool has_tasks();
149
185template<typename T>
187 // Handle invalid promises
188 if (!p.valid()) {
189 return PromiseResult<T>(Error("Invalid promise"));
190 }
191
192 // If already completed, return immediately
193 if (p.is_completed()) {
194 if (p.is_resolved()) {
195 return PromiseResult<T>(p.value());
196 } else {
197 return PromiseResult<T>(p.error());
198 }
199 }
200
201 // Track recursion depth to prevent infinite loops
202 int& await_depth = detail::await_depth_tls();
203 if (await_depth > 10) {
204 return PromiseResult<T>(Error("await_top_level recursion limit exceeded - possible infinite loop"));
205 }
206
207 ++await_depth;
208
209 // Wait for promise to complete while pumping async tasks
210 int pump_count = 0;
211 const int max_pump_iterations = 10000; // Safety limit
212
213 while (!p.is_completed() && pump_count < max_pump_iterations) {
214 // Update the promise first (in case it's not managed by async system)
215 p.update();
216
217 // Check if completed after update
218 if (p.is_completed()) {
219 break;
220 }
221
222 // Platform-agnostic async pump and yield
223 run(1000);
224
225 ++pump_count;
226 }
227
228 --await_depth;
229
230 // Check for timeout
231 if (pump_count >= max_pump_iterations) {
232 return PromiseResult<T>(Error("await_top_level timeout - promise did not complete"));
233 }
234
235 // Return the result
236 if (p.is_resolved()) {
237 return PromiseResult<T>(p.value());
238 } else {
239 return PromiseResult<T>(p.error());
240 }
241}
242
243} // namespace task
244} // namespace fl
245
246// ============================================================================
247// Await API Comparison: await() vs await_top_level()
248// ============================================================================
249//
250// FastLED provides two await functions for different contexts:
251//
252// 1. fl::task::await() - For coroutines (ESP32/Host only)
253// - Zero CPU overhead (true OS-level blocking)
254// - Must be called from fl::task::coroutine() context
255// - Suspends coroutine thread until promise completes
256// - Platform support: ESP32 (FreeRTOS), Host/Stub (std::thread)
257//
258// 2. fl::task::await_top_level() - For main loop/top-level code (All platforms)
259// - High CPU usage (busy-wait with run(1000))
260// - Safe to call from Arduino loop() or main()
261// - NOT safe in promise callbacks or nested async operations
262// - Platform support: All platforms
263//
264// **When to use which?**
265// - In fl::task::coroutine(): Use fl::task::await() for zero CPU waste
266// - In Arduino loop() or main(): Use fl::task::await_top_level()
267// - Other platforms without coroutine support: Use fl::task::await_top_level()
268//
269// ============================================================================
270
271
272
273namespace fl {
274namespace task {
275
304template<typename T>
306 return fl::platforms::await(p);
307}
308
309} // namespace task
310} // namespace fl
311
fl::vector< Runner * > mRunners
Definition executor.h:123
void update_all()
Update all registered runners.
void register_runner(Runner *r)
Register a runner.
size_t total_active_tasks() const
Get total number of active tasks across all runners.
static Executor & instance()
void unregister_runner(Runner *r)
Unregister a runner.
Task executor (singleton) — manages registered runners.
Definition executor.h:103
bool is_completed() const FL_NOEXCEPT
Check if Promise is completed (resolved or rejected)
Definition promise.h:140
const T & value() const FL_NOEXCEPT
Get the result value (only valid if is_resolved() returns true)
Definition promise.h:158
const Error & error() const FL_NOEXCEPT
Get the error (only valid if is_rejected() returns true)
Definition promise.h:167
bool valid() const FL_NOEXCEPT
Check if Promise is valid.
Definition promise.h:108
void update() FL_NOEXCEPT
Update Promise state in main loop - should be called periodically This processes pending callbacks wh...
Definition promise.h:134
bool is_resolved() const FL_NOEXCEPT
Check if Promise is resolved (completed successfully)
Definition promise.h:146
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 void update()=0
Update this runner (called during task pumping)
virtual size_t active_task_count() const =0
Get number of active tasks (for debugging/monitoring)
virtual ~Runner() FL_NOEXCEPT=default
virtual bool has_active_tasks() const =0
Check if this runner has active tasks.
Generic task runner interface.
Definition executor.h:88
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
int & await_depth_tls()
Get reference to thread-local await recursion depth.
bool has_tasks()
Check if any systems have active tasks.
ExecFlags operator|(ExecFlags a, ExecFlags b)
Definition executor.h:73
void run(fl::u32 microseconds, ExecFlags flags)
Run selected task subsystems.
size_t active_tasks()
Get the number of active tasks across all systems.
PromiseResult< T > await_top_level(Promise< T > p)
Synchronously wait for a promise to complete (ONLY safe in top-level contexts)
Definition executor.h:186
PromiseResult< T > await(Promise< T > p)
Await promise completion in a coroutine (Trampoline to platform implementation)
Definition executor.h:305
ExecFlags
Flags controlling which subsystems run() pumps.
Definition executor.h:66
bool operator&(ExecFlags a, ExecFlags b)
Definition executor.h:77
unsigned char u8
Definition stdint.h:131
Base definition for an LED controller.
Definition crgb.hpp:179
Promise-based fluent API for FastLED - standalone async primitives.
#define FL_NOEXCEPT
Task scheduler — manages timer and frame-based tasks.