1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-04 17:11:51 +00:00

Compare commits

...

11 Commits

Author SHA1 Message Date
J. Nick Koston
38fe47b554 Merge branch 'dev' into action_chaining 2025-11-03 17:45:59 -06:00
J. Nick Koston
738cf4cace Merge branch 'dev' into action_chaining 2025-11-02 19:09:44 -06:00
Jesse Hills
0a01fde503 Merge branch 'dev' into action_chaining 2025-11-03 14:07:15 +13:00
J. Nick Koston
52a5cccc77 fix regression from moved code that was conflicted 2025-11-02 17:39:57 -06:00
J. Nick Koston
a3dbaa7a95 Merge branch 'cotinuation_tests' into action_chaining 2025-11-02 17:25:52 -06:00
J. Nick Koston
47cc240368 Add action continuation tests
new baseline ahead of https://github.com/esphome/esphome/pull/11650
2025-11-02 17:23:37 -06:00
J. Nick Koston
21a343701d cover 2025-11-02 17:21:03 -06:00
J. Nick Koston
2f35a94d28 revert 2025-11-02 17:13:56 -06:00
J. Nick Koston
035a510aba fix conflict 2025-11-02 17:11:13 -06:00
J. Nick Koston
c1023116f2 Merge dev branch with action continuation optimizations
- Integrated upstream loop re-entry fixes from PR #7972
- Updated WhileAction and RepeatAction to use simpler parameter passing (no var_ storage)
- Maintained all optimization benefits (ContinuationAction, WhileLoopContinuation, RepeatLoopContinuation)
- DelayAction: shared_ptr + lambda instead of std::bind
- WaitUntilAction: simple lambda instead of std::bind
- IfAction: ContinuationAction (4-8 bytes) instead of LambdaAction (40 bytes)
- WhileAction: WhileLoopContinuation with simplified parameter passing
- RepeatAction: RepeatLoopContinuation with simplified parameter passing
2025-11-02 17:06:22 -06:00
J. Nick Koston
6c2f1c8a28 wip action chaining 2025-11-01 01:53:27 -05:00
2 changed files with 73 additions and 19 deletions

View File

@@ -220,6 +220,7 @@ template<typename... Ts> class Action {
protected:
friend ActionList<Ts...>;
template<typename... Us> friend class ContinuationAction;
virtual void play(Ts... x) = 0;
void play_next_(Ts... x) {

View File

@@ -216,18 +216,46 @@ template<typename... Ts> class StatelessLambdaAction : public Action<Ts...> {
void (*f_)(Ts...);
};
/// Simple continuation action that calls play_next_ on a parent action.
/// Used internally by IfAction, WhileAction, RepeatAction, etc. to chain actions.
/// Memory: 4-8 bytes (parent pointer) vs 40 bytes (LambdaAction with std::function).
template<typename... Ts> class ContinuationAction : public Action<Ts...> {
public:
explicit ContinuationAction(Action<Ts...> *parent) : parent_(parent) {}
void play(Ts... x) override { this->parent_->play_next_(x...); }
protected:
Action<Ts...> *parent_;
};
// Forward declaration for WhileLoopContinuation
template<typename... Ts> class WhileAction;
/// Loop continuation for WhileAction that checks condition and repeats or continues.
/// Memory: 4-8 bytes (parent pointer) vs 40 bytes (LambdaAction with std::function).
template<typename... Ts> class WhileLoopContinuation : public Action<Ts...> {
public:
explicit WhileLoopContinuation(WhileAction<Ts...> *parent) : parent_(parent) {}
void play(Ts... x) override;
protected:
WhileAction<Ts...> *parent_;
};
template<typename... Ts> class IfAction : public Action<Ts...> {
public:
explicit IfAction(Condition<Ts...> *condition) : condition_(condition) {}
void add_then(const std::initializer_list<Action<Ts...> *> &actions) {
this->then_.add_actions(actions);
this->then_.add_action(new LambdaAction<Ts...>([this](Ts... x) { this->play_next_(x...); }));
this->then_.add_action(new ContinuationAction<Ts...>(this));
}
void add_else(const std::initializer_list<Action<Ts...> *> &actions) {
this->else_.add_actions(actions);
this->else_.add_action(new LambdaAction<Ts...>([this](Ts... x) { this->play_next_(x...); }));
this->else_.add_action(new ContinuationAction<Ts...>(this));
}
void play_complex(Ts... x) override {
@@ -268,17 +296,11 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
void add_then(const std::initializer_list<Action<Ts...> *> &actions) {
this->then_.add_actions(actions);
this->then_.add_action(new LambdaAction<Ts...>([this](Ts... x) {
if (this->num_running_ > 0 && this->condition_->check(x...)) {
// play again
this->then_.play(x...);
} else {
// condition false, play next
this->play_next_(x...);
}
}));
this->then_.add_action(new WhileLoopContinuation<Ts...>(this));
}
friend class WhileLoopContinuation<Ts...>;
void play_complex(Ts... x) override {
this->num_running_++;
// Initial condition check
@@ -304,22 +326,43 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
ActionList<Ts...> then_;
};
// Implementation of WhileLoopContinuation::play
template<typename... Ts> void WhileLoopContinuation<Ts...>::play(Ts... x) {
if (this->parent_->num_running_ > 0 && this->parent_->condition_->check(x...)) {
// play again
this->parent_->then_.play(x...);
} else {
// condition false, play next
this->parent_->play_next_(x...);
}
}
// Forward declaration for RepeatLoopContinuation
template<typename... Ts> class RepeatAction;
/// Loop continuation for RepeatAction that increments iteration and repeats or continues.
/// Memory: 4-8 bytes (parent pointer) vs 40 bytes (LambdaAction with std::function).
template<typename... Ts> class RepeatLoopContinuation : public Action<uint32_t, Ts...> {
public:
explicit RepeatLoopContinuation(RepeatAction<Ts...> *parent) : parent_(parent) {}
void play(uint32_t iteration, Ts... x) override;
protected:
RepeatAction<Ts...> *parent_;
};
template<typename... Ts> class RepeatAction : public Action<Ts...> {
public:
TEMPLATABLE_VALUE(uint32_t, count)
void add_then(const std::initializer_list<Action<uint32_t, Ts...> *> &actions) {
this->then_.add_actions(actions);
this->then_.add_action(new LambdaAction<uint32_t, Ts...>([this](uint32_t iteration, Ts... x) {
iteration++;
if (iteration >= this->count_.value(x...)) {
this->play_next_(x...);
} else {
this->then_.play(iteration, x...);
}
}));
this->then_.add_action(new RepeatLoopContinuation<Ts...>(this));
}
friend class RepeatLoopContinuation<Ts...>;
void play_complex(Ts... x) override {
this->num_running_++;
if (this->count_.value(x...) > 0) {
@@ -338,6 +381,16 @@ template<typename... Ts> class RepeatAction : public Action<Ts...> {
ActionList<uint32_t, Ts...> then_;
};
// Implementation of RepeatLoopContinuation::play
template<typename... Ts> void RepeatLoopContinuation<Ts...>::play(uint32_t iteration, Ts... x) {
iteration++;
if (iteration >= this->parent_->count_.value(x...)) {
this->parent_->play_next_(x...);
} else {
this->parent_->then_.play(iteration, x...);
}
}
/** Wait until a condition is true to continue execution.
*
* Uses queue-based storage to safely handle concurrent executions.