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

Method waitForCondition

src/fl/channels/manager.cpp.hpp:424–491  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

422
423template<typename Condition>
424bool ChannelManager::waitForCondition(Condition condition, u32 timeoutMs) {
425 const u32 startTime = timeoutMs > 0 ? millis() : 0;
426
427 // Tier 1: instant non-blocking check (avoid micros() / millis() cost on
428 // the common already-ready path).
429 if (condition()) {
430 return true;
431 }
432
433 // Tier 2: bounded microsecond spin (#2818). Catches short DMA tails
434 // (APA102 small strips, WS2812B <=8 LEDs) without paying the >=1-tick
435 // floor of the cooperator yield below. Budget is runtime-tunable via
436 // FastLED.setWaitSpinBudgetUs(N); set to 0 to disable.
437 {
438 const u32 spinBudget = fl::detail::getWaitSpinBudgetUs();
439 if (spinBudget > 0) {
440 const u32 spinStart = fl::micros();
441 while ((fl::micros() - spinStart) < spinBudget) {
442 if (condition()) {
443 return true;
444 }
445 if (timeoutMs > 0 && (millis() - startTime) >= timeoutMs) {
446 FL_ERROR("ChannelManager: Timeout occurred while waiting for condition");
447 return false;
448 }
449 }
450 }
451 }
452
453 while (!condition()) {
454 // Check timeout if specified
455 if (timeoutMs > 0 && (millis() - startTime >= timeoutMs)) {
456 FL_ERROR("ChannelManager: Timeout occurred while waiting for condition");
457 return false; // Timeout occurred
458 }
459
460 const u32 sliceMs = pollNeededWaitSliceMs(startTime, timeoutMs);
461 if (sliceMs == 0) {
462 return false;
463 }
464 if (waitForPollNeededSignal(sliceMs)) {
465 continue;
466 }
467
468 // Adaptive yield (refs #2815, generalizes the #2493 ESP32-P4 carve-out):
469 //
470 // The 1-tick (>=1 ms at CONFIG_FREERTOS_HZ=1000) floor only exists to
471 // keep WiFi / lwIP / BT controller tasks alive while we are inside the
472 // channel wait loop (#2254). When no radio is actually up, that floor
473 // is pure timing drift -- visible as the regression reported in #2420
474 // and as the per-frame cost the #2493 ESP32-P4 carve-out was avoiding.
475 //
476 // NetworkDetector::isAnyNetworkActive() is the runtime version of the
477 // "is a radio up?" question. On non-ESP32 platforms and on ESP32-P4
478 // (no radio silicon) it folds to a constant `false`, so this is
479 // strictly a perf win for the common single-strip / no-WiFi case
480 // without losing the WiFi-friendly behavior when a radio is active.
481 if (fl::NetworkDetector::isAnyNetworkActive()) {

Callers

nothing calls this directly

Calls 4

millisFunction · 0.50
getWaitSpinBudgetUsFunction · 0.50
microsFunction · 0.50
runFunction · 0.50

Tested by

no test coverage detected