Modified element creation so that fundamental types do not make unnecessary calls to constructors and destructors.

This commit is contained in:
John Wellbelove 2016-06-18 07:07:51 +01:00
parent 54d90ffbf3
commit 800b9b3555
5 changed files with 433 additions and 32 deletions

View File

@ -1240,7 +1240,7 @@ namespace etl
_end = iterator(0, *this, p_buffer);
}
iterator _begin; ///Iterator to the _begin item in the deque.
iterator _begin; ///Iterator to the _begin item in the deque.
iterator _end; ///Iterator to the _end item in the deque.
pointer p_buffer; ///The buffer for the deque.
@ -1249,7 +1249,24 @@ namespace etl
//*********************************************************************
/// Create a new element with a default value at the front.
//*********************************************************************
void create_element_front()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element_front()
{
if (!empty())
{
--_begin;
}
++current_size;
}
//*********************************************************************
/// Create a new element with a default value at the front.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element_front()
{
if (!empty())
{
@ -1264,7 +1281,40 @@ namespace etl
/// Create a new elements from a range at the front.
//*********************************************************************
template <typename TIterator>
void create_element_front(size_t n, TIterator from)
typename etl::enable_if<etl::is_fundamental<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
create_element_front(size_t n, TIterator from)
{
if (n == 0)
{
return;
}
if (!empty())
{
--_begin;
--n;
}
if (n > 0)
{
_begin -= n;
}
iterator item = _begin;
do
{
*item++ = *from++;
++current_size;
} while (n-- != 0);
}
//*********************************************************************
/// Create a new elements from a range at the front.
//*********************************************************************
template <typename TIterator>
typename etl::enable_if<!etl::is_fundamental<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
create_element_front(size_t n, TIterator from)
{
if (n == 0)
{
@ -1295,7 +1345,20 @@ namespace etl
//*********************************************************************
/// Create a new element with a default value at the back.
//*********************************************************************
void create_element_back()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element_back()
{
++_end;
++current_size;
}
//*********************************************************************
/// Create a new element with a default value at the back.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element_back()
{
new(&(*_end)) T();
++_end;
@ -1305,7 +1368,20 @@ namespace etl
//*********************************************************************
/// Create a new element with a default value at the front.
//*********************************************************************
void create_element_front(parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element_front(parameter_t value)
{
--_begin;
++current_size;
}
//*********************************************************************
/// Create a new element with a default value at the front.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element_front(parameter_t value)
{
--_begin;
new(&(*_begin)) T(value);
@ -1315,7 +1391,21 @@ namespace etl
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
void create_element_back(parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element_back(parameter_t value)
{
*_end = value;
++_end;
++current_size;
}
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element_back(parameter_t value)
{
new(&(*_end)) T(value);
++_end;
@ -1325,7 +1415,20 @@ namespace etl
//*********************************************************************
/// Destroy an element at the front.
//*********************************************************************
void destroy_element_front()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
destroy_element_front()
{
--current_size;
++_begin;
}
//*********************************************************************
/// Destroy an element at the front.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
destroy_element_front()
{
(*_begin).~T();
--current_size;
@ -1335,7 +1438,20 @@ namespace etl
//*********************************************************************
/// Destroy an element at the back.
//*********************************************************************
void destroy_element_back()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
destroy_element_back()
{
--_end;
--current_size;
}
//*********************************************************************
/// Destroy an element at the back.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
destroy_element_back()
{
--_end;
(*_end).~T();
@ -1431,7 +1547,7 @@ bool operator <(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
template <typename T>
bool operator <=(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
{
return !operator >(lhs, rhs);
return !(lhs > rhs);
}
//***************************************************************************
@ -1444,7 +1560,7 @@ bool operator <=(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
template <typename T>
bool operator >(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
{
return operator <(rhs, lhs);
return (rhs < lhs);
}
//***************************************************************************
@ -1457,7 +1573,7 @@ bool operator >(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
template <typename T>
bool operator >=(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
{
return !operator <(lhs, rhs);
return !(lhs < rhs);
}
#undef __ETL_IN_IDEQUE_H__

View File

@ -312,6 +312,30 @@ namespace etl
return end();
}
//*************************************************************************
/// Allocate an object from the pool.
/// Uses the default constructor.
/// If asserts or exceptions are enabled and there are no more free items an
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, T*>::type
allocate()
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
#else
ETL_ASSERT(items_allocated < MAX_SIZE, ETL_ERROR(pool_no_allocation));
#endif
T* result = &p_buffer[next_free];
in_use_flags.set(next_free);
next_free = in_use_flags.find_first(false);
++items_allocated;
return result;
}
//*************************************************************************
/// Allocate an object from the pool.
/// Uses the default constructor.
@ -319,7 +343,9 @@ namespace etl
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
T* allocate()
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, T*>::type
allocate()
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
@ -340,7 +366,33 @@ namespace etl
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
T* allocate(const T& initial)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, T*>::type
allocate(const T& initial)
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
#else
ETL_ASSERT(items_allocated < MAX_SIZE, ETL_ERROR(pool_no_allocation));
#endif
T* result = &p_buffer[next_free];
*result = initial;
in_use_flags.set(next_free);
next_free = in_use_flags.find_first(false);
++items_allocated;
return result;
}
//*************************************************************************
/// Allocate an object from the pool from an ititial value.
/// If asserts or exceptions are enabled and there are no more free items an
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, T*>::type
allocate(const T& initial)
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
@ -372,7 +424,36 @@ namespace etl
/// pool then an etl::pool_object_not_in_pool is thrown.
/// \param p_object A pointer to the object to be released.
//*************************************************************************
void release(const T* const p_object)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
release(const T* const p_object)
{
// Does it belong to me?
ETL_ASSERT(is_in_pool(p_object), ETL_ERROR(pool_object_not_in_pool));
// Where is it in the buffer?
typename std::iterator_traits<T*>::difference_type distance = p_object - p_buffer;
size_t index = static_cast<size_t>(distance);
// Check that it hasn't already been released.
if (in_use_flags.test(index))
{
// Destroy the object and mark as available.
in_use_flags.reset(index);
--items_allocated;
next_free = index;
}
}
//*************************************************************************
/// Release an object in the pool.
/// If asserts or exceptions are enabled and the object does not belong to this
/// pool then an etl::pool_object_not_in_pool is thrown.
/// \param p_object A pointer to the object to be released.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
release(const T* const p_object)
{
// Does it belong to me?
ETL_ASSERT(is_in_pool(p_object), ETL_ERROR(pool_object_not_in_pool));

View File

@ -112,7 +112,27 @@ namespace etl
/// otherwise does nothing if full.
///\param value The value to push to the queue.
//*************************************************************************
void push(parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
push(parameter_t value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
p_buffer[in] = value;
in = (in == (MAX_SIZE - 1)) ? 0 : in + 1;
++current_size;
}
//*************************************************************************
/// Adds a value to the queue.
/// If asserts or exceptions are enabled, throws an etl::queue_full is the queue is already full,
/// otherwise does nothing if full.
///\param value The value to push to the queue.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
push(parameter_t value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
@ -130,7 +150,32 @@ namespace etl
/// otherwise does nothing if full.
/// \return A reference to the position to 'push' to.
//*************************************************************************
reference push()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, reference>::type
push()
{
const size_type next = in;
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
in = (in == (MAX_SIZE - 1)) ? 0 : in + 1;
++current_size;
return p_buffer[next];
}
//*************************************************************************
/// Allows a possibly more efficient 'push' by moving to the next input value
/// and returning a reference to it.
/// This may eliminate a copy by allowing direct construction in-place.<br>
/// If asserts or exceptions are enabled, throws an etl::queue_full is the queue is already full,
/// otherwise does nothing if full.
/// \return A reference to the position to 'push' to.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, reference>::type
push()
{
const size_type next = in;
@ -147,7 +192,26 @@ namespace etl
//*************************************************************************
/// Clears the queue to the empty state.
//*************************************************************************
void clear()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
clear()
{
while (current_size > 0)
{
out = (out == (MAX_SIZE - 1)) ? 0 : out + 1;
--current_size;
}
in = 0;
out = 0;
}
//*************************************************************************
/// Clears the queue to the empty state.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
clear()
{
while (current_size > 0)
{
@ -164,7 +228,24 @@ namespace etl
/// Removes the oldest value from the back of the queue.
/// Does nothing if the queue is already empty.
//*************************************************************************
void pop()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(queue_empty));
#endif
out = (out == (MAX_SIZE - 1)) ? 0 : out + 1;
--current_size;
}
//*************************************************************************
/// Removes the oldest value from the back of the queue.
/// Does nothing if the queue is already empty.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(queue_empty));

View File

@ -84,7 +84,25 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::stack_full is the stack is already full.
///\param value The value to push to the stack.
//*************************************************************************
void push(parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
push(parameter_t value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
top_index = current_size++;
p_buffer[top_index] = value;
}
//*************************************************************************
/// Adds a value to the stack.
/// If asserts or exceptions are enabled, throws an etl::stack_full is the stack is already full.
///\param value The value to push to the stack.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
push(parameter_t value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
@ -100,7 +118,28 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::stack_full is the stack is already full.
/// \return A reference to the position to 'push' to.
//*************************************************************************
reference push()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, reference>::type
push()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
top_index = current_size++;
return p_buffer[top_index];
}
//*************************************************************************
/// Allows a possibly more efficient 'push' by moving to the next input value
/// and returning a reference to it.
/// This may eliminate a copy by allowing direct construction in-place.<br>
/// If asserts or exceptions are enabled, throws an etl::stack_full is the stack is already full.
/// \return A reference to the position to 'push' to.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, reference>::type
push()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
@ -123,7 +162,23 @@ namespace etl
//*************************************************************************
/// Clears the stack to the empty state.
//*************************************************************************
void clear()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
clear()
{
while (current_size > 0)
{
--top_index;
--current_size;
}
}
//*************************************************************************
/// Clears the stack to the empty state.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
clear()
{
while (current_size > 0)
{
@ -137,7 +192,24 @@ namespace etl
/// Removes the oldest item from the top of the stack.
/// Does nothing if the stack is already empty.
//*************************************************************************
void pop()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(stack_empty));
#endif
--top_index;
--current_size;
}
//*************************************************************************
/// Removes the oldest item from the top of the stack.
/// Does nothing if the stack is already empty.
//*************************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(stack_empty));

View File

@ -439,13 +439,16 @@ namespace etl
{
ETL_ASSERT((current_size)+1 <= MAX_SIZE, ETL_ERROR(vector_full));
create_element(value);
if (position != end())
{
create_element();
std::copy_backward(position, end() - 1, end());
*position = value;
}
else
{
create_element(value);
}
return position;
}
@ -647,7 +650,19 @@ namespace etl
//*********************************************************************
/// Create a new element with a default value at the back.
//*********************************************************************
void create_element()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element()
{
current_size++;
}
//*********************************************************************
/// Create a new element with a default value at the back.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element()
{
new(&p_buffer[current_size++]) T();
}
@ -655,7 +670,19 @@ namespace etl
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
void create_element(parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element(parameter_t value)
{
p_buffer[current_size++] = value;
}
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element(parameter_t value)
{
new(&p_buffer[current_size++]) T(value);
}
@ -663,7 +690,19 @@ namespace etl
//*********************************************************************
/// Create a new element with a value at the index
//*********************************************************************
void create_element_at(size_t index, parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
create_element_at(size_t index, parameter_t value)
{
p_buffer[index] = value;
}
//*********************************************************************
/// Create a new element with a value at the index
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
create_element_at(size_t index, parameter_t value)
{
new(&p_buffer[index]) T(value);
}
@ -671,9 +710,21 @@ namespace etl
//*********************************************************************
/// Destroy an element at the back.
//*********************************************************************
void destroy_element()
template <typename U = T>
typename etl::enable_if<etl::is_fundamental<U>::value, void>::type
destroy_element()
{
p_buffer[--current_size].~T();
--current_size;
}
//*********************************************************************
/// Destroy an element at the back.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::is_fundamental<U>::value, void>::type
destroy_element()
{
p_buffer[--current_size].~U();
}
// Disable copy construction.
@ -731,7 +782,7 @@ namespace etl
template <typename T>
bool operator >(const etl::ivector<T>& lhs, const etl::ivector<T>& rhs)
{
return operator <(rhs, lhs);
return (rhs < lhs);
}
//***************************************************************************
@ -744,7 +795,7 @@ namespace etl
template <typename T>
bool operator <=(const etl::ivector<T>& lhs, const etl::ivector<T>& rhs)
{
return !operator >(lhs, rhs);
return !(lhs > rhs);
}
//***************************************************************************
@ -757,7 +808,7 @@ namespace etl
template <typename T>
bool operator >=(const etl::ivector<T>& lhs, const etl::ivector<T>& rhs)
{
return !operator <(lhs, rhs);
return !(lhs < rhs);
}
}