mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Changed pool to use uninitialised buffer.
Changed pool to use uninitialised buffer instead of internal array. Allocates and releases using placement new and destructors.
This commit is contained in:
parent
293d3d4b54
commit
f349ca416d
222
ipool.h
222
ipool.h
@ -30,6 +30,8 @@ SOFTWARE.
|
||||
#define __ETL_IPOOL__
|
||||
#define __ETL_IN_IPOOL_H__
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "pool_base.h"
|
||||
#include "nullptr.h"
|
||||
|
||||
@ -39,25 +41,169 @@ SOFTWARE.
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//*************************************************************************
|
||||
//***************************************************************************
|
||||
///\ingroup pool
|
||||
//*************************************************************************
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
class ipool : public pool_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// const_iterator
|
||||
//*************************************************************************
|
||||
class const_iterator : public std::iterator<std::forward_iterator_tag, const T>
|
||||
{
|
||||
public:
|
||||
|
||||
friend class ipool;
|
||||
|
||||
//*******************************
|
||||
const_iterator()
|
||||
: index(0),
|
||||
p_buffer(p_buffer),
|
||||
p_in_use_flags(p_in_use_flags)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_iterator(const const_iterator& other)
|
||||
: index(other.index),
|
||||
p_buffer(p_buffer),
|
||||
p_in_use_flags(p_in_use_flags)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_iterator& operator ++()
|
||||
{
|
||||
index = p_in_use_flags->find_next(true, index + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_iterator operator ++(int)
|
||||
{
|
||||
const_iterator temp(*this);
|
||||
index = p_in_use_flags->find_next(true, index + 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_iterator operator =(const const_iterator& other)
|
||||
{
|
||||
index = other.index;
|
||||
p_buffer = other.p_buffer;
|
||||
p_in_use_flags = other.p_in_use_flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_reference operator *() const
|
||||
{
|
||||
return p_buffer[index];
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_pointer operator ->() const
|
||||
{
|
||||
return &p_buffer[index];
|
||||
}
|
||||
|
||||
//*******************************
|
||||
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
|
||||
{
|
||||
return (lhs.p_buffer == rhs.p_buffer) && (lhs.index == rhs.index);
|
||||
}
|
||||
|
||||
//*******************************
|
||||
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************
|
||||
const_iterator(const_pointer p_buffer,
|
||||
const ibitset* p_in_use_flags)
|
||||
: index(0),
|
||||
p_buffer(p_buffer),
|
||||
p_in_use_flags(p_in_use_flags)
|
||||
{
|
||||
index = p_in_use_flags->find_first(true);
|
||||
}
|
||||
|
||||
//*******************************
|
||||
const_iterator(size_t index,
|
||||
const_pointer p_buffer,
|
||||
const ibitset* p_in_use_flags)
|
||||
: index(index),
|
||||
p_buffer(p_buffer),
|
||||
p_in_use_flags(p_in_use_flags)
|
||||
{
|
||||
}
|
||||
|
||||
size_t index;
|
||||
const_pointer p_buffer;
|
||||
const ibitset* p_in_use_flags;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Get a const iterator to the first allocated item in the pool.
|
||||
//*************************************************************************
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(in_use_flags.find_first(true), p_buffer, &in_use_flags);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get a const iterator to the first allocated item in the pool.
|
||||
//*************************************************************************
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get a const iterator to the end of the pool.
|
||||
//*************************************************************************
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(in_use_flags.size(), p_buffer, &in_use_flags);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get a const iterator to the end of the pool.
|
||||
//*************************************************************************
|
||||
const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate an object from the pool.
|
||||
/// Uses the default constructor.
|
||||
/// If ETL_THROW_EXCEPTIONS is defined 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.
|
||||
//*************************************************************************
|
||||
T* allocate()
|
||||
{
|
||||
if (next_free != MAX_SIZE)
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
if (items_allocated < MAX_SIZE && !in_use_flags.test(next_free))
|
||||
#else
|
||||
if (items_allocated < MAX_SIZE)
|
||||
#endif
|
||||
{
|
||||
T* result = &p_buffer[next_free];
|
||||
T* result = new(&p_buffer[next_free]) T();
|
||||
in_use_flags.set(next_free);
|
||||
next_free = in_use_flags.find_first(false);
|
||||
++items_allocated;
|
||||
@ -75,7 +221,38 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Free an object in the pool.
|
||||
/// Allocate an object from the pool from an ititial value.
|
||||
/// If ETL_THROW_EXCEPTIONS is defined 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.
|
||||
//*************************************************************************
|
||||
T* allocate(const T& initial)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
if (items_allocated < MAX_SIZE && !in_use_flags.test(next_free))
|
||||
#else
|
||||
if (items_allocated < MAX_SIZE)
|
||||
#endif
|
||||
{
|
||||
T* result = new(&p_buffer[next_free]) T(initial);
|
||||
in_use_flags.set(next_free);
|
||||
next_free = in_use_flags.find_first(false);
|
||||
++items_allocated;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ETL_THROW_EXCEPTIONS
|
||||
throw pool_no_allocation();
|
||||
#else
|
||||
error_handler::error(pool_no_allocation());
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Release an object in the pool.
|
||||
/// If ETL_THROW_EXCEPTIONS is defined 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.
|
||||
@ -86,7 +263,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Free an object in the pool.
|
||||
/// Release an object in the pool.
|
||||
/// If ETL_THROW_EXCEPTIONS is defined 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.
|
||||
@ -96,12 +273,19 @@ namespace etl
|
||||
// Does it belong to me?
|
||||
if (is_in_pool(p_object))
|
||||
{
|
||||
// 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);
|
||||
|
||||
// Mark the object as available.
|
||||
next_free = static_cast<size_t>(distance);
|
||||
in_use_flags.reset(next_free);
|
||||
// Check that it hasn't already been released.
|
||||
if (in_use_flags.test(index))
|
||||
{
|
||||
// Destroy the object and mark as available.
|
||||
p_object->~T();
|
||||
in_use_flags.reset(index);
|
||||
--items_allocated;
|
||||
next_free = index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -113,6 +297,24 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Releases all objects in the pool.
|
||||
//*************************************************************************
|
||||
void release_all()
|
||||
{
|
||||
const_iterator i_object = begin();
|
||||
|
||||
while (i_object != end())
|
||||
{
|
||||
i_object->~T();
|
||||
++i_object;
|
||||
}
|
||||
|
||||
in_use_flags.reset();
|
||||
items_allocated = 0;
|
||||
next_free = 0;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Check to see if the object belongs to the pool.
|
||||
/// \param p_object A pointer to the object to be checked.
|
||||
@ -144,7 +346,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
ipool(T* p_buffer, ibitset& in_use_flags, size_t size)
|
||||
: pool_base(size),
|
||||
p_buffer(nullptr),
|
||||
p_buffer(p_buffer),
|
||||
in_use_flags(in_use_flags)
|
||||
{
|
||||
}
|
||||
|
||||
13
pool.h
13
pool.h
@ -29,6 +29,8 @@ SOFTWARE.
|
||||
#ifndef __ETL_POOL__
|
||||
#define __ETL_POOL__
|
||||
|
||||
#include "alignment.h"
|
||||
#include "array.h"
|
||||
#include "bitset.h"
|
||||
#include "ipool.h"
|
||||
|
||||
@ -44,7 +46,6 @@ namespace etl
|
||||
{
|
||||
//*************************************************************************
|
||||
/// A templated pool implementation that uses a fixed size pool.
|
||||
/// SIZE_ elements will be always be constructed.
|
||||
///\ingroup pool
|
||||
//*************************************************************************
|
||||
template <typename T, const size_t SIZE_>
|
||||
@ -58,15 +59,19 @@ namespace etl
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
pool()
|
||||
: ipool<T>(buffer, in_use, SIZE)
|
||||
: ipool<T>(reinterpret_cast<T*>(&aligned_buffer.value[0]), in_use, SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T buffer[SIZE]; ///< The pool of objects.
|
||||
bitset<SIZE> in_use; ///< The set of flags that indicate which items are free in the pool.
|
||||
///< The memory for the pool of objects.
|
||||
etl::align_as<etl::array<uint8_t, SIZE * sizeof(T)>, T> aligned_buffer;
|
||||
|
||||
///< The set of flags that indicate which items are free in the pool.
|
||||
bitset<SIZE> in_use;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ namespace etl
|
||||
/// Checks to see if there are no free items in the pool.
|
||||
/// \return <b>true</b> if there are none free (or 'empty')
|
||||
//*************************************************************************
|
||||
bool empty() const
|
||||
bool none_free() const
|
||||
{
|
||||
return items_allocated == MAX_SIZE;
|
||||
}
|
||||
@ -119,7 +119,7 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
size_t next_free; ///< The position of the next free item in the pool.
|
||||
size_t next_free; ///< The next free slot in the block.
|
||||
size_t items_allocated; ///< The number of items allocated.
|
||||
const size_t MAX_SIZE; ///< The maximum number of objects that can be allocated.
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user