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();
66 void store(T value, std::memory_order order = std::memory_order_seq_cst) {
67 if (order != std::memory_order_relaxed)
68 ESPHOME_LFQ_COMPILER_BARRIER();
71 T
fetch_add(T amount, std::memory_order = std::memory_order_seq_cst) {
73 value_ = value + amount;
76 T
exchange(T desired, std::memory_order = std::memory_order_seq_cst) {
87template<
typename T>
using AtomicIndex = std::atomic<T>;
107 if constexpr ((SIZE & (SIZE - 1)) == 0) {
108 return (index + 1) % SIZE;
110 uint8_t next = index + 1;
111 if (next >= SIZE) [[unlikely]]
119 if (element ==
nullptr)
122 uint8_t current_tail =
tail_.load(std::memory_order_relaxed);
126 uint8_t head_before =
head_.load(std::memory_order_acquire);
128 if (next_tail == head_before) {
134 was_empty = (current_tail == head_before);
135 old_tail = current_tail;
137 buffer_[current_tail] = element;
138 tail_.store(next_tail, std::memory_order_release);
145 uint8_t current_head =
head_.load(std::memory_order_relaxed);
147 if (current_head ==
tail_.load(std::memory_order_acquire)) {
151 T *element =
buffer_[current_head];
157 uint8_t tail =
tail_.load(std::memory_order_acquire);
158 uint8_t head =
head_.load(std::memory_order_acquire);
159 if constexpr ((SIZE & (SIZE - 1)) == 0) {
160 return (tail - head + SIZE) % SIZE;
162 int diff =
static_cast<int>(tail) -
static_cast<int>(head);
165 return static_cast<size_t>(diff);
181 bool empty()
const {
return head_.load(std::memory_order_acquire) ==
tail_.load(std::memory_order_acquire); }
185 return next_tail ==
head_.load(std::memory_order_acquire);
212 if (result && task_to_notify_ !=
nullptr &&
213 (was_empty || this->
head_.load(std::memory_order_acquire) == old_tail)) {
220 xTaskNotifyGive(task_to_notify_);
233 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)