Arduino DLNA Server
Loading...
Searching...
No Matches
QueueLockFree.h
Go to the documentation of this file.
1
2#pragma once
3#include <stdint.h>
4
5#include <atomic>
6#include <cstddef>
7#include <utility>
8
9namespace tiny_dlna {
10
14template <typename T>
16 public:
19 }
20
22 // destroy any remaining constructed elements between head and tail
23 size_t head = head_pos.load(std::memory_order_relaxed);
24 size_t tail = tail_pos.load(std::memory_order_relaxed);
25 for (size_t i = head; i != tail; ++i)
26 (&p_node[i & capacity_mask].data)->~T();
27 }
28
29 // setAllocator removed – allocator compatibility dropped.
30
31 void resize(size_t capacity) {
32 // round up to next power-of-two and compute mask/value
34 for (size_t i = 1; i <= sizeof(void*) * 4; i <<= 1)
37
38 // allocate vector with the power-of-two capacity_value
39 vector.resize(capacity_value);
40 p_node = vector.data();
41
42 // initialize nodes for the full allocated capacity
43 for (size_t i = 0; i < capacity_value; ++i) {
44 p_node[i].tail.store(i, std::memory_order_relaxed);
45 p_node[i].head.store((size_t)-1, std::memory_order_relaxed);
46 }
47
48 tail_pos.store(0, std::memory_order_relaxed);
49 head_pos.store(0, std::memory_order_relaxed);
50 }
51
52 size_t capacity() const { return capacity_value; }
53
54 size_t size() const {
55 size_t head = head_pos.load(std::memory_order_acquire);
56 return tail_pos.load(std::memory_order_relaxed) - head;
57 }
58
59 bool enqueue( T&& data) {
60 Node* node;
61 size_t tail = tail_pos.load(std::memory_order_relaxed);
62 for (;;) {
63 node = &p_node[tail & capacity_mask];
64 if (node->tail.load(std::memory_order_relaxed) != tail) return false;
65 if ((tail_pos.compare_exchange_weak(tail, tail + 1,
66 std::memory_order_relaxed)))
67 break;
68 }
69 // move-construct into the node to avoid an extra copy (important in
70 // async/interrupt contexts where the source may have already allocated)
71 new (&node->data) T(std::move(data));
72 node->head.store(tail, std::memory_order_release);
73 return true;
74 }
75
76 bool enqueue( T& data) {
77 Node* node;
78 size_t tail = tail_pos.load(std::memory_order_relaxed);
79 for (;;) {
80 node = &p_node[tail & capacity_mask];
81 if (node->tail.load(std::memory_order_relaxed) != tail) return false;
82 if ((tail_pos.compare_exchange_weak(tail, tail + 1,
83 std::memory_order_relaxed)))
84 break;
85 }
86 new (&node->data) T(data);
87 node->head.store(tail, std::memory_order_release);
88 return true;
89 }
90
91 bool dequeue(const T&& data) {
92 return dequeue(data);
93 }
94
95 bool dequeue(T& result) {
96 Node* node;
97 size_t head = head_pos.load(std::memory_order_relaxed);
98 for (;;) {
99 node = &p_node[head & capacity_mask];
100 if (node->head.load(std::memory_order_relaxed) != head) return false;
101 if (head_pos.compare_exchange_weak(head, head + 1,
102 std::memory_order_relaxed))
103 break;
104 }
105 // move-assign to avoid an extra copy when possible
106 result = std::move(node->data);
107 (&node->data)->~T();
108 node->tail.store(head + capacity_value, std::memory_order_release);
109 return true;
110 }
111
112 void clear() {
113 T tmp;
114 while (dequeue(tmp));
115 }
116
117 protected:
119 struct Node {
121 std::atomic<size_t> tail;
122 std::atomic<size_t> head;
123 };
124
128 std::atomic<size_t> tail_pos;
129 std::atomic<size_t> head_pos;
130 Vector<Node> vector; // uses default DLNA_ALLOCATOR<T> for Node
131};
132} // namespace audio_tools
A simple single producer, single consumer lock free queue.
Definition: QueueLockFree.h:15
void clear()
Definition: QueueLockFree.h:112
Vector< Node > vector
Definition: QueueLockFree.h:130
bool dequeue(const T &&data)
Definition: QueueLockFree.h:91
void resize(size_t capacity)
Definition: QueueLockFree.h:31
size_t size() const
Definition: QueueLockFree.h:54
~QueueLockFree()
Definition: QueueLockFree.h:21
size_t capacity() const
Definition: QueueLockFree.h:52
bool enqueue(T &data)
Definition: QueueLockFree.h:76
size_t capacity_value
Definition: QueueLockFree.h:127
bool enqueue(T &&data)
Definition: QueueLockFree.h:59
std::atomic< size_t > tail_pos
Definition: QueueLockFree.h:128
size_t capacity_mask
Definition: QueueLockFree.h:126
std::atomic< size_t > head_pos
Definition: QueueLockFree.h:129
bool dequeue(T &result)
Definition: QueueLockFree.h:95
QueueLockFree(size_t capacity)
Definition: QueueLockFree.h:17
Node * p_node
Definition: QueueLockFree.h:125
Lightweight wrapper around std::vector with Arduino-friendly helpers and a pluggable allocator.
Definition: Vector.h:39
Definition: Allocator.h:13
QueueLockFree Node.
Definition: QueueLockFree.h:119
std::atomic< size_t > head
Definition: QueueLockFree.h:122
std::atomic< size_t > tail
Definition: QueueLockFree.h:121
T data
Definition: QueueLockFree.h:120