arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
QueueLockFree.h
1
2#pragma once
3#include <stdint.h>
4
5#include <atomic>
6#include <cstddef>
7
8namespace audio_tools {
9
13template <typename T>
15 public:
16 QueueLockFree(size_t capacity, Allocator& allocator = DefaultAllocator) {
17 setAllocator(allocator);
18 resize(capacity);
19 }
20
22 for (size_t i = head_pos; i != tail_pos; ++i)
23 (&p_node[i & capacity_mask].data)->~T();
24
25 //delete[] (char*)p_node;
26 }
27
28 void setAllocator(Allocator& allocator) { vector.setAllocator(allocator); }
29
30 void resize(size_t capacity) {
31 capacity_mask = capacity - 1;
32 for (size_t i = 1; i <= sizeof(void*) * 4; i <<= 1)
33 capacity_mask |= capacity_mask >> i;
34 capacity_value = capacity_mask + 1;
35
36 vector.resize(capacity);
37 p_node = vector.data();
38
39 for (size_t i = 0; i < capacity; ++i) {
40 p_node[i].tail.store(i, std::memory_order_relaxed);
41 p_node[i].head.store(-1, std::memory_order_relaxed);
42 }
43
44 tail_pos.store(0, std::memory_order_relaxed);
45 head_pos.store(0, std::memory_order_relaxed);
46 }
47
48 size_t capacity() const { return capacity_value; }
49
50 bool empty() { return size() == 0;}
51
52 size_t size() const {
53 size_t head = head_pos.load(std::memory_order_acquire);
54 return tail_pos.load(std::memory_order_relaxed) - head;
55 }
56
57 bool enqueue(const T&& data) {
58 return enqueue(data);
59 }
60
61 bool enqueue(const T& data) {
62 Node* node;
63 size_t tail = tail_pos.load(std::memory_order_relaxed);
64 for (;;) {
65 node = &p_node[tail & capacity_mask];
66 if (node->tail.load(std::memory_order_relaxed) != tail) return false;
67 if ((tail_pos.compare_exchange_weak(tail, tail + 1,
68 std::memory_order_relaxed)))
69 break;
70 }
71 new (&node->data) T(data);
72 node->head.store(tail, std::memory_order_release);
73 return true;
74 }
75
76 bool dequeue(T& result) {
77 Node* node;
78 size_t head = head_pos.load(std::memory_order_relaxed);
79 for (;;) {
80 node = &p_node[head & capacity_mask];
81 if (node->head.load(std::memory_order_relaxed) != head) return false;
82 if (head_pos.compare_exchange_weak(head, head + 1,
83 std::memory_order_relaxed))
84 break;
85 }
86 result = node->data;
87 (&node->data)->~T();
88 node->tail.store(head + capacity_value, std::memory_order_release);
89 return true;
90 }
91
92 void clear() {
93 T tmp;
94 while (dequeue(tmp));
95 }
96
97 protected:
98 struct Node {
99 T data;
100 std::atomic<size_t> tail;
101 std::atomic<size_t> head;
102 };
103
104 Node* p_node = nullptr;
105 size_t capacity_mask;
106 size_t capacity_value;
107 std::atomic<size_t> tail_pos;
108 std::atomic<size_t> head_pos;
109 Vector<Node> vector;
110};
111} // namespace audio_tools
Memory allocateator which uses malloc.
Definition Allocator.h:23
A simple single producer, single consumer lock free queue.
Definition QueueLockFree.h:14
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Definition QueueLockFree.h:98