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