31#ifndef ETL_SPSC_QUEUE_ATOMIC_INCLUDED
32#define ETL_SPSC_QUEUE_ATOMIC_INCLUDED
50 template <
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
51 class queue_spsc_atomic_base
65 return read.load(etl::memory_order_acquire) ==
write.load(etl::memory_order_acquire);
75 size_type next_index = get_next_index(
write.load(etl::memory_order_acquire), RESERVED);
77 return (next_index ==
read.load(etl::memory_order_acquire));
84 size_type size()
const
86 size_type write_index =
write.load(etl::memory_order_acquire);
87 size_type read_index =
read.load(etl::memory_order_acquire);
91 if (write_index >= read_index)
93 n = write_index - read_index;
97 n = RESERVED - read_index + write_index;
107 size_type available()
const
109 return RESERVED - size() - 1;
115 size_type capacity()
const
130 queue_spsc_atomic_base(size_type reserved_)
140 static size_type get_next_index(size_type index, size_type maximum)
144 if (index == maximum) ETL_UNLIKELY
152 etl::atomic<size_type>
write;
153 etl::atomic<size_type>
read;
154 const size_type RESERVED;
161#if defined(ETL_POLYMORPHIC_SPSC_QUEUE_ATOMIC) || defined(ETL_POLYMORPHIC_CONTAINERS)
163 virtual ~queue_spsc_atomic_base()
168 ~queue_spsc_atomic_base()
185 template <
typename T, const
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
186 class iqueue_spsc_atomic :
public queue_spsc_atomic_base<MEMORY_MODEL>
190 typedef typename etl::queue_spsc_atomic_base<MEMORY_MODEL> base_t;
194 typedef T value_type;
195 typedef T& reference;
196 typedef const T& const_reference;
198 typedef T&& rvalue_reference;
200 typedef typename base_t::size_type size_type;
204 using base_t::RESERVED;
205 using base_t::get_next_index;
210 bool push(const_reference value)
212 size_type write_index =
write.load(etl::memory_order_relaxed);
213 size_type next_index = get_next_index(write_index, RESERVED);
215 if (next_index !=
read.load(etl::memory_order_acquire))
217 ::new (&p_buffer[write_index]) T(value);
219 write.store(next_index, etl::memory_order_release);
228#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ATOMIC_FORCE_CPP03_IMPLEMENTATION)
232 bool push(rvalue_reference value)
234 size_type write_index =
write.load(etl::memory_order_relaxed);
235 size_type next_index = get_next_index(write_index, RESERVED);
237 if (next_index !=
read.load(etl::memory_order_acquire))
239 ::new (&p_buffer[write_index]) T(etl::move(value));
241 write.store(next_index, etl::memory_order_release);
251#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ATOMIC_FORCE_CPP03_IMPLEMENTATION)
256 template <
typename ... Args>
257 bool emplace(Args&&... args)
259 size_type write_index =
write.load(etl::memory_order_relaxed);
260 size_type next_index = get_next_index(write_index, RESERVED);
262 if (next_index !=
read.load(etl::memory_order_acquire))
264 ::new (&p_buffer[write_index]) T(etl::forward<Args>(args)...);
266 write.store(next_index, etl::memory_order_release);
279 template <
typename T1>
280 bool emplace(
const T1& value1)
282 size_type write_index =
write.load(etl::memory_order_relaxed);
283 size_type next_index = get_next_index(write_index, RESERVED);
285 if (next_index !=
read.load(etl::memory_order_acquire))
287 ::new (&p_buffer[write_index]) T(value1);
289 write.store(next_index, etl::memory_order_release);
302 template <
typename T1,
typename T2>
303 bool emplace(
const T1& value1,
const T2& value2)
305 size_type write_index =
write.load(etl::memory_order_relaxed);
306 size_type next_index = get_next_index(write_index, RESERVED);
308 if (next_index !=
read.load(etl::memory_order_acquire))
310 ::new (&p_buffer[write_index]) T(value1, value2);
312 write.store(next_index, etl::memory_order_release);
325 template <
typename T1,
typename T2,
typename T3>
326 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3)
328 size_type write_index =
write.load(etl::memory_order_relaxed);
329 size_type next_index = get_next_index(write_index, RESERVED);
331 if (next_index !=
read.load(etl::memory_order_acquire))
333 ::new (&p_buffer[write_index]) T(value1, value2, value3);
335 write.store(next_index, etl::memory_order_release);
348 template <
typename T1,
typename T2,
typename T3,
typename T4>
349 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3,
const T4& value4)
351 size_type write_index =
write.load(etl::memory_order_relaxed);
352 size_type next_index = get_next_index(write_index, RESERVED);
354 if (next_index !=
read.load(etl::memory_order_acquire))
356 ::new (&p_buffer[write_index]) T(value1, value2, value3, value4);
358 write.store(next_index, etl::memory_order_release);
371 bool front(reference value)
373 size_type read_index =
read.load(etl::memory_order_relaxed);
375 if (read_index ==
write.load(etl::memory_order_acquire))
381 value = p_buffer[read_index];
389 bool pop(reference value)
391 size_type read_index =
read.load(etl::memory_order_relaxed);
393 if (read_index ==
write.load(etl::memory_order_acquire))
399 size_type next_index = get_next_index(read_index, RESERVED);
401#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
402 value = etl::move(p_buffer[read_index]);
404 value = p_buffer[read_index];
407 p_buffer[read_index].~T();
409 read.store(next_index, etl::memory_order_release);
419 size_type read_index =
read.load(etl::memory_order_relaxed);
421 if (read_index ==
write.load(etl::memory_order_acquire))
427 size_type next_index = get_next_index(read_index, RESERVED);
429 p_buffer[read_index].~T();
431 read.store(next_index, etl::memory_order_release);
441 size_type read_index =
read.load(etl::memory_order_relaxed);
443 return p_buffer[read_index];
449 const_reference front()
const
451 size_type read_index =
read.load(etl::memory_order_relaxed);
453 return p_buffer[read_index];
474 iqueue_spsc_atomic(T* p_buffer_, size_type reserved_)
483 iqueue_spsc_atomic(
const iqueue_spsc_atomic&) ETL_DELETE;
484 iqueue_spsc_atomic& operator =(
const iqueue_spsc_atomic&) ETL_DELETE;
487 iqueue_spsc_atomic(iqueue_spsc_atomic&&) =
delete;
488 iqueue_spsc_atomic& operator =(iqueue_spsc_atomic&&) =
delete;
502 template <
typename T,
size_t SIZE, const
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
503 class queue_spsc_atomic :
public iqueue_spsc_atomic<T, MEMORY_MODEL>
507 typedef typename etl::iqueue_spsc_atomic<T, MEMORY_MODEL> base_t;
511 typedef typename base_t::size_type size_type;
515 static ETL_CONSTANT size_type RESERVED_SIZE = size_type(SIZE + 1);
521 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
527 : base_t(reinterpret_cast<T*>(&buffer[0]), RESERVED_SIZE)
545 template <
typename T,
size_t SIZE, const
size_t MEMORY_MODEL>
546 ETL_CONSTANT
typename queue_spsc_atomic<T, SIZE, MEMORY_MODEL>::size_type queue_spsc_atomic<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
Definition: alignment.h:221
Definition: integral_limits.h:468
add_rvalue_reference
Definition: type_traits_generator.h:1327
bitset_ext
Definition: absolute.h:38
size_t max_size() const
Returns the maximum number of items in the variant_pool.
Definition: variant_pool_generator.h:281
etl::optional< T > read(etl::bit_stream_reader &stream)
Read a checked type from a stream.
Definition: bit_stream.h:1348
bool write(etl::bit_stream_writer &stream, bool value)
Definition: bit_stream.h:992
Definition: memory_model.h:50