|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef TCG_POOL_H
|
|
Toshihiro Shimizu |
890ddd |
#define TCG_POOL_H
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// STD includes
|
|
Toshihiro Shimizu |
890ddd |
#include "assert.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <vector></vector>
|
|
Toshihiro Shimizu |
890ddd |
#include <algorithm></algorithm>
|
|
Toshihiro Shimizu |
890ddd |
#include <functional></functional>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Discriminate rvalues support - either use Boost's config.hpp for automatic lookup,
|
|
Toshihiro Shimizu |
890ddd |
// or deal with it manually
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef TCG_RVALUES_SUPPORT
|
|
Toshihiro Shimizu |
890ddd |
#include <boost config.hpp=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef BOOST_NO_RVALUE_REFERENCES
|
|
Toshihiro Shimizu |
890ddd |
#define TCG_RVALUES_SUPPORT 0
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define TCG_RVALUES_SUPPORT 1
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\file pool.h
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\brief This file contains an implementation of the \a pool container concept.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\details A pool is a container that supports two fundamental operations, acquire() and
|
|
Toshihiro Shimizu |
890ddd |
release(), whose purpose is that of marking access operations to a resource
|
|
Toshihiro Shimizu |
890ddd |
that should not be destroyed when the access operation ends.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Creation and destruction of resources can be a time-consuming task that could
|
|
Toshihiro Shimizu |
890ddd |
be avoided when it is known that resources could be reused - which is the very
|
|
Toshihiro Shimizu |
890ddd |
reason why caching can be a useful approach to some problems.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The classical cache concept is nothing more than that of a standard associative
|
|
Toshihiro Shimizu |
890ddd |
map, tweaked to accomodate specific commodities - such as managing the cache
|
|
Toshihiro Shimizu |
890ddd |
size.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
However, sometimes resources could be considered to be effectively indentical,
|
|
Toshihiro Shimizu |
890ddd |
to the point that assigning a key is merely a way to keep the objects
|
|
Toshihiro Shimizu |
890ddd |
distinct in the cache. Users are in the condition to require only two functions,
|
|
Toshihiro Shimizu |
890ddd |
one to acquire() a resource, the other to release() it.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The Pool concept we are introducing satisfies the following ruleset:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The pool is a dynamical container which allocates resources by invoking the
|
|
Toshihiro Shimizu |
890ddd |
objects' default constructor.
|
|
Toshihiro Shimizu |
890ddd |
Objects in the pool are \b not destructed, except when the pool is explicitly
|
|
Toshihiro Shimizu |
890ddd |
\a squeezed by the user.
|
|
Toshihiro Shimizu |
890ddd |
Keys are indices, returned by the pool with an incremental ordering.
|
|
Toshihiro Shimizu |
890ddd |
An object which has been acquired cannot be acquired again until it has been
|
|
Toshihiro Shimizu |
890ddd |
released
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace tcg
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// TCG Indices Pool class
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename cont="std::vector<T" t="size_t," typename="">></typename>
|
|
Toshihiro Shimizu |
890ddd |
class indices_pool
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef T value_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef Cont container_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
T m_start; //!< First index to be acquired
|
|
Toshihiro Shimizu |
890ddd |
T m_size; //!< Current indices count
|
|
Toshihiro Shimizu |
890ddd |
Cont m_releasedIndices; //!< Priority queue of released indices
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
indices_pool(value_type start = 0) : m_start(start), m_size(0) {}
|
|
Toshihiro Shimizu |
890ddd |
~indices_pool() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename iter=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
indices_pool(value_type size, iter releasedBegin, iter releasedEnd, value_type start = 0)
|
|
Toshihiro Shimizu |
890ddd |
: m_start(start), m_size(size), m_releasedIndices(releasedBegin, releasedEnd)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::make_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>());</t>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename iter=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
indices_pool(iter acquiredBegin, iter acquiredEnd, value_type start = 0)
|
|
Toshihiro Shimizu |
890ddd |
: m_start(start)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (acquiredBegin == acquiredEnd)
|
|
Toshihiro Shimizu |
890ddd |
m_size = 0;
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
// Sort the acquired indices
|
|
Toshihiro Shimizu |
890ddd |
std::vector<t> acquired(acquiredBegin, acquiredEnd);</t>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::sort(acquired.begin(), acquired.end());
|
|
Toshihiro Shimizu |
890ddd |
assert(acquired.front() >= m_start);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Scan them, adding holes in the acquired sequence to released indices
|
|
Toshihiro Shimizu |
890ddd |
m_size = acquired.back() - m_start + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_size >= (T)acquired.size());
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.reserve(m_size - acquired.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
T curIdx = m_start;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typename std::vector<t>::iterator at, aEnd(acquired.end());</t>
|
|
Toshihiro Shimizu |
890ddd |
for (at = acquired.begin(); at != aEnd; ++at, ++curIdx)
|
|
Toshihiro Shimizu |
890ddd |
for (; curIdx != *at; ++curIdx)
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.push_back(curIdx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::make_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>());</t>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type size() const { return m_size; }
|
|
Toshihiro Shimizu |
890ddd |
value_type releasedSize() const { return m_releasedIndices.size(); }
|
|
Toshihiro Shimizu |
890ddd |
value_type acquiredSize() const { return size() - releasedSize(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const container_type &releasedIndices() const { return m_releasedIndices; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type acquire()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_releasedIndices.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
value_type idx = m_releasedIndices.front();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pop_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>());</t>
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.pop_back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return idx;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return m_start + m_size++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void release(value_type idx)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.push_back(idx);
|
|
Toshihiro Shimizu |
890ddd |
push_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>());</t>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void clear()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_size = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Removes pool entries whose index is beyond that of the last acquired one.
|
|
Toshihiro Shimizu |
890ddd |
void squeeze()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_releasedIndices.empty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::sort_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>()); // O(n logn)</t>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Decrease the pool size as long as the back items are unused
|
|
Toshihiro Shimizu |
890ddd |
T lastIndex = m_start + m_size - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typename Cont::iterator ut, uEnd(m_releasedIndices.end());
|
|
Toshihiro Shimizu |
890ddd |
for (ut = m_releasedIndices.begin(); ut != uEnd && *ut == lastIndex; ++ut)
|
|
Toshihiro Shimizu |
890ddd |
--lastIndex, --m_size;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (ut != m_releasedIndices.begin())
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices.swap(Cont(ut, uEnd));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::make_heap(m_releasedIndices.begin(), m_releasedIndices.end(), std::greater<t>()); // O(n)</t>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#if (TCG_RVALUES_SUPPORT > 0)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
indices_pool(const indices_pool &other)
|
|
Toshihiro Shimizu |
890ddd |
: m_start(other.m_start), m_size(other.m_size), m_releasedIndices(other.m_releasedIndices)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
indices_pool &operator=(const indices_pool &other)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_start = other.m_start, m_size = other.m_size, m_releasedIndices = other.m_releasedIndices;
|
|
Toshihiro Shimizu |
890ddd |
return *this;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
indices_pool(indices_pool &&other)
|
|
Toshihiro Shimizu |
890ddd |
: m_start(other.m_start), m_size(other.m_size), m_releasedIndices(std::forward<container_type &&="">(other.m_releasedIndices)) {}</container_type>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
indices_pool &operator=(indices_pool &&other)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_start = other.m_start, m_size = other.m_size;
|
|
Toshihiro Shimizu |
890ddd |
m_releasedIndices = std::forward<container_type &&="">(other.m_releasedIndices);</container_type>
|
|
Toshihiro Shimizu |
890ddd |
return *this;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename cont="std::vector<T" t,="" typename="">></typename>
|
|
Toshihiro Shimizu |
890ddd |
class pool
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef T value_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef Cont container_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef size_t size_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
Cont m_objects; //!< Objects in the pool
|
|
Toshihiro Shimizu |
890ddd |
tcg::indices_pool<size_t> m_indices; //!< Indices Pool representing m_objects</size_t>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
pool() {}
|
|
Toshihiro Shimizu |
890ddd |
~pool() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const tcg::indices_pool<size_t> &indices() const { return m_indices; }</size_t>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
size_type size() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_indices.size() <= m_objects.size());
|
|
Toshihiro Shimizu |
890ddd |
return m_objects.size();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
size_type releasedSize() const { return m_objects.size() - m_indices.acquiredSize(); }
|
|
Toshihiro Shimizu |
890ddd |
size_type acquiredSize() const { return m_indices.acquiredSize(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const value_type &operator[](size_type idx) const { return m_objects[idx]; }
|
|
Toshihiro Shimizu |
890ddd |
value_type &operator[](size_type idx) { return m_objects[idx]; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
size_type acquire()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
size_t result = m_indices.acquire();
|
|
Toshihiro Shimizu |
890ddd |
if (result >= m_objects.size()) {
|
|
Toshihiro Shimizu |
890ddd |
assert(result == m_objects.size());
|
|
Toshihiro Shimizu |
890ddd |
m_objects.push_back(T());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return result;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void release(size_type idx) { m_indices.release(idx); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void releaseAll() { m_indices.clear(); }
|
|
Toshihiro Shimizu |
890ddd |
void clear()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
releaseAll();
|
|
Toshihiro Shimizu |
890ddd |
m_objects.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Removes pool entries whose index is beyond that of the last acquired one.
|
|
Toshihiro Shimizu |
890ddd |
void squeeze()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_indices.squeeze();
|
|
Toshihiro Shimizu |
890ddd |
m_objects.resize(m_indices.size());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace tcg
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif // TCG_POOL_H
|