Skip to content

Commit 5121d03

Browse files
committed
LockFreeFifoDyn does not require power of 2 sized buffer
1 parent f1531b0 commit 5121d03

File tree

1 file changed

+6
-16
lines changed

1 file changed

+6
-16
lines changed

util/lockfree_fifo_spsc_dyn.hh

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#pragma once
2-
#include "util/math.hh"
32
#include <atomic>
43
#include <optional>
54
#include <vector>
@@ -9,18 +8,13 @@
98
// For cheaply copied types
109
// Will not overwrite -- put() returns false if buffer is full, and get() returns nullopt if buffer is empty.
1110
// Provide the buffer size in the constructor.
12-
// max_size_ MUST be a power of 2. If it's not, the next-highest power of 2 will be used for the size.
1311
//
1412
// Edge-case: max_size cannot be more than half the largest integer representable by size_t
1513
template<class T>
1614
class LockFreeFifoSpscDyn {
1715
public:
18-
size_t max_size_;
19-
size_t SIZE_MASK;
20-
2116
LockFreeFifoSpscDyn(size_t max_size)
22-
: max_size_{MathTools::next_power_of_2(max_size)}
23-
, SIZE_MASK{max_size_ - 1}
17+
: max_size_{max_size}
2418
, head_{0}
2519
, tail_{0}
2620
, buf_(max_size_) {
@@ -30,19 +24,15 @@ public:
3024
// Useful, for example, if get() and put() happen at the same rates
3125
// and you want to provide a fixed delay
3226
LockFreeFifoSpscDyn(size_t max_size, size_t head)
33-
: max_size_{MathTools::next_power_of_2(max_size)}
34-
, SIZE_MASK{max_size_ - 1}
27+
: max_size_{max_size}
3528
, head_{head}
3629
, tail_{0}
3730
, buf_(max_size_) {
3831
}
3932

4033
// Resets and resizes the vector. All contents are lost.
41-
// max_size must be a power of 2 or else the next highest power of 2 will be used.
4234
// If max_size does not change, do nothing.
43-
// Edge-case: max_size cannot be more than half the largest integer representable by size_t
4435
void resize(size_t new_max_size) {
45-
new_max_size = MathTools::next_power_of_2(new_max_size);
4636
if (new_max_size != max_size_) {
4737
reset();
4838

@@ -54,7 +44,6 @@ public:
5444
buf_.resize(new_max_size);
5545

5646
max_size_ = new_max_size;
57-
SIZE_MASK = max_size_ - 1;
5847
}
5948
}
6049

@@ -67,7 +56,7 @@ public:
6756
if ((tmp_head - tail_.load(std::memory_order_acquire)) == max_size_)
6857
return false;
6958

70-
buf_[tmp_head & SIZE_MASK] = item;
59+
buf_[tmp_head % max_size_] = item;
7160
tmp_head++;
7261
std::atomic_signal_fence(std::memory_order_release);
7362
head_.store(tmp_head, std::memory_order_release);
@@ -101,7 +90,7 @@ public:
10190
return std::nullopt;
10291
}
10392

104-
auto item = buf_[tmp_tail & SIZE_MASK];
93+
auto item = buf_[tmp_tail % max_size_];
10594
tmp_tail++;
10695
std::atomic_signal_fence(std::memory_order_release);
10796
tail_.store(tmp_tail, std::memory_order_release);
@@ -115,7 +104,7 @@ public:
115104
return false;
116105
}
117106

118-
t = std::move(buf_[tmp_tail & SIZE_MASK]);
107+
t = std::move(buf_[tmp_tail % max_size_]);
119108
tmp_tail++;
120109
std::atomic_signal_fence(std::memory_order_release);
121110
tail_.store(tmp_tail, std::memory_order_release);
@@ -168,6 +157,7 @@ public:
168157
}
169158

170159
private:
160+
size_t max_size_;
171161
std::atomic<size_t> head_ = 0;
172162
std::atomic<size_t> tail_ = 0;
173163
std::vector<T> buf_;

0 commit comments

Comments
 (0)