I am a beginner and would like to build a pool. I made some research and found out that if my software has heavy object create and delete part, I should use a pool because of performance. I made some function to get a T from the pool and reset it, and would like to know if it works correctly. I tried my implementation, but it seems a bit slow. How can i improve this? The pool allocating Ts on the stack in an array, every in-use object has a stored pointer and the free() reset the objects through the pointers. I made a function for a full reset as well. I've found out that I should use a smart pointer, but first i would like to build a simple pool from my own. As a first improvement i would like to use a placement new for the vector to avoid the use of the heap.
#include <array>
#include <vector>
#include <algorithm>
#include <iostream>
//------------------------------------------------------------------------------
template<class T,int N>
class Pool
{
public:
Pool();
T* get();
void free(T* t);
void reset();
int available()const{ return N - used.size(); } // number of free Ts
private:
T default_T{}; // reset helper
std::array<T,N> allocated{};
std::vector<T*> used;
};
//------------------------------------------------------------------------------
template<class T, int N>
T* Pool<T,N>::get()
// get a T from the pool; return 0 if no free Ts
{
if(available()<1)
{
std::cerr << "Pool exhausted! Free memory!\n";
return 0;
}
T* t{nullptr};
for(unsigned int i=0; i<allocated.size(); ++i)
{
auto p = std::find(used.begin()+i,used.end(),&allocated[i]);
if(p==used.end())
{
t = &allocated[i];
used.push_back(t);
return t;
}
}
return t;
}
//------------------------------------------------------------------------------
template<class T,int N>
void Pool<T,N>::free(T* t)
// return a T given out by get() to the pool and reset it to default
{
auto p = std::find(used.begin(),used.end(),t);
if(*p==t)
{
*t = default_T;
used.erase(p);
}
}
//------------------------------------------------------------------------------
template<class T,int N>
void Pool<T,N>::reset()
// return ALL T given out by get() to the pool
{
for(auto& r: allocated)
free(&r);
}
Allocator
to allocate the raw memory used by the container. So you should implement anAllocator
that uses a "Pool" underneath. Then you can plug your allocator into the standard container types. \$\endgroup\$