[automation] Remove actions_end_ pointer from ActionList to save RAM (#15283)

This commit is contained in:
J. Nick Koston
2026-03-30 08:20:52 -10:00
committed by GitHub
parent b579758c46
commit ad3f6ae313
+21 -18
View File
@@ -419,44 +419,48 @@ template<typename... Ts> class Action {
template<typename... Ts> class ActionList { template<typename... Ts> class ActionList {
public: public:
void add_action(Action<Ts...> *action) { void add_action(Action<Ts...> *action) {
if (this->actions_end_ == nullptr) { // Walk to end of chain - action lists are short and only built during setup()
this->actions_begin_ = action; Action<Ts...> **tail = &this->actions_;
} else { while (*tail != nullptr)
this->actions_end_->next_ = action; tail = &(*tail)->next_;
} *tail = action;
this->actions_end_ = action;
} }
void add_actions(const std::initializer_list<Action<Ts...> *> &actions) { void add_actions(const std::initializer_list<Action<Ts...> *> &actions) {
// Find tail once, then append all actions in a single pass
Action<Ts...> **tail = &this->actions_;
while (*tail != nullptr)
tail = &(*tail)->next_;
for (auto *action : actions) { for (auto *action : actions) {
this->add_action(action); *tail = action;
tail = &action->next_;
} }
} }
// Force-inline: part of the Trigger→Automation→ActionList forwarding // Force-inline: part of the Trigger→Automation→ActionList forwarding
// chain collapsed to reduce automation call stack depth. // chain collapsed to reduce automation call stack depth.
inline void play(const Ts &...x) ESPHOME_ALWAYS_INLINE { inline void play(const Ts &...x) ESPHOME_ALWAYS_INLINE {
if (this->actions_begin_ != nullptr) if (this->actions_ != nullptr)
this->actions_begin_->play_complex(x...); this->actions_->play_complex(x...);
} }
void play_tuple(const std::tuple<Ts...> &tuple) { void play_tuple(const std::tuple<Ts...> &tuple) {
this->play_tuple_(tuple, std::make_index_sequence<sizeof...(Ts)>{}); this->play_tuple_(tuple, std::make_index_sequence<sizeof...(Ts)>{});
} }
void stop() { void stop() {
if (this->actions_begin_ != nullptr) if (this->actions_ != nullptr)
this->actions_begin_->stop_complex(); this->actions_->stop_complex();
} }
bool empty() const { return this->actions_begin_ == nullptr; } bool empty() const { return this->actions_ == nullptr; }
/// Check if any action in this action list is currently running. /// Check if any action in this action list is currently running.
bool is_running() { bool is_running() {
if (this->actions_begin_ == nullptr) if (this->actions_ == nullptr)
return false; return false;
return this->actions_begin_->is_running(); return this->actions_->is_running();
} }
/// Return the number of actions in this action list that are currently running. /// Return the number of actions in this action list that are currently running.
int num_running() { int num_running() {
if (this->actions_begin_ == nullptr) if (this->actions_ == nullptr)
return 0; return 0;
return this->actions_begin_->num_running_total(); return this->actions_->num_running_total();
} }
protected: protected:
@@ -464,8 +468,7 @@ template<typename... Ts> class ActionList {
this->play(std::get<S>(tuple)...); this->play(std::get<S>(tuple)...);
} }
Action<Ts...> *actions_begin_{nullptr}; Action<Ts...> *actions_{nullptr};
Action<Ts...> *actions_end_{nullptr};
}; };
template<typename... Ts> class Automation { template<typename... Ts> class Automation {