9#include <freertos/FreeRTOS.h>
10#include <freertos/task.h>
33namespace lockfree_internal {
34#if defined(ESPHOME_THREAD_MULTI_NO_ATOMICS) || defined(ESPHOME_THREAD_SINGLE)
55#define ESPHOME_LFQ_COMPILER_BARRIER() __asm__ __volatile__("" ::: "memory")
60 T
load(std::memory_order order = std::memory_order_seq_cst)
const {
62 if (order != std::memory_order_relaxed) {
63 ESPHOME_LFQ_COMPILER_BARRIER();
67 void store(T value, std::memory_order order = std::memory_order_seq_cst) {
68 if (order != std::memory_order_relaxed) {
69 ESPHOME_LFQ_COMPILER_BARRIER();
73 T
fetch_add(T amount, std::memory_order = std::memory_order_seq_cst) {
75 value_ = value + amount;
78 T
exchange(T desired, std::memory_order = std::memory_order_seq_cst) {
89template<
typename T>
using AtomicIndex = std::atomic<T>;
109 if constexpr ((SIZE & (SIZE - 1)) == 0) {
110 return (index + 1) % SIZE;
112 uint8_t
next = index + 1;
113 if (
next >= SIZE) [[unlikely]]
121 if (element ==
nullptr)
124 uint8_t current_tail =
tail_.load(std::memory_order_relaxed);
128 uint8_t head_before =
head_.load(std::memory_order_acquire);
130 if (next_tail == head_before) {
136 was_empty = (current_tail == head_before);
137 old_tail = current_tail;
139 buffer_[current_tail] = element;
140 tail_.store(next_tail, std::memory_order_release);
147 uint8_t current_head =
head_.load(std::memory_order_relaxed);
149 if (current_head ==
tail_.load(std::memory_order_acquire)) {
153 T *element =
buffer_[current_head];
159 uint8_t tail =
tail_.load(std::memory_order_acquire);
160 uint8_t head =
head_.load(std::memory_order_acquire);
161 if constexpr ((SIZE & (SIZE - 1)) == 0) {
162 return (tail - head + SIZE) % SIZE;
164 int diff =
static_cast<int>(tail) -
static_cast<int>(head);
167 return static_cast<size_t>(diff);
183 bool empty()
const {
return head_.load(std::memory_order_acquire) ==
tail_.load(std::memory_order_acquire); }
187 return next_tail ==
head_.load(std::memory_order_acquire);
214 if (result && task_to_notify_ !=
nullptr &&
215 (was_empty || this->
head_.load(std::memory_order_acquire) == old_tail)) {
222 xTaskNotifyGive(task_to_notify_);
235 TaskHandle_t task_to_notify_;
uint16_t get_and_reset_dropped_count()
static constexpr uint8_t next_index(uint8_t index)
lockfree_internal::AtomicIndex< uint8_t > head_
bool push_internal_(T *element, bool &was_empty, uint8_t &old_tail)
lockfree_internal::AtomicIndex< uint16_t > dropped_count_
void increment_dropped_count()
lockfree_internal::AtomicIndex< uint8_t > tail_
void set_task_to_notify(TaskHandle_t task)
T fetch_add(T amount, std::memory_order=std::memory_order_seq_cst)
T exchange(T desired, std::memory_order=std::memory_order_seq_cst)
T load(std::memory_order order=std::memory_order_seq_cst) const
void store(T value, std::memory_order order=std::memory_order_seq_cst)
constexpr PlainAtomic(T value)