9#include <freertos/FreeRTOS.h>
10#include <freertos/task.h>
31namespace lockfree_internal {
32#ifdef ESPHOME_THREAD_MULTI_NO_ATOMICS
43#define ESPHOME_LFQ_COMPILER_BARRIER() __asm__ __volatile__("" ::: "memory")
48 T
load(std::memory_order order = std::memory_order_seq_cst)
const {
50 if (order != std::memory_order_relaxed)
51 ESPHOME_LFQ_COMPILER_BARRIER();
54 void store(T value, std::memory_order order = std::memory_order_seq_cst) {
55 if (order != std::memory_order_relaxed)
56 ESPHOME_LFQ_COMPILER_BARRIER();
59 T
fetch_add(T amount, std::memory_order = std::memory_order_seq_cst) {
61 value_ = value + amount;
64 T
exchange(T desired, std::memory_order = std::memory_order_seq_cst) {
75template<
typename T>
using AtomicIndex = std::atomic<T>;
95 if constexpr ((SIZE & (SIZE - 1)) == 0) {
96 return (index + 1) % SIZE;
98 uint8_t next = index + 1;
99 if (next >= SIZE) [[unlikely]]
107 if (element ==
nullptr)
110 uint8_t current_tail =
tail_.load(std::memory_order_relaxed);
114 uint8_t head_before =
head_.load(std::memory_order_acquire);
116 if (next_tail == head_before) {
122 was_empty = (current_tail == head_before);
123 old_tail = current_tail;
125 buffer_[current_tail] = element;
126 tail_.store(next_tail, std::memory_order_release);
133 uint8_t current_head =
head_.load(std::memory_order_relaxed);
135 if (current_head ==
tail_.load(std::memory_order_acquire)) {
139 T *element =
buffer_[current_head];
145 uint8_t tail =
tail_.load(std::memory_order_acquire);
146 uint8_t head =
head_.load(std::memory_order_acquire);
147 if constexpr ((SIZE & (SIZE - 1)) == 0) {
148 return (tail - head + SIZE) % SIZE;
150 int diff =
static_cast<int>(tail) -
static_cast<int>(head);
153 return static_cast<size_t>(diff);
169 bool empty()
const {
return head_.load(std::memory_order_acquire) ==
tail_.load(std::memory_order_acquire); }
173 return next_tail ==
head_.load(std::memory_order_acquire);
200 if (result && task_to_notify_ !=
nullptr &&
201 (was_empty || this->
head_.load(std::memory_order_acquire) == old_tail)) {
208 xTaskNotifyGive(task_to_notify_);
221 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)