31#ifndef ETL_SPSC_QUEUE_ATOMIC_INCLUDED
32#define ETL_SPSC_QUEUE_ATOMIC_INCLUDED
49 template <
size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
50 class queue_spsc_atomic_base
55 typedef typename etl::size_type_lookup<Memory_Model>::type size_type;
64 return read.load(etl::memory_order_acquire) ==
write.load(etl::memory_order_acquire);
74 size_type next_index = get_next_index(
write.load(etl::memory_order_acquire), Reserved);
76 return (next_index ==
read.load(etl::memory_order_acquire));
83 size_type
size()
const
85 size_type write_index =
write.load(etl::memory_order_acquire);
86 size_type read_index =
read.load(etl::memory_order_acquire);
90 if (write_index >= read_index)
92 n = write_index - read_index;
96 n = Reserved - read_index + write_index;
106 size_type available()
const
108 return Reserved -
size() - 1;
114 size_type capacity()
const
122 size_type max_size()
const
129 queue_spsc_atomic_base(size_type reserved_)
132 , Reserved(reserved_)
139 static size_type get_next_index(size_type index, size_type maximum)
143 if (index == maximum) ETL_UNLIKELY
151 etl::atomic<size_type>
write;
152 etl::atomic<size_type>
read;
153 const size_type Reserved;
160 #if defined(ETL_POLYMORPHIC_SPSC_QUEUE_ATOMIC) || defined(ETL_POLYMORPHIC_CONTAINERS)
164 virtual ~queue_spsc_atomic_base() {}
169 ~queue_spsc_atomic_base() {}
184 template <
typename T, const
size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
185 class iqueue_spsc_atomic :
public queue_spsc_atomic_base<Memory_Model>
189 typedef typename etl::queue_spsc_atomic_base<Memory_Model> base_t;
193 typedef T value_type;
194 typedef T& reference;
195 typedef const T& const_reference;
197 typedef T&& rvalue_reference;
199 typedef typename base_t::size_type size_type;
201 using base_t::get_next_index;
203 using base_t::Reserved;
209 bool push(const_reference value)
211 size_type write_index =
write.load(etl::memory_order_relaxed);
212 size_type next_index = get_next_index(write_index, Reserved);
214 if (next_index !=
read.load(etl::memory_order_acquire))
216 ::new (&p_buffer[write_index]) T(value);
218 write.store(next_index, etl::memory_order_release);
227 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ATOMIC_FORCE_CPP03_IMPLEMENTATION)
231 bool push(rvalue_reference value)
233 size_type write_index =
write.load(etl::memory_order_relaxed);
234 size_type next_index = get_next_index(write_index, Reserved);
236 if (next_index !=
read.load(etl::memory_order_acquire))
238 ::new (&p_buffer[write_index]) T(etl::move(value));
240 write.store(next_index, etl::memory_order_release);
250 #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);
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();
289 write.store(next_index, etl::memory_order_release);
303 template <
typename T1>
304 bool emplace(
const T1& value1)
306 size_type write_index =
write.load(etl::memory_order_relaxed);
307 size_type next_index = get_next_index(write_index, Reserved);
309 if (next_index !=
read.load(etl::memory_order_acquire))
311 ::new (&p_buffer[write_index]) T(value1);
313 write.store(next_index, etl::memory_order_release);
327 template <
typename T1,
typename T2>
328 bool emplace(
const T1& value1,
const T2& value2)
330 size_type write_index =
write.load(etl::memory_order_relaxed);
331 size_type next_index = get_next_index(write_index, Reserved);
333 if (next_index !=
read.load(etl::memory_order_acquire))
335 ::new (&p_buffer[write_index]) T(value1, value2);
337 write.store(next_index, etl::memory_order_release);
351 template <
typename T1,
typename T2,
typename T3>
352 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3)
354 size_type write_index =
write.load(etl::memory_order_relaxed);
355 size_type next_index = get_next_index(write_index, Reserved);
357 if (next_index !=
read.load(etl::memory_order_acquire))
359 ::new (&p_buffer[write_index]) T(value1, value2, value3);
361 write.store(next_index, etl::memory_order_release);
375 template <
typename T1,
typename T2,
typename T3,
typename T4>
376 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3,
const T4& value4)
378 size_type write_index =
write.load(etl::memory_order_relaxed);
379 size_type next_index = get_next_index(write_index, Reserved);
381 if (next_index !=
read.load(etl::memory_order_acquire))
383 ::new (&p_buffer[write_index]) T(value1, value2, value3, value4);
385 write.store(next_index, etl::memory_order_release);
398 bool front(reference value)
400 size_type read_index =
read.load(etl::memory_order_relaxed);
402 if (read_index ==
write.load(etl::memory_order_acquire))
408 value = p_buffer[read_index];
416 bool pop(reference value)
418 size_type read_index =
read.load(etl::memory_order_relaxed);
420 if (read_index ==
write.load(etl::memory_order_acquire))
426 size_type next_index = get_next_index(read_index, Reserved);
428 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
429 value = etl::move(p_buffer[read_index]);
431 value = p_buffer[read_index];
434 p_buffer[read_index].~T();
436 read.store(next_index, etl::memory_order_release);
446 size_type read_index =
read.load(etl::memory_order_relaxed);
448 if (read_index ==
write.load(etl::memory_order_acquire))
454 size_type next_index = get_next_index(read_index, Reserved);
456 p_buffer[read_index].~T();
458 read.store(next_index, etl::memory_order_release);
468 size_type read_index =
read.load(etl::memory_order_relaxed);
470 return p_buffer[read_index];
476 const_reference front()
const
478 size_type read_index =
read.load(etl::memory_order_relaxed);
480 return p_buffer[read_index];
490 if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
509 iqueue_spsc_atomic(T* p_buffer_, size_type reserved_)
511 , p_buffer(p_buffer_)
518 iqueue_spsc_atomic(
const iqueue_spsc_atomic&) ETL_DELETE;
519 iqueue_spsc_atomic& operator=(
const iqueue_spsc_atomic&) ETL_DELETE;
522 iqueue_spsc_atomic(iqueue_spsc_atomic&&) =
delete;
523 iqueue_spsc_atomic& operator=(iqueue_spsc_atomic&&) =
delete;
538 template <
typename T,
size_t Size, const
size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
539 class queue_spsc_atomic :
public iqueue_spsc_atomic<T, Memory_Model>
543 typedef typename etl::iqueue_spsc_atomic<T, Memory_Model> base_t;
547 typedef typename base_t::size_type size_type;
551 static ETL_CONSTANT size_type Reserved_Size = size_type(Size + 1);
555 ETL_STATIC_ASSERT((Size <= (etl::integral_limits<size_type>::max - 1)),
"Size too large for memory model");
557 static ETL_CONSTANT size_type MAX_SIZE = size_type(Size);
563 : base_t(reinterpret_cast<T*>(&buffer[0]), Reserved_Size)
578 typename etl::aligned_storage<
sizeof(T), etl::alignment_of<T>::value>::type buffer[Reserved_Size];
581 template <
typename T,
size_t Size, const
size_t Memory_Model>
582 ETL_CONSTANT
typename queue_spsc_atomic<T, Size, Memory_Model>::size_type queue_spsc_atomic<T, Size, Memory_Model>::MAX_SIZE;
etl::optional< T > read(etl::bit_stream_reader &stream)
Read a checked type from a stream.
Definition bit_stream.h:1430
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1434
bool write(etl::bit_stream_writer &stream, bool value)
Definition bit_stream.h:1035