This commit is contained in:
J. Nick Koston 2025-06-30 13:14:55 -05:00
parent 519c49f175
commit 44a7c1d4a5
No known key found for this signature in database

View File

@ -69,29 +69,28 @@ class OTAComponent : public Component {
} }
protected: protected:
/** Thread-safe callback manager that automatically defers to main loop. /** Extended callback manager with deferred call support.
* *
* This ensures all OTA callbacks are executed in the main loop task, * This adds a call_deferred() method for thread-safe execution from other tasks.
* making them safe to call from any context (including web_server's OTA task).
* Existing code doesn't need changes - callbacks are automatically deferred.
*/ */
class DeferredCallbackManager : public CallbackManager<void(OTAState, float, uint8_t)> { class StateCallbackManager : public CallbackManager<void(OTAState, float, uint8_t)> {
public: public:
DeferredCallbackManager(OTAComponent *component) : component_(component) {} StateCallbackManager(OTAComponent *component) : component_(component) {}
/// Override call to automatically defer to main loop /** Call callbacks with deferral to main loop (for thread safety).
void call(OTAState state, float progress, uint8_t error) { *
// Always defer to main loop for thread safety * This should be used by OTA implementations that run in separate tasks
component_->defer([this, state, progress, error]() { * (like web_server OTA) to ensure callbacks execute in the main loop.
CallbackManager<void(OTAState, float, uint8_t)>::call(state, progress, error); */
}); void call_deferred(OTAState state, float progress, uint8_t error) {
component_->defer([this, state, progress, error]() { this->call(state, progress, error); });
} }
private: private:
OTAComponent *component_; OTAComponent *component_;
}; };
DeferredCallbackManager state_callback_{this}; StateCallbackManager state_callback_{this};
#endif #endif
}; };
@ -114,10 +113,10 @@ class OTAGlobalCallback {
OTAGlobalCallback *get_global_ota_callback(); OTAGlobalCallback *get_global_ota_callback();
void register_ota_platform(OTAComponent *ota_caller); void register_ota_platform(OTAComponent *ota_caller);
// Thread-safe callback execution is automatically provided by DeferredCallbackManager // OTA implementations should use:
// which overrides call() to use Component::defer(). This ensures all OTA callbacks // - state_callback_.call() when already in main loop (e.g., esphome OTA)
// run in the main loop task, making them safe to call from any context including // - state_callback_.call_deferred() when in separate task (e.g., web_server OTA)
// web_server's separate OTA task. No code changes needed. // This ensures proper callback execution in all contexts.
#endif #endif
} // namespace ota_base } // namespace ota_base