diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 1557ca07900..99eabb704f4 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1842,23 +1842,30 @@ template class CallbackManager { protected: template friend class LazyCallbackManager; /// Non-template core to avoid code duplication per lambda type. + /// Inline fast path; cold growth path is out-of-line in grow_(). void add_(CbType cb) { - if (this->size_ == this->capacity_) { - auto *new_data = new CbType[this->size_ + 1]; - if (this->data_) { - __builtin_memcpy(new_data, this->data_, this->size_ * sizeof(CbType)); - delete[] this->data_; - } - this->data_ = new_data; - this->capacity_ = this->size_ + 1; - } + if (this->size_ == this->capacity_) + this->grow_(); this->data_[this->size_++] = cb; } + /// Out-of-line cold path: allocate exact size needed. + void grow_(); CbType *data_{nullptr}; uint16_t size_{0}; uint16_t capacity_{0}; }; +/// Out-of-line cold growth path for CallbackManager::add_(). +template __attribute__((noinline, cold)) void CallbackManager::grow_() { + auto *new_data = new CbType[this->size_ + 1]; + if (this->data_) { + __builtin_memcpy(new_data, this->data_, this->size_ * sizeof(CbType)); + delete[] this->data_; + } + this->data_ = new_data; + this->capacity_ = this->size_ + 1; +} + template class LazyCallbackManager; /** Lazy-allocating callback manager that only allocates memory when callbacks are registered.