HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Simple object pool template container in C++

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simpletemplatecontainerpoolobject

Problem

The main advantage of this pattern is when I often create and destroy objects, which in this case are often used.

I made this because I needed to track several short timers at the same time, but it can also be used for stuff like missiles or else.

#include 
#include 

#define itv(TYPE) std::vector::iterator

using namespace std;
template 
struct object_pool
{
    std::vector pool;
    std::queue avail;
    TYPE & operator[](const size_t & i) { return pool[i]; }
    void add(size_t & pos)
    {
        if(avail.empty()) // no reusable object
        { pool.push_back(TYPE()); pos = pool.size()-1; }
        else
        { pos = avail.back(); avail.pop(); }
    }
    void rem(size_t & a) { avail.push(a); }
    size_t size() { return pool.size(); }
};


What do you think ?

Solution

Don't do this:

using namespace std;


In anything other than a toy this will cause problems.

I don't like this:

#define itv(TYPE) std::vector::iterator


With C++11 this type if thing has been resolved by auto.

I would also define the iterator in terms of the object pool:

template 
struct object_pool
{
    typedef std::vector::iterator  iterator;


I would hide the fact that internally the object_pool uses a vector and queue. I would then add the obligatory functions to extract information:

template 
class object_pool
{
    std::vector pool;
    std::queue avail;

  public:
    typedef std::vector::iterator       iterator;
    typedef std::vector::const_iterator const_iterator;

    iterator       begin()       { return pool.begin();}
    iterator       end()         { return pool.end();}
    const_iterator begin() const { return pool.begin();}
    const_iterator end()   const { return pool.end();}


To access elements I would also provide const version

TYPE&       operator[](std::size_t index)       { return pool[index];}
    TYPE&       at(std::size_t index)               { return pool.at(index);}

    TYPE const& operator[](std::size_t index) const { return pool[index];}
    TYPE const& at(std::size_t index) const         { return pool.at(index);}


The methods that can be const should be const:

size_t size() const { return pool.size(); }
             //  ^^^^^^^


The implementation details are fine.

void add(size_t & pos)
    {
        if(avail.empty()) // no reusable object
        { pool.push_back(TYPE()); pos = pool.size()-1; }
        else
        { pos = avail.back(); avail.pop(); }
    }
    void rem(size_t & a) { avail.push(a); }


I would change the add() so it returned pos:

size_t add();


Also the vector starts off very small and re-sizes to get bigger.

To make sure that it does not re-size too often I would add a constructor that gives the vector a reasonable size to start with:

object_pool::object_pool()
{
    pool.reserve(1000);
}


But I think you are using the wrong technique.

I would use a pool allocator and plug it into the vector.

You can read more about it here: https://stackoverflow.com/q/2984434/14065

Code Snippets

using namespace std;
#define itv(TYPE) std::vector<TYPE>::iterator
template <class TYPE>
struct object_pool
{
    typedef std::vector<TYPE>::iterator  iterator;
template <class TYPE>
class object_pool
{
    std::vector<TYPE> pool;
    std::queue<size_t> avail;

  public:
    typedef std::vector<TYPE>::iterator       iterator;
    typedef std::vector<TYPE>::const_iterator const_iterator;

    iterator       begin()       { return pool.begin();}
    iterator       end()         { return pool.end();}
    const_iterator begin() const { return pool.begin();}
    const_iterator end()   const { return pool.end();}
TYPE&       operator[](std::size_t index)       { return pool[index];}
    TYPE&       at(std::size_t index)               { return pool.at(index);}

    TYPE const& operator[](std::size_t index) const { return pool[index];}
    TYPE const& at(std::size_t index) const         { return pool.at(index);}

Context

StackExchange Code Review Q#13979, answer score: 7

Revisions (0)

No revisions yet.