libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
lockfree_pool.hpp
1#pragma once
2
3#include <atomic>
4#include <new>
5
6#include "libxr_def.hpp"
7
8namespace LibXR
9{
10
24template <typename Data>
26{
27 public:
28 // NOLINTBEGIN
30 enum class SlotState : uint32_t
31 {
32 FREE = 0,
33 BUSY = 1,
34 READY = 2,
35 RECYCLE = UINT32_MAX
36
37 };
38 // NOLINTEND
39
41 union alignas(LIBXR_CACHE_LINE_SIZE) Slot
42 {
43 struct
44 {
45 std::atomic<SlotState> state;
46 Data data;
47 } slot;
48
49 uint8_t pad[LIBXR_CACHE_LINE_SIZE];
50 };
51
56 LockFreePool(uint32_t slot_count)
57 : SLOT_COUNT(slot_count),
58 slots_(new(std::align_val_t(LIBXR_CACHE_LINE_SIZE)) Slot[slot_count])
59 {
60 for (uint32_t index = 0; index < SLOT_COUNT; index++)
61 {
62 slots_[index].slot.state.store(SlotState::FREE, std::memory_order_relaxed);
63 }
64 }
65
69 ~LockFreePool() { delete[] slots_; }
70
79 ErrorCode Put(const Data &data)
80 {
81 uint32_t start_index = 0;
82 return Put(data, start_index);
83 }
84
95 ErrorCode Put(const Data &data, uint32_t &start_index)
96 {
97 for (uint32_t index = start_index; index < SLOT_COUNT; index++)
98 {
99 auto expected = slots_[index].slot.state.load(std::memory_order_relaxed);
100 if (expected == SlotState::FREE || expected == SlotState::RECYCLE)
101 {
102 if (slots_[index].slot.state.compare_exchange_strong(expected, SlotState::BUSY,
103 std::memory_order_release,
104 std::memory_order_relaxed))
105 {
106 slots_[index].slot.data = data;
107 slots_[index].slot.state.store(SlotState::READY, std::memory_order_release);
108 start_index = index;
109 return ErrorCode::OK;
110 }
111 }
112 }
113 return ErrorCode::FULL;
114 }
115
125 ErrorCode PutToSlot(const Data &data, uint32_t index)
126 {
127 auto expected = slots_[index].slot.state.load(std::memory_order_relaxed);
128 if (expected == SlotState::FREE || expected == SlotState::RECYCLE)
129 {
130 if (slots_[index].slot.state.compare_exchange_strong(expected, SlotState::BUSY,
131 std::memory_order_release,
132 std::memory_order_relaxed))
133 {
134 slots_[index].slot.data = data;
135 slots_[index].slot.state.store(SlotState::READY, std::memory_order_release);
136 return ErrorCode::OK;
137 }
138 }
139 return ErrorCode::FULL;
140 }
141
150 ErrorCode Get(Data &data)
151 {
152 uint32_t start_index = 0;
153
154 return Get(data, start_index);
155 }
156
167 ErrorCode Get(Data &data, uint32_t &start_index)
168 {
169 for (uint32_t index = start_index; index < SLOT_COUNT; index++)
170 {
171 auto expected = slots_[index].slot.state.load(std::memory_order_acquire);
172 if (expected == SlotState::READY)
173 {
174 if (slots_[index].slot.state.compare_exchange_strong(expected, SlotState::BUSY,
175 std::memory_order_acquire,
176 std::memory_order_relaxed))
177 {
178 data = slots_[index].slot.data;
179 slots_[index].slot.state.store(SlotState::RECYCLE, std::memory_order_release);
180 start_index = index;
181 return ErrorCode::OK;
182 }
183 }
184 if (expected == SlotState::FREE)
185 {
186 start_index = 0;
187 return ErrorCode::EMPTY;
188 }
189 }
190
191 start_index = 0;
192 return ErrorCode::EMPTY;
193 }
194
204 ErrorCode GetFromSlot(Data &data, uint32_t index)
205 {
206 auto expected = slots_[index].slot.state.load(std::memory_order_acquire);
207 if (expected == SlotState::READY)
208 {
209 if (slots_[index].slot.state.compare_exchange_strong(expected, SlotState::BUSY,
210 std::memory_order_acquire,
211 std::memory_order_relaxed))
212 {
213 data = slots_[index].slot.data;
214 slots_[index].slot.state.store(SlotState::RECYCLE, std::memory_order_release);
215 return ErrorCode::OK;
216 }
217 }
218 return ErrorCode::EMPTY;
219 }
220
229 ErrorCode RecycleSlot(uint32_t index)
230 {
231 auto expected = slots_[index].slot.state.load(std::memory_order_relaxed);
232 if (expected == SlotState::READY)
233 {
234 if (slots_[index].slot.state.compare_exchange_strong(expected, SlotState::RECYCLE,
235 std::memory_order_release,
236 std::memory_order_relaxed))
237 {
238 return ErrorCode::OK;
239 }
240 }
241 return ErrorCode::EMPTY;
242 }
243
248 [[nodiscard]] size_t Size() const
249 {
250 uint32_t size = 0;
251 for (uint32_t index = 0; index < SLOT_COUNT; index++)
252 {
253 if (slots_[index].slot.state.load(std::memory_order_relaxed) == SlotState::READY)
254 {
255 size++;
256 }
257 }
258 return size;
259 }
260
265 [[nodiscard]] size_t EmptySize()
266 {
267 uint32_t size = 0;
268 for (uint32_t index = 0; index < SLOT_COUNT; index++)
269 {
270 auto state = slots_[index].slot.state.load(std::memory_order_relaxed);
271 if (state == SlotState::FREE || state == SlotState::RECYCLE)
272 {
273 size++;
274 }
275 }
276 return size;
277 }
278
279 private:
280 const uint32_t SLOT_COUNT;
282};
283} // namespace LibXR
无锁无序槽池 / Lock-free, unordered slot pool
size_t EmptySize()
查询当前池可用槽数量 / Query the number of writable slots in the pool
ErrorCode GetFromSlot(Data &data, uint32_t index)
从指定槽位开始,取出一个元素 / Retrieve an element from the pool
Slot * slots_
槽数组指针 / Array of slots
~LockFreePool()
析构,释放槽池内存 / Destructor, releasing pool memory
ErrorCode PutToSlot(const Data &data, uint32_t index)
向指定槽放入一个元素 / Put an element into a specific slot
ErrorCode Get(Data &data, uint32_t &start_index)
从指定槽位开始,取出一个元素 / Retrieve an element from the pool
SlotState
槽状态 / Slot state
@ RECYCLE
已读待回收 / Slot was read, waiting for next write.
@ READY
写入完成,可读 / Slot contains valid data, ready to read.
@ BUSY
正在写入 / Slot is being written.
@ FREE
空闲,可写 / Slot is free and can be written.
LockFreePool(uint32_t slot_count)
构造对象池 / Constructor for the pool
ErrorCode RecycleSlot(uint32_t index)
回收指定槽位 / Recycle a slot
ErrorCode Put(const Data &data)
向池中放入一个元素 / Put an element into the pool
const uint32_t SLOT_COUNT
槽总数 / Number of slots
ErrorCode Get(Data &data)
从池中取出一个元素 / Retrieve an element from the pool
ErrorCode Put(const Data &data, uint32_t &start_index)
向池中放入一个元素,返回起始槽索引 / Put an element into the pool and return the starting slot index
size_t Size() const
查询池中可取元素数量 / Query the number of available elements in the pool
LibXR 命名空间
Definition ch32_gpio.hpp:9
单个槽结构体 / Individual slot structure (cache line aligned)
Data data
槽内数据 / Stored data
std::atomic< SlotState > state
当前槽状态 / Current state