31#ifndef ETL_MPMC_QUEUE_MUTEX_INCLUDED
32#define ETL_MPMC_QUEUE_MUTEX_INCLUDED
55 class queue_mpmc_exception :
public exception
59 queue_mpmc_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
60 : exception(reason_, file_name_, line_number_)
69 class queue_mpmc_empty :
public queue_mpmc_exception
73 queue_mpmc_empty(string_type file_name_, numeric_type line_number_)
74 : queue_mpmc_exception(ETL_ERROR_TEXT(
"queue_mpmc_mutex:empty", ETL_QUEUE_MPMC_MUTEX_FILE_ID
"A"), file_name_, line_number_)
79 template <
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
80 class queue_mpmc_mutex_base
85 typedef typename etl::size_type_lookup<MEMORY_MODEL>::type size_type;
90 size_type capacity()
const
98 size_type max_size()
const
105 queue_mpmc_mutex_base(size_type max_size_)
109 , MAX_SIZE(max_size_)
116 static size_type get_next_index(size_type index, size_type maximum)
120 if (index == maximum) ETL_UNLIKELY
128 size_type write_index;
129 size_type read_index;
130 size_type current_size;
131 const size_type MAX_SIZE;
136 #if defined(ETL_POLYMORPHIC_MPMC_QUEUE_MUTEX) || defined(ETL_POLYMORPHIC_CONTAINERS)
140 virtual ~queue_mpmc_mutex_base() {}
145 ~queue_mpmc_mutex_base() {}
160 template <
typename T, const
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
161 class iqueue_mpmc_mutex :
public queue_mpmc_mutex_base<MEMORY_MODEL>
165 typedef etl::queue_mpmc_mutex_base<MEMORY_MODEL> base_t;
169 typedef T value_type;
170 typedef T& reference;
171 typedef const T& const_reference;
173 typedef T&& rvalue_reference;
175 typedef typename base_t::size_type size_type;
177 using base_t::current_size;
178 using base_t::get_next_index;
179 using base_t::MAX_SIZE;
180 using base_t::read_index;
181 using base_t::write_index;
186 bool push(const_reference value)
190 bool result = push_implementation(value);
201 bool push(rvalue_reference value)
205 bool result = push_implementation(etl::move(value));
213 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03_IMPLEMENTATION)
219 template <
typename... Args>
220 bool emplace(Args&&... args)
224 bool result = emplace_implementation(etl::forward<Args>(args)...);
240 bool result = emplace_implementation();
252 template <
typename T1>
253 bool emplace(
const T1& value1)
257 bool result = emplace_implementation(value1);
269 template <
typename T1,
typename T2>
270 bool emplace(
const T1& value1,
const T2& value2)
274 bool result = emplace_implementation(value1, value2);
286 template <
typename T1,
typename T2,
typename T3>
287 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3)
291 bool result = emplace_implementation(value1, value2, value3);
303 template <
typename T1,
typename T2,
typename T3,
typename T4>
304 bool emplace(
const T1& value1,
const T2& value2,
const T3& value3,
const T4& value4)
308 bool result = emplace_implementation(value1, value2, value3, value4);
319 bool pop(reference value)
323 bool result = pop_implementation(value);
337 bool result = pop_implementation();
351 #if ETL_CHECKING_EXTRA
353 if (current_size != 0)
355 reference inner_result = front_implementation();
362 ETL_ASSERT_FAIL(ETL_ERROR(queue_mpmc_empty));
368 reference result = front_implementation();
378 const_reference front()
const
380 #if ETL_CHECKING_EXTRA
382 if (current_size != 0)
384 const_reference inner_result = front_implementation();
391 ETL_ASSERT_FAIL(ETL_ERROR(queue_mpmc_empty));
397 const_reference result = front_implementation();
409 if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
411 this->write_index = 0;
412 this->read_index = 0;
413 this->current_size = 0;
417 while (pop_implementation())
433 size_type result = (current_size == 0);
447 size_type result = (current_size == MAX_SIZE);
457 size_type
size()
const
461 size_type result = current_size;
471 size_type available()
const
475 size_type result = MAX_SIZE - current_size;
487 iqueue_mpmc_mutex(T* p_buffer_, size_type max_size_)
489 , p_buffer(p_buffer_)
498 bool push_implementation(const_reference value)
500 if (current_size != MAX_SIZE)
502 ::new (&p_buffer[write_index]) T(value);
504 write_index = get_next_index(write_index, MAX_SIZE);
515 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03_IMPLEMENTATION)
519 bool push_implementation(rvalue_reference value)
521 if (current_size != MAX_SIZE)
523 ::new (&p_buffer[write_index]) T(etl::move(value));
525 write_index = get_next_index(write_index, MAX_SIZE);
537 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03_IMPLEMENTATION)
541 template <
typename... Args>
542 bool emplace_implementation(Args&&... args)
544 if (current_size != MAX_SIZE)
546 ::new (&p_buffer[write_index]) T(etl::forward<Args>(args)...);
548 write_index = get_next_index(write_index, MAX_SIZE);
562 bool emplace_implementation()
564 if (current_size != MAX_SIZE)
566 ::new (&p_buffer[write_index]) T();
568 write_index = get_next_index(write_index, MAX_SIZE);
580 template <
typename T1>
581 bool emplace_implementation(
const T1& value1)
583 if (current_size != MAX_SIZE)
585 ::new (&p_buffer[write_index]) T(value1);
587 write_index = get_next_index(write_index, MAX_SIZE);
601 template <
typename T1,
typename T2>
602 bool emplace_implementation(
const T1& value1,
const T2& value2)
604 if (current_size != MAX_SIZE)
606 ::new (&p_buffer[write_index]) T(value1, value2);
608 write_index = get_next_index(write_index, MAX_SIZE);
622 template <
typename T1,
typename T2,
typename T3>
623 bool emplace_implementation(
const T1& value1,
const T2& value2,
const T3& value3)
625 if (current_size != MAX_SIZE)
627 ::new (&p_buffer[write_index]) T(value1, value2, value3);
629 write_index = get_next_index(write_index, MAX_SIZE);
643 template <
typename T1,
typename T2,
typename T3,
typename T4>
644 bool emplace_implementation(
const T1& value1,
const T2& value2,
const T3& value3,
const T4& value4)
646 if (current_size != MAX_SIZE)
648 ::new (&p_buffer[write_index]) T(value1, value2, value3, value4);
650 write_index = get_next_index(write_index, MAX_SIZE);
665 bool pop_implementation(reference value)
667 if (current_size == 0)
673 #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
674 value = etl::move(p_buffer[read_index]);
676 value = p_buffer[read_index];
679 p_buffer[read_index].~T();
681 read_index = get_next_index(read_index, MAX_SIZE);
691 bool pop_implementation()
693 if (current_size == 0)
699 p_buffer[read_index].~T();
701 read_index = get_next_index(read_index, MAX_SIZE);
711 reference front_implementation()
713 return p_buffer[read_index];
719 const_reference front_implementation()
const
721 return p_buffer[read_index];
725 iqueue_mpmc_mutex(
const iqueue_mpmc_mutex&);
726 iqueue_mpmc_mutex& operator=(
const iqueue_mpmc_mutex&);
742 template <
typename T,
size_t SIZE, const
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
743 class queue_mpmc_mutex :
public etl::iqueue_mpmc_mutex<T, MEMORY_MODEL>
747 typedef etl::iqueue_mpmc_mutex<T, MEMORY_MODEL> base_t;
751 typedef typename base_t::size_type size_type;
753 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max),
"Size too large for memory model");
755 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
761 : base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE)
775 queue_mpmc_mutex(
const queue_mpmc_mutex&) ETL_DELETE;
776 queue_mpmc_mutex& operator=(
const queue_mpmc_mutex&) ETL_DELETE;
779 queue_mpmc_mutex(queue_mpmc_mutex&&) =
delete;
780 queue_mpmc_mutex& operator=(queue_mpmc_mutex&&) =
delete;
784 typename etl::aligned_storage<
sizeof(T), etl::alignment_of<T>::value>::type buffer[MAX_SIZE];
787 template <
typename T,
size_t SIZE, const
size_t MEMORY_MODEL>
788 ETL_CONSTANT
typename queue_mpmc_mutex<T, SIZE, MEMORY_MODEL>::size_type queue_mpmc_mutex<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
Definition exception.h:59
bitset_ext
Definition absolute.h:40
std::mutex mutex
This mutex class is implemented using std::mutex.
Definition mutex_std.h:42
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192