Skip to content

Commit a29ea9a

Browse files
Improve code.
1 parent acb4ed2 commit a29ea9a

5 files changed

+43
-35
lines changed

WaitFreeRingBufferUtilities/Include/multi-producer-multi-consumer-ring-buffer.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename T, std::size_t Count>
1313
struct RingBuffer<T,
1414
AccessRequirements::MULTI_CONSUMER | AccessRequirements::MULTI_PRODUCER,
1515
Count> : MultiProducerBehaviour<MultiConsumerBehaviour<RingBufferStateBase<Element<T, MultiProducerElementFeature, MultiConsumerElementFeature>,
16-
Count, std::atomic_size_t, std::atomic_size_t>>>
16+
Count>>>
1717
{
1818
};
1919
} // namespace WaitFreeRingBufferUtilities

WaitFreeRingBufferUtilities/Include/multi-producer-single-consumer-ring-buffer.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename T, std::size_t Count>
1313
struct RingBuffer<T,
1414
AccessRequirements::SINGLE_CONSUMER | AccessRequirements::MULTI_PRODUCER,
1515
Count> : MultiProducerBehaviour<SingleConsumerBehaviour<RingBufferStateBase<Element<T, MultiProducerElementFeature>,
16-
Count, SizeTWrapper, std::atomic_size_t>>>
16+
Count>>>
1717
{
1818
};
1919
} // namespace WaitFreeRingBufferUtilities

WaitFreeRingBufferUtilities/Include/ring-buffer-base.inl

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ struct SizeTWrapper
104104
}
105105
};
106106

107-
template <typename Element, std::size_t Count, typename BeginType, typename EndType>
107+
template <typename Element, std::size_t Count>
108108
struct RingBufferStateBase
109109
{
110110
protected:
@@ -115,20 +115,13 @@ protected:
115115
COUNT_MASK = Count - 1,
116116
};
117117

118-
Details::CacheAlignedAndPaddedObject<BeginType> begin;
119-
Details::CacheAlignedAndPaddedObject<EndType> end;
120-
Details::CacheAlignedAndPaddedObject<std::atomic<std::int64_t>> pop_task_count;
121-
Details::CacheAlignedAndPaddedObject<std::atomic<std::int64_t>> push_task_count;
122-
std::array<Details::CacheAlignedAndPaddedObject<Element>, Count> elements;
118+
std::array<Details::CacheAlignedAndPaddedObject<Element>, Count> elements{};
119+
Details::CacheAlignedAndPaddedObject<std::atomic<std::int64_t>> pop_task_count{std::int64_t(0)};
120+
Details::CacheAlignedAndPaddedObject<std::atomic<std::int64_t>> push_task_count{static_cast<std::int64_t>(Count)};
123121

124122
public:
125123
static_assert(Count > 0 && !(COUNT_MASK & Count), "Count should be a power of two.");
126124
static_assert(Count <= static_cast<std::size_t>(std::numeric_limits<std::int64_t>::max()), "Count exceeds the maximum. Count should fit in a std::int64_t.");
127-
128-
RingBufferStateBase() : begin(std::size_t(0)), end(std::size_t(0)),
129-
pop_task_count(std::int64_t(0)), push_task_count(static_cast<std::int64_t>(Count)), elements{}
130-
{
131-
}
132125
};
133126

