ESPHome
2026.5.0-dev
Loading...
Searching...
No Matches
esphome
core
event_pool.h
Go to the documentation of this file.
1
#pragma once
2
3
#if defined(USE_ESP32) || defined(USE_ZEPHYR)
4
5
#include <atomic>
6
#include <cstddef>
7
#include "
esphome/core/helpers.h
"
8
#include "
esphome/core/lock_free_queue.h
"
9
10
namespace
esphome
{
11
12
// Event Pool - On-demand pool of objects to avoid heap fragmentation
13
// Events are allocated on first use and reused thereafter, growing to peak usage
14
// @tparam T The type of objects managed by the pool (must have a release() method)
15
// @tparam SIZE The maximum number of objects in the pool (1-255, limited by uint8_t)
16
//
17
// SIZING: When paired with a LockFreeQueue<T, Q_SIZE>, the pool SIZE should be
18
// Q_SIZE - 1 (the queue's actual capacity, since the ring buffer reserves one slot).
19
// This ensures allocate() returns nullptr before push() can fail, which:
20
// - Prevents the allocate-succeeds-but-push-fails mismatch that permanently
21
// leaks a pool slot (the element is never returned to the pool)
22
// - Avoids needing release() on the producer path after a failed push(),
23
// preserving the SPSC contract on the internal free list
24
template
<
class
T, u
int
8_t SIZE>
class
EventPool
{
25
public
:
26
EventPool
() : total_created_(0) {}
27
28
~EventPool
() {
29
// Clean up any remaining events in the free list
30
// IMPORTANT: This destructor assumes no concurrent access. The EventPool must not
31
// be destroyed while any thread might still call allocate() or release().
32
// In practice, this is typically ensured by destroying the pool only during
33
// component shutdown when all producer/consumer threads have been stopped.
34
T *event;
35
RAMAllocator<T>
allocator(
RAMAllocator<T>::ALLOC_INTERNAL
);
36
while
((event = this->free_list_.pop()) !=
nullptr
) {
37
// Call destructor
38
event
->~T();
39
// Deallocate using RAMAllocator
40
allocator.
deallocate
(event, 1);
41
}
42
}
43
44
// Allocate an event from the pool
45
// Returns nullptr if pool is full
46
T *
allocate
() {
47
// Try to get from free list first
48
T *
event
= this->free_list_.pop();
49
if
(event !=
nullptr
)
50
return
event;
51
52
// Need to create a new event
53
if
(this->total_created_ >= SIZE) {
54
// Pool is at capacity
55
return
nullptr
;
56
}
57
58
// Use internal RAM for better performance
59
RAMAllocator<T>
allocator(
RAMAllocator<T>::ALLOC_INTERNAL
);
60
event
= allocator.
allocate
(1);
61
62
if
(event ==
nullptr
) {
63
// Memory allocation failed
64
return
nullptr
;
65
}
66
67
// Placement new to construct the object
68
new
(event) T();
69
this->total_created_++;
70
return
event;
71
}
72
73
// Return an event to the pool for reuse
74
void
release
(T *event) {
75
if
(event !=
nullptr
) {
76
// Clean up the event's allocated memory
77
event
->release();
78
this->free_list_.push(event);
79
}
80
}
81
82
private
:
83
LockFreeQueue<T, SIZE>
free_list_;
// Free events ready for reuse
84
uint8_t total_created_;
// Total events created (high water mark, max 255)
85
};
86
87
}
// namespace esphome
88
89
#endif
// defined(USE_ESP32)
esphome::EventPool
Definition
event_pool.h:24
esphome::EventPool::~EventPool
~EventPool()
Definition
event_pool.h:28
esphome::EventPool::allocate
T * allocate()
Definition
event_pool.h:46
esphome::EventPool::EventPool
EventPool()
Definition
event_pool.h:26
esphome::EventPool::release
void release(T *event)
Definition
event_pool.h:74
esphome::LockFreeQueue
Definition
lock_free_queue.h:30
esphome::RAMAllocator
An STL allocator that uses SPI or internal RAM.
Definition
helpers.h:2212
esphome::RAMAllocator::deallocate
void deallocate(T *p, size_t n)
Definition
helpers.h:2267
esphome::RAMAllocator::allocate
T * allocate(size_t n)
Definition
helpers.h:2229
helpers.h
lock_free_queue.h
esphome
Providing packet encoding functions for exchanging data with a remote host.
Definition
a01nyub.cpp:7
Generated by
1.12.0