@@ -104,7 +104,7 @@ struct SizeTWrapper
104
104
}
105
105
};
106
106
107
- template <typename Element, std::size_t Count, typename BeginType, typename EndType >
107
+ template <typename Element, std::size_t Count>
108
108
struct RingBufferStateBase
109
109
{
110
110
protected:
@@ -115,20 +115,13 @@ protected:
115
115
COUNT_MASK = Count - 1 ,
116
116
};
117
117
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)};
123
121
124
122
public:
125
123
static_assert (Count > 0 && !(COUNT_MASK & Count), " Count should be a power of two." );
126
124
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
- }
132
125
};
133
126
134
127
#ifdef __cpp_lib_optional
@@ -142,6 +135,10 @@ using OptionalType = boost::optional<T>;
142
135
template <typename BaseType>
143
136
struct MultiProducerBehaviour : BaseType
144
137
{
138
+ private:
139
+ Details::CacheAlignedAndPaddedObject<std::atomic_size_t > end{std::size_t (0 )};
140
+
141
+ public:
145
142
using ElementType = typename BaseType::ElementType;
146
143
147
144
template <typename ... Args>
@@ -155,7 +152,7 @@ struct MultiProducerBehaviour : BaseType
155
152
156
153
while (true )
157
154
{
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);
159
156
const std::size_t element_index = local_end & BaseType::COUNT_MASK;
160
157
bool expected_is_pusher_processing = false ;
161
158
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
180
177
template <typename BaseType>
181
178
struct MultiConsumerBehaviour : BaseType
182
179
{
180
+ private:
181
+ Details::CacheAlignedAndPaddedObject<std::atomic_size_t > begin{std::size_t (0 )};
182
+
183
+ public:
183
184
using ElementType = typename BaseType::ElementType;
184
185
185
186
OptionalType<ElementType> pop ()
@@ -192,7 +193,7 @@ struct MultiConsumerBehaviour : BaseType
192
193
193
194
while (true )
194
195
{
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);
196
197
197
198
const std::size_t element_index = local_begin & BaseType::COUNT_MASK;
198
199
bool expected_is_popper_processing = false ;
@@ -221,6 +222,10 @@ struct MultiConsumerBehaviour : BaseType
221
222
template <typename BaseType>
222
223
struct SingleProducerBehaviour : BaseType
223
224
{
225
+ private:
226
+ Details::CacheAlignedAndPaddedObject<SizeTWrapper> end{std::size_t (0 )};
227
+
228
+ public:
224
229
using ElementType = typename BaseType::ElementType;
225
230
226
231
template <typename ... Args>
@@ -234,23 +239,27 @@ struct SingleProducerBehaviour : BaseType
234
239
235
240
while (true )
236
241
{
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;
241
243
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);
245
249
246
- return true ;
250
+ return true ;
251
+ }
247
252
}
248
253
}
249
254
};
250
255
251
256
template <typename BaseType>
252
257
struct SingleConsumerBehaviour : BaseType
253
258
{
259
+ private:
260
+ Details::CacheAlignedAndPaddedObject<SizeTWrapper> begin{std::size_t (0 )};
261
+
262
+ public:
254
263
using ElementType = typename BaseType::ElementType;
255
264
256
265
OptionalType<ElementType> pop ()
@@ -263,19 +272,19 @@ struct SingleConsumerBehaviour : BaseType
263
272
264
273
while (true )
265
274
{
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;
267
276
268
277
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 ();
274
282
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);
277
285
278
- return result;
286
+ return result;
287
+ }
279
288
}
280
289
}
281
290
};
0 commit comments