Skip to content

Commit

Permalink
Hoisted pool functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
jwellbelove committed Dec 10, 2014
1 parent 455377a commit e0e7d20
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 153 deletions.
101 changes: 76 additions & 25 deletions ipool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,104 @@ SOFTWARE.
#define __ETL_IPOOL__
#define __ETL_IN_IPOOL_H__

//*****************************************************************************
///\defgroup pool pool
/// A fixed capacity pool.
///\ingroup containers
//*****************************************************************************
#include "pool_base.h"
#include "nullptr.h"

#ifndef ETL_THROW_EXCEPTIONS
#include "error_handler.h"
#endif

namespace etl
{
//*************************************************************************
/// A templated pool implementation that uses a fixed size pool.
/// SIZE_ elements will be always be constructed.
///\ingroup pool
//*************************************************************************
template <typename T>
class ipool : public pool_base
{
private:

struct element
{
T* p_item;
};

public:

//*************************************************************************
/// Allocate an object from the pool.
/// 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)
if (next_free != MAX_SIZE)
{
T* result = &p_buffer[next_free];
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;
}
}

//*************************************************************************
/// Free 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.
//*************************************************************************
void release(const T& object)
{
release(&object);
}

//*************************************************************************
/// Free 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.
//*************************************************************************
void release(const T* const p_object)
{
// Does this object belong to this pool?
typename std::iterator_traits<T*>::difference_type distance = p_object - p_buffer;

// Not within the range of the buffer?
if ((distance < 0) || (distance >= static_cast<typename std::iterator_traits<T*>::difference_type>(MAX_SIZE)))
{
#ifdef ETL_THROW_EXCEPTIONS
throw pool_object_not_in_pool();
#else
error_handler::error(pool_object_not_in_pool());
#endif
}
else
{
// Mark the object as available.
next_free = static_cast<size_t>(distance);
in_use_flags.reset(next_free);
--items_allocated;
}
}

protected:

//*************************************************************************
/// Constructor
//*************************************************************************
ipool(T* p_buffer, size_t size)
: next_free(0),
p_buffer(p_buffer),
SIZE(size)

ipool(T* p_buffer, ibitset& in_use_flags, size_t size)
: pool_base(size),
p_buffer(nullptr),
in_use_flags(in_use_flags)
{
}

private:

size_t next_free;
T* p_buffer;
const size_t SIZE;
T* p_buffer;
ibitset& in_use_flags;
};
}
#endif
Expand Down
131 changes: 3 additions & 128 deletions pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SOFTWARE.
#define __ETL_POOL__

#include "bitset.h"
#include "nullptr.h"
#include "ipool.h"

#include <iterator>

Expand All @@ -42,54 +42,13 @@ SOFTWARE.

namespace etl
{
#ifdef ETL_THROW_EXCEPTIONS
//***************************************************************************
/// The base class for pool exceptions.
///\ingroup pool
//***************************************************************************
class pool_exception : public exception
{
public:

pool_exception(const char* what)
: exception(what)
{}
};

//***************************************************************************
/// The exception thrown when the pool has no more free items.
///\ingroup pool
//***************************************************************************
class pool_no_allocation : public pool_exception
{
public:

pool_no_allocation()
: pool_exception("pool: no allocation")
{}
};

//***************************************************************************
/// The exception thrown when an object is released which does not belong to the pool.
///\ingroup pool
//***************************************************************************
class pool_object_not_in_pool : public pool_exception
{
public:

pool_object_not_in_pool()
: pool_exception("pool: not in pool")
{}
};
#endif

//*************************************************************************
/// 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_>
class pool
class pool : public ipool<T>
{
public:

Expand All @@ -99,96 +58,12 @@ namespace etl
/// Constructor
//*************************************************************************
pool()
: next_free(0),
count(0)
{
}

//*************************************************************************
/// Allocate an object from the pool.
/// 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 != SIZE)
{
T* result = &buffer[next_free];
in_use.set(next_free);
next_free = in_use.find_first(false);
++count;
return result;
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw pool_no_allocation();
#else
return nullptr;
#endif
}
}

//*************************************************************************
/// Free 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 object A reference to the object to be released.
//*************************************************************************
void release(const T& object)
{
release(&object);
}

//*************************************************************************
/// Free 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.
//*************************************************************************
void release(const T* const p_object)
{
// Does this object belong to this pool?
typename std::iterator_traits<T*>::difference_type distance = p_object - buffer;

// Not within the range of the buffer?
if ((distance < 0) || (distance >= SIZE))
{
#ifdef ETL_THROW_EXCEPTIONS
throw pool_object_not_in_pool();
#endif
}
else
{
// Mark the object as available.
next_free = static_cast<size_t>(distance);
in_use.reset(next_free);
--count;
}
}

//*************************************************************************
/// Returns the number of free items in the pool.
//*************************************************************************
size_t available() const
{
return SIZE - in_use.count();
}

//*************************************************************************
/// 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
: ipool(buffer, in_use, SIZE)
{
return count == SIZE;
}

private:

size_t next_free; ///< The position of the next free item in the pool.
size_t count; ///< The number of objects allocated.
T buffer[SIZE]; ///< The pool of objects.
bitset<SIZE> in_use; ///< The set of flags that indicate which items are free in the pool.
};
Expand Down
Loading

0 comments on commit e0e7d20

Please sign in to comment.