Loading...
Searching...
No Matches
queue.h
Go to the documentation of this file.
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2014 John Wellbelove, Mark Kitson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef ETL_QUEUE_INCLUDED
#define ETL_QUEUE_INCLUDED
#include "platform.h"
#include "alignment.h"
#include "debug_count.h"
#include "error_handler.h"
#include "exception.h"
#include "integral_limits.h"
#include "memory_model.h"
#include "parameter_type.h"
#include "placement_new.h"
#include "type_traits.h"
#include "utility.h"
#include <stddef.h>
//*****************************************************************************
//*****************************************************************************
namespace etl
{
//***************************************************************************
//***************************************************************************
class queue_exception : public exception
{
public:
queue_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class queue_full : public queue_exception
{
public:
queue_full(string_type file_name_, numeric_type line_number_)
: queue_exception(ETL_ERROR_TEXT("queue:full", ETL_QUEUE_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class queue_empty : public queue_exception
{
public:
queue_empty(string_type file_name_, numeric_type line_number_)
: queue_exception(ETL_ERROR_TEXT("queue:empty", ETL_QUEUE_FILE_ID"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
template <size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_base
{
public:
typedef typename etl::size_type_lookup<MEMORY_MODEL>::type size_type;
//*************************************************************************
//*************************************************************************
size_type size() const
{
return current_size;
}
//*************************************************************************
//*************************************************************************
size_type max_size() const
{
return CAPACITY;
}
//*************************************************************************
//*************************************************************************
size_type capacity() const
{
return CAPACITY;
}
//*************************************************************************
//*************************************************************************
bool empty() const
{
return current_size == 0;
}
//*************************************************************************
//*************************************************************************
bool full() const
{
return current_size == CAPACITY;
}
//*************************************************************************
//*************************************************************************
size_type available() const
{
return max_size() - size();
}
protected:
//*************************************************************************
//*************************************************************************
queue_base(size_type max_size_)
: in(0)
, out(0)
, current_size(0)
, CAPACITY(max_size_)
{
}
//*************************************************************************
//*************************************************************************
~queue_base() {}
//*************************************************************************
//*************************************************************************
void add_in()
{
if (++in == CAPACITY) ETL_UNLIKELY
{
in = 0;
}
++current_size;
ETL_INCREMENT_DEBUG_COUNT;
}
//*************************************************************************
//*************************************************************************
void del_out()
{
if (++out == CAPACITY) ETL_UNLIKELY
{
out = 0;
}
--current_size;
ETL_DECREMENT_DEBUG_COUNT;
}
//*************************************************************************
//*************************************************************************
void index_clear()
{
in = 0;
out = 0;
current_size = 0;
ETL_RESET_DEBUG_COUNT;
}
size_type in;
size_type out;
size_type current_size;
const size_type CAPACITY;
ETL_DECLARE_DEBUG_COUNT;
};
//***************************************************************************
//***************************************************************************
template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class iqueue : public etl::queue_base<MEMORY_MODEL>
{
private:
typedef typename etl::queue_base<MEMORY_MODEL> base_t;
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
#if ETL_USING_CPP11
typedef T&& rvalue_reference;
#endif
typedef T* pointer;
typedef const T* const_pointer;
typedef typename base_t::size_type size_type;
using base_t::add_in;
using base_t::CAPACITY;
using base_t::current_size;
using base_t::del_out;
using base_t::empty;
using base_t::full;
using base_t::in;
using base_t::out;
//*************************************************************************
//*************************************************************************
reference front()
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
return p_buffer[out];
}
//*************************************************************************
//*************************************************************************
const_reference front() const
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
return p_buffer[out];
}
//*************************************************************************
//*************************************************************************
reference back()
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
}
//*************************************************************************
//*************************************************************************
const_reference back() const
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
}
//*************************************************************************
//*************************************************************************
void push(const_reference value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
::new (&p_buffer[in]) T(value);
add_in();
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void push(rvalue_reference value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
::new (&p_buffer[in]) T(etl::move(value));
add_in();
}
#endif
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************
//*************************************************************************
template <typename... Args>
reference emplace(Args&&... args)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T(etl::forward<Args>(args)...);
add_in();
return value;
}
#else
//*************************************************************************
//*************************************************************************
reference emplace()
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T();
add_in();
return value;
}
//*************************************************************************
//*************************************************************************
template <typename T1>
reference emplace(const T1& value1)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T(value1);
add_in();
return value;
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2>
reference emplace(const T1& value1, const T2& value2)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T(value1, value2);
add_in();
return value;
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2, typename T3>
reference emplace(const T1& value1, const T2& value2, const T3& value3)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T(value1, value2, value3);
add_in();
return value;
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
reference value = p_buffer[in];
::new (&value) T(value1, value2, value3, value4);
add_in();
return value;
}
#endif
//*************************************************************************
//*************************************************************************
void clear()
{
if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
{
base_t::index_clear();
}
else
{
while (current_size > 0)
{
p_buffer[out].~T();
del_out();
}
in = 0;
out = 0;
}
}
//*************************************************************************
//*************************************************************************
void pop()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(queue_empty));
p_buffer[out].~T();
del_out();
}
//*************************************************************************
//*************************************************************************
void pop_into(reference destination)
{
destination = ETL_MOVE(front());
pop();
}
//*************************************************************************
//*************************************************************************
template <typename TContainer>
void pop_into(TContainer& destination)
{
destination.push(ETL_MOVE(front()));
pop();
}
//*************************************************************************
//*************************************************************************
iqueue& operator=(const iqueue& rhs)
{
if (&rhs != this)
{
clear();
clone(rhs);
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
iqueue& operator=(iqueue&& rhs)
{
if (&rhs != this)
{
clear();
move_clone(rhs);
}
return *this;
}
#endif
protected:
//*************************************************************************
//*************************************************************************
void clone(const iqueue& other)
{
clear();
size_type index = other.out;
for (size_type i = 0; i < other.size(); ++i)
{
push(other.p_buffer[index]);
index = (index == (CAPACITY - 1)) ? 0 : index + 1;
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void move_clone(iqueue&& other)
{
clear();
size_type index = other.out;
for (size_type i = 0; i < other.size(); ++i)
{
push(etl::move(other.p_buffer[index]));
index = (index == (CAPACITY - 1)) ? 0 : index + 1;
}
}
#endif
//*************************************************************************
//*************************************************************************
iqueue(T* p_buffer_, size_type max_size_)
: base_t(max_size_)
, p_buffer(p_buffer_)
{
}
private:
// Disable copy construction.
iqueue(const iqueue&);
T* p_buffer;
//*************************************************************************
//*************************************************************************
#if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS)
public:
virtual ~iqueue() {}
#else
protected:
~iqueue() {}
#endif
};
//***************************************************************************
//***************************************************************************
template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class queue : public etl::iqueue<T, MEMORY_MODEL>
{
private:
typedef etl::iqueue<T, MEMORY_MODEL> base_t;
public:
typedef typename base_t::size_type size_type;
typedef typename etl::aligned_storage< sizeof(T), etl::alignment_of<T>::value>::type container_type;
ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
//*************************************************************************
//*************************************************************************
queue()
: base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
{
}
//*************************************************************************
//*************************************************************************
queue(const queue& rhs)
: base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
{
base_t::clone(rhs);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
queue(queue&& rhs)
: base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
{
base_t::move_clone(etl::move(rhs));
}
#endif
//*************************************************************************
//*************************************************************************
~queue()
{
base_t::clear();
}
//*************************************************************************
//*************************************************************************
queue& operator=(const queue& rhs)
{
if (&rhs != this)
{
base_t::clone(rhs);
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
queue& operator=(queue&& rhs)
{
if (&rhs != this)
{
base_t::move_clone(etl::move(rhs));
}
return *this;
}
#endif
private:
container_type buffer[SIZE];
};
template <typename T, const size_t SIZE, const size_t MEMORY_MODEL>
ETL_CONSTANT typename queue<T, SIZE, MEMORY_MODEL>::size_type queue<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
} // namespace etl
#endif
alignment.h
etl::size_type
debug_count.h
error_handler.h
exception.h
etl::aligned_storage
Definition alignment.h:251
etl::exception::exception
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
etl::integral_limits
Definition integral_limits.h:517
etl::queue::~queue
~queue()
Destructor.
Definition queue.h:670
etl::queue_base< MEMORY_MODEL >::in
size_type in
Definition queue.h:218
etl::iqueue::emplace
reference emplace(const T1 &value1, const T2 &value2)
Definition queue.h:403
etl::queue::operator=
queue & operator=(const queue &rhs)
Assignment operator.
Definition queue.h:678
etl::iqueue::front
const_reference front() const
Definition queue.h:282
etl::queue_base< MEMORY_MODEL >::ETL_DECLARE_DEBUG_COUNT
ETL_DECLARE_DEBUG_COUNT
Definition queue.h:222
etl::iqueue::const_pointer
const T * const_pointer
A const pointer to the type used in the queue.
Definition queue.h:252
etl::iqueue::push
void push(const_reference value)
Definition queue.h:318
etl::iqueue::emplace
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue.h:423
etl::iqueue::back
const_reference back() const
Definition queue.h:306
etl::iqueue::front
reference front()
Definition queue.h:270
etl::queue_base< MEMORY_MODEL >::current_size
size_type current_size
Definition queue.h:220
etl::queue::queue
queue()
Default constructor.
Definition queue.h:642
etl::iqueue::pop_into
void pop_into(reference destination)
Definition queue.h:496
etl::queue_base::size_type
etl::size_type_lookup< MEMORY_MODEL >::type size_type
The type used for determining the size of queue.
Definition queue.h:109
etl::iqueue::operator=
iqueue & operator=(const iqueue &rhs)
Assignment operator.
Definition queue.h:519
etl::iqueue::emplace
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue.h:444
etl::iqueue::value_type
T value_type
The type stored in the queue.
Definition queue.h:245
etl::iqueue::pop
void pop()
Definition queue.h:483
etl::queue_base::index_clear
void index_clear()
Clears the indexes.
Definition queue.h:210
etl::queue_base< MEMORY_MODEL >::out
size_type out
Definition queue.h:219
etl::queue_base::~queue_base
~queue_base()
Destructor.
Definition queue.h:178
etl::queue_base::full
bool full() const
Definition queue.h:148
etl::iqueue::back
reference back()
Definition queue.h:294
etl::queue_base::available
size_type available() const
Definition queue.h:157
etl::queue_base::del_out
void del_out()
Increments (and wraps) the 'out' index value to record a queue deletion.
Definition queue.h:197
etl::queue_base::add_in
void add_in()
Increments (and wraps) the 'in' index value to record a queue addition.
Definition queue.h:183
etl::iqueue::~iqueue
~iqueue()
Destructor.
Definition queue.h:610
etl::queue_base< MEMORY_MODEL >::CAPACITY
const size_type CAPACITY
Definition queue.h:221
etl::iqueue::emplace
reference emplace()
Definition queue.h:366
etl::iqueue::size_type
base_t::size_type size_type
The type used for determining the size of the queue.
Definition queue.h:253
etl::iqueue::iqueue
iqueue(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:585
etl::queue_base::queue_base
queue_base(size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:167
etl::iqueue::clone
void clone(const iqueue &other)
Make this a clone of the supplied queue.
Definition queue.h:551
etl::queue::queue
queue(const queue &rhs)
Copy constructor.
Definition queue.h:650
etl::queue_base::size
size_type size() const
Returns the current number of items in the queue.
Definition queue.h:114
etl::iqueue::const_reference
const T & const_reference
A const reference to the type used in the queue.
Definition queue.h:247
etl::iqueue::pop_into
void pop_into(TContainer &destination)
Definition queue.h:510
etl::queue_base::capacity
size_type capacity() const
Returns the maximum number of items that can be queued.
Definition queue.h:130
etl::iqueue::reference
T & reference
A reference to the type used in the queue.
Definition queue.h:246
etl::queue_base::max_size
size_type max_size() const
Returns the maximum number of items that can be queued.
Definition queue.h:122
etl::iqueue::emplace
reference emplace(const T1 &value1)
Definition queue.h:384
etl::queue_base::empty
bool empty() const
Definition queue.h:139
etl::iqueue::pointer
T * pointer
A pointer to the type used in the queue.
Definition queue.h:251
etl::iqueue::clear
void clear()
Clears the queue to the empty state.
Definition queue.h:458
etl::iqueue
This is the base for all queues that contain a particular type.
Definition queue.h:238
etl::queue
Definition queue.h:625
etl::queue_base
Definition queue.h:105
etl::queue_empty
Definition queue.h:90
etl::queue_full
Definition queue.h:76
integral_limits.h
memory_model.h
etl
Definition absolute.h:40
parameter_type.h
placement_new.h
platform.h
etl::type
etl::size_type_lookup
Definition memory_model.h:50
type_traits.h
utility.h