I'm having trouble getting some c++ templates to work. Here's what I want to do:
template <class T, const int I = 16, const int N = 65536, const int M = 2>
class pool
{
public:
pool();
~pool();
void clear();
T * get();
void put(void * p);
};
template<class T, const int I = 16, const int N = 65536, const int M = 2>
class pool_of_pools {
private:
static std::map<pthread_t, pool<T,I,N,M>*> pools;
public:
typedef typename std::map<pthread_t, pool<T,I,N,M>*>::iterator iterator_type;
static void registerThread(pthread_t id) {
if (pools.find(id) == pools.end())
pools[id] = new pool<T,I,N,M>();
}
static void registerThread() {
registerThread(pthread_self());
}
static void clear() {
for (iterator_type it = pools.begin(); it != pools.end(); ++it)
it->second->clear();
}
static pool<T,I,N,M>* getPool() {
if (pools.find(pthread_self()) == pools.end()) // <-- warning here
registerThread();
return pools[pthread_self()];
}
};
The idea is to have a pool of pools where the current thread always allocates from it's own pool but any thread can release the objects and they will go back to the correct pool. A pointer to their origin pool is stored within the object itself. When it runs, worker threads will allocate objects but a single collector thread will free them all when done.
Notice the static std::map
. When I try to instantiate that as:
template<typename T, int I, int N, int M> std::map<pthread_t, pool<T,I,N,M>*> pool_of_pools<T,I,N,M>::pools;
this gives me a warning of instantiation of variable 'pool_of_pools<int>::pools' required here, but no definition is available
. It compiles and runs, but when different threads call getPool
, they seem to register with their own thread-local(?) versions of pools
. I create a thread, then call registerThread(id)
with the thread id, and also registerThread()
to register the main thread. But when I call getPool
from the created thread, the address of pools
(&pools
) is different than what it was when I registered the two threads from the main thread. I'm not sure how that's possible since it's static and a global.
When I try to instantiate the map as:
template<> std::map<pthread_t, void*> pool_of_pools<int,512*1024,1024*1024,2>::pools;
it won't compile. I get a linker error undefined reference to pool_of_pools<int, 52488, 1048576, 2>::pools
I've done single templated classes before but never a templated class that has a static templated class instance in it.
How do I do this? Is it even possible?