MCPcopy Create free account
hub / github.com/FastLED/FastLED / CoroutineRuntimeWasm

Class CoroutineRuntimeWasm

src/platforms/wasm/coroutine_runtime_wasm.impl.hpp:40–103  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

38//=============================================================================
39
40class CoroutineRuntimeWasm : public ICoroutineRuntime {
41public:
42 void pumpCoroutines(fl::u32 us) FL_NOEXCEPT override {
43 if (CoroutineContext::isInsideCoroutine()) {
44 // Called from within a coroutine — yield back to runner
45 CoroutineContext::suspend();
46 } else {
47 // Called from main thread — give time to background coroutines
48 CoroutineRunner::instance().run(us);
49 }
50 }
51
52 /// Park on a real futex instead of busy-yielding.
53 ///
54 /// fl::platforms::await() polls a Promise with this method between
55 /// re-checks. The calling pthread parks via WASM `Atomics.wait` until
56 /// either (a) the timeout elapses or (b) wakeWaiters() notifies on the
57 /// shared counter from a JS callback.
58 ///
59 /// emscripten_atomic_wait_u32 is only valid off the browser main UI
60 /// thread, but with -sPROXY_TO_PTHREAD both main() and every coroutine
61 /// run on worker pthreads, so any caller that reaches this path is on
62 /// a parkable thread.
63 void suspendMainthread(fl::u32 us) FL_NOEXCEPT override {
64 // Inside a coroutine: hand the baton back to the runner so other
65 // coroutines (and the main loop) keep progressing — same as default.
66 if (CoroutineContext::isInsideCoroutine()) {
67 CoroutineContext::suspend();
68 return;
69 }
70 // Outside a coroutine (e.g. await called from setup/loop):
71 // snapshot the futex counter then park on it for up to `us`. Any
72 // wakeWaiters() call between the snapshot and the wait will be
73 // observed and short-circuit the timeout.
74 fl::u32 snapshot = mWakeupCounter.load();
75 fl::i64 timeout_ns = static_cast<fl::i64>(us) * 1000;
76 // emscripten_atomic_wait_u32 takes plain void* — fl::atomic<u32> is
77 // a standard-layout wrapper around a single u32, so its address
78 // coincides with the underlying word.
79 emscripten_atomic_wait_u32(
80 static_cast<void*>(&mWakeupCounter), // ok reinterpret_cast — atomic wrapper is layout-compat with its u32
81 snapshot,
82 timeout_ns);
83 }
84
85 /// Wake every pthread parked in suspendMainthread().
86 /// Called from async callbacks (currently js_fetch_success_callback /
87 /// js_fetch_error_callback) after they have committed Promise state, so
88 /// the awaiting pthread re-checks promptly.
89 void wakeWaiters() FL_NOEXCEPT override {
90 mWakeupCounter.fetch_add(1);
91 // emscripten_atomic_notify expects a 64-bit count; pass a sentinel
92 // that wakes all parked threads.
93 emscripten_atomic_notify(
94 static_cast<void*>(&mWakeupCounter),
95 static_cast<fl::i64>(0x7fffffff));
96 }
97

Callers

nothing calls this directly

Calls 3

runMethod · 0.45
loadMethod · 0.45
fetch_addMethod · 0.45

Tested by

no test coverage detected