134127
#ifdef __cpp_lib_optional
@@ -142,6 +135,10 @@ using OptionalType = boost::optional<T>;
142135
template <typename BaseType>
143136
struct MultiProducerBehaviour : BaseType
144137
{
138+
private:
139+
Details::CacheAlignedAndPaddedObject<std::atomic_size_t> end{std::size_t(0)};
140+
141+
public:
145142
using ElementType = typename BaseType::ElementType;
146143

147144
template <typename... Args>
@@ -155,7 +152,7 @@ struct MultiProducerBehaviour : BaseType
155152

156153
while (true)
157154
{
158-
const std::size_t local_end = BaseType::end.fetch_add(1, std::memory_order_acquire);
155+
const std::size_t local_end = end.fetch_add(1, std::memory_order_acquire);
159156
const std::size_t element_index = local_end & BaseType::COUNT_MASK;
160157
bool expected_is_pusher_processing = false;
161158
if (std::atomic_compare_exchange_strong(&BaseType::elements[element_index].is_pusher_processing, &expected_is_pusher_processing, true))
@@ -180,6 +177,10 @@ struct MultiProducerBehaviour : BaseType
180177
template <typename BaseType>
181178
struct MultiConsumerBehaviour : BaseType
182179
{
180+
private:
181+
Details::CacheAlignedAndPaddedObject<std::atomic_size_t> begin{std::size_t(0)};
182+
183+
public:
183184
using ElementType = typename BaseType::ElementType;
184185

185186
OptionalType<ElementType> pop()
@@ -192,7 +193,7 @@ struct MultiConsumerBehaviour : BaseType
192193

193194
while (true)
194195
{
195-
const std::size_t local_begin = BaseType::begin.fetch_add(1, std::memory_order_acquire);
196+
const std::size_t local_begin = begin.fetch_add(1, std::memory_order_acquire);
196197

197198
const std::size_t element_index = local_begin & BaseType::COUNT_MASK;
198199
bool expected_is_popper_processing = false;
@@ -221,6 +222,10 @@ struct MultiConsumerBehaviour : BaseType
221222
template <typename BaseType>
222223
struct SingleProducerBehaviour : BaseType
223224
{
225+
private:
226+
Details::CacheAlignedAndPaddedObject<SizeTWrapper> end{std::size_t(0)};
227+
228+
public:
224229
using ElementType = typename BaseType::ElementType;
225230

226231
template <typename... Args>
@@ -234,23 +239,27 @@ struct SingleProducerBehaviour : BaseType
234239

235240
while (true)
236241
{
237-
const std::size_t element_index = (BaseType::end.value++) & BaseType::COUNT_MASK;
238-
239-
if (BaseType::elements[element_index].value_ptr.load(std::memory_order_relaxed))
240-
continue;
242+
const std::size_t element_index = (end.value++) & BaseType::COUNT_MASK;
241243

242-
BaseType::elements[element_index].value_ptr.store(new (&BaseType::elements[element_index].storage) ElementType(std::forward<Args>(args)...),
243-
std::memory_order_release);
244-
BaseType::pop_task_count.fetch_add(1, std::memory_order_release);
244+
if (!BaseType::elements[element_index].value_ptr.load(std::memory_order_relaxed))
245+
{
246+
BaseType::elements[element_index].value_ptr.store(new (&BaseType::elements[element_index].storage) ElementType(std::forward<Args>(args)...),
247+
std::memory_order_release);
248+
BaseType::pop_task_count.fetch_add(1, std::memory_order_release);
245249

246-
return true;
250+
return true;
251+
}
247252
}
248253
}
249254
};
250255

251256
template <typename BaseType>
252257
struct SingleConsumerBehaviour : BaseType
253258
{
259+
private:
260+
Details::CacheAlignedAndPaddedObject<SizeTWrapper> begin{std::size_t(0)};
261+
262+
public:
254263
using ElementType = typename BaseType::ElementType;
255264

256265
OptionalType<ElementType> pop()
@@ -263,19 +272,19 @@ struct SingleConsumerBehaviour : BaseType
263272

264273
while (true)
265274
{
266-
const std::size_t element_index = (BaseType::begin.value++) & BaseType::COUNT_MASK;
275+
const std::size_t element_index = (begin.value++) & BaseType::COUNT_MASK;
267276

268277
const auto value_ptr = BaseType::elements[element_index].value_ptr.load(std::memory_order_relaxed);
269-
if (!value_ptr)
270-
continue;
271-
272-
OptionalType<ElementType> result{std::move(*value_ptr)};
273-
value_ptr->~ElementType();
278+
if (value_ptr)
279+
{
280+
OptionalType<ElementType> result{std::move(*value_ptr)};
281+
value_ptr->~ElementType();
274282

275-
BaseType::elements[element_index].value_ptr.store(nullptr, std::memory_order_release);
276-
BaseType::push_task_count.fetch_add(1, std::memory_order_release);
283+
BaseType::elements[element_index].value_ptr.store(nullptr, std::memory_order_release);
284+
BaseType::push_task_count.fetch_add(1, std::memory_order_release);
277285

278-
return result;
286+
return result;
287+
}
279288
}
280289
}
281290
};

WaitFreeRingBufferUtilities/Include/single-producer-multi-consumer-ring-buffer.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename T, std::size_t Count>
1313
struct RingBuffer<T,
1414
AccessRequirements::MULTI_CONSUMER | AccessRequirements::SINGLE_PRODUCER,
1515
Count> : SingleProducerBehaviour<MultiConsumerBehaviour<RingBufferStateBase<Element<T, MultiConsumerElementFeature>,
16-
Count, std::atomic_size_t, SizeTWrapper>>>
16+
Count>>>
1717
{
1818
};
1919
} // namespace WaitFreeRingBufferUtilities

WaitFreeRingBufferUtilities/Include/single-producer-single-consumer-ring-buffer.inl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ namespace WaitFreeRingBufferUtilities
1111
template <typename T, std::size_t Count>
1212
struct RingBuffer<T,
1313
AccessRequirements::SINGLE_CONSUMER | AccessRequirements::SINGLE_PRODUCER,
14-
Count> : SingleProducerBehaviour<SingleConsumerBehaviour<RingBufferStateBase<Element<T>,
15-
Count, SizeTWrapper, SizeTWrapper>>>
14+
Count> : SingleProducerBehaviour<SingleConsumerBehaviour<RingBufferStateBase<Element<T>, Count>>>
1615
{
1716
};
1817
} // namespace WaitFreeRingBufferUtilities

0 commit comments

Comments
 (0)