[Tdg] some bugfixes to the memory pool / idle allocator classes
Graham Wakefield
lists at grahamwakefield.net
Wed Feb 21 16:23:21 PST 2007
#ifndef INC_GLV_MEM_POOL_H
#define INC_GLV_MEM_POOL_H
/* From Alex's MemPool class */
/* example:
// Note self-reference in template class definition
// this makes each object have its own pool.
class TypeWithOwnMemPool : public MemPool<TypeWithOwnMemPool>
{
private:
unsigned int blah;
};
// To share a single pool between many classes,
// inherit from a shared template class.
class SharedMemPoolType
{
private:
unsigned int blah;
unsigned int blah2;
};
class TypeWithSharedMemPool1 : public MemPool<SharedMemPoolType>
{
private:
unsigned int blah;
};
class TypeWithSharedMemPool2 : public MemPool<SharedMemPoolType>
{
private:
unsigned int blah;
unsigned int blah2;
};
int main()
{
TypeWithOwnMemPool::initMemPool(1);
TypeWithOwnMemPool * m1 = new TypeWithOwnMemPool;
TypeWithOwnMemPool * m2 = new TypeWithOwnMemPool;
delete m1;
delete m2;
TypeWithSharedMemPool1 * p1 = new TypeWithSharedMemPool1;
TypeWithSharedMemPool2 * p2 = new TypeWithSharedMemPool2;
delete p1;
delete p2;
}
*/
#include <pthread.h>
#include <queue>
#include <map>
#include <stack>
// comment out this line if you don't want to use doug lea's malloc:
#include "../dlmalloc/malloc-2.8.3.h"
#define GLV_MEM_IDLE_DEBUG
#define GLV_MEM_POOL_DEBUG
#ifdef MALLOC_280_H
#define glv_malloc dlmalloc
#define glv_free dlfree
#else
#define glv_malloc malloc
#define glv_free free
#endif
namespace glv {
template <class T>
class MemPool
{
public:
MemPool(){}
void * operator new(size_t num_bytes);
void operator delete (void *ptr, size_t bytes);
static void * pool_alloc(size_t num_bytes);
static void pool_free(void *ptr, size_t bytes);
unsigned int getMemPoolSize() { return cMemPool.size(); }
unsigned int getMemPoolItemSize() { return cMemPoolItemSize; }
static void initMemPool(unsigned int num_elements, size_t
num_bytes = sizeof(T));
static void setMemPoolItemSize(size_t num_bytes);
protected:
static std::stack<void *> cMemPool;
static unsigned int cMemPoolItemSize; // no. bytes
};
class MemIdle;
class MemIdleTask
{
friend class MemIdle;
public:
MemIdleTask(size_t size = 0);
MemIdleTask(void * ptr);
bool ready();
void * data();
protected:
bool flag;
void * memory;
size_t size;
};
class MemIdle
{
public:
static MemIdleTask * request(size_t num_bytes);
static bool allocate(MemIdleTask * m);
static MemIdleTask * free(void * ptr);
protected:
static void init();
static void * thread_alloc(void * arg);
static bool thread_initialized;
static std::queue<MemIdleTask *> Q;
};
template <class T>
unsigned int MemPool<T> :: cMemPoolItemSize = sizeof(T); // no.
bytes, e.g. sizeof(double) * 8
template <class T>
std::stack<void *> MemPool<T> :: cMemPool;
template <class T>
inline void * MemPool<T> :: operator new(size_t num_bytes)
{
void * item;
if(num_bytes > cMemPoolItemSize){
#ifdef GLV_MEM_POOL_DEBUG
printf("malloc new MemPool element (element too big)\n");
#endif
return glv_malloc(num_bytes);
} else if (cMemPool.empty()){
#ifdef GLV_MEM_POOL_DEBUG
printf("malloc new MemPool element (pool empty)\n");
#endif
return glv_malloc(cMemPoolItemSize);
} else {
#ifdef GLV_MEM_POOL_DEBUG
printf("dequeue new MemPool element\n");
#endif
item = cMemPool.top();
cMemPool.pop();
return item;
}
}
template <class T>
void * MemPool<T> :: pool_alloc(size_t num_bytes)
{
void * item;
if(num_bytes > cMemPoolItemSize){
#ifdef GLV_MEM_POOL_DEBUG
printf("malloc new MemPool element (element too big)\n");
#endif
return glv_malloc(num_bytes);
} else if (cMemPool.empty()){
#ifdef GLV_MEM_POOL_DEBUG
printf("malloc new MemPool element (pool empty)\n");
#endif
return glv_malloc(cMemPoolItemSize);
} else {
#ifdef GLV_MEM_POOL_DEBUG
printf("dequeue new MemPool element\n");
#endif
item = cMemPool.top();
cMemPool.pop();
return item;
}
}
template <class T>
inline void MemPool<T>::operator delete (void * ptr, size_t num_bytes)
{
if(num_bytes > cMemPoolItemSize){
#ifdef GLV_MEM_POOL_DEBUG
printf("MemPool free pointer\n");
#endif
glv_free(ptr);
} else {
#ifdef GLV_MEM_POOL_DEBUG
printf("MemPool return to queue\n");
#endif
cMemPool.push(ptr);
ptr = NULL;
}
}
template <class T>
void MemPool<T>::pool_free (void * ptr, size_t num_bytes)
{
if(num_bytes > cMemPoolItemSize){
#ifdef GLV_MEM_POOL_DEBUG
printf("MemPool free pointer\n");
#endif
glv_free(ptr);
} else {
#ifdef GLV_MEM_POOL_DEBUG
printf("MemPool return to queue\n");
#endif
cMemPool.push(ptr);
ptr = NULL;
}
}
template <class T>
void MemPool<T>::setMemPoolItemSize(size_t num_bytes)
{
if (num_bytes <= cMemPoolItemSize)
{
cMemPoolItemSize = num_bytes;
return;
}
cMemPoolItemSize = num_bytes;
// otherwise, empty pool:
while (!cMemPool.empty())
{
void * item = cMemPool.top();
cMemPool.pop();
glv_free(item);
}
}
template <class T>
void MemPool<T>::initMemPool(unsigned int num_elements, size_t
num_bytes)
{
#ifdef GLV_MEM_POOL_DEBUG
printf("MemPool pre allocate %i x %i = %.2fk\n", num_elements,
num_bytes, num_elements * num_bytes / 1024.0);
#endif
setMemPoolItemSize(num_bytes);
// fill up the pool:
while(cMemPool.size() < num_elements)
{
void * item = glv_malloc(cMemPoolItemSize);
cMemPool.push(item);
}
}
inline
MemIdleTask :: MemIdleTask(size_t size)
: size(size)
{
flag = false;
memory = NULL;
};
inline
MemIdleTask :: MemIdleTask(void * ptr)
: memory(ptr)
{
flag = false;
size = 0;
};
inline
bool MemIdleTask :: ready() { return flag; }
inline
void * MemIdleTask :: data() { return memory; }
bool MemIdle :: thread_initialized = false;
std::queue<MemIdleTask *> MemIdle :: Q;
MemIdleTask * MemIdle :: request(size_t num_bytes)
{
if (!thread_initialized) init();
MemIdleTask * m = new MemIdleTask(num_bytes);
Q.push(m);
return m;
}
MemIdleTask * MemIdle :: free(void * ptr)
{
MemIdleTask * m = new MemIdleTask(ptr);
Q.push(m);
return m;
}
void MemIdle :: init()
{
#ifdef GLV_MEM_IDLE_DEBUG
printf(">\t MemIdle thread: initialize\n");
#endif
thread_initialized = true;
// create a low priority pthread to allocate the memory:
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
// TODO: figure out how to set low priority
// sched_param schedparam;
// schedparam.sched_priority = 16; // is this a low enough priority?
// pthread_attr_setschedparam(&attr, &schedparam);
pthread_create(&thread, &attr, thread_alloc, 0);
}
void * MemIdle :: thread_alloc(void * arg)
{
while (thread_initialized)
{
sleep(1); // super lazy
if (!Q.empty())
{
MemIdleTask * m = Q.front();
printf(">\t MemIdle thread: %p %i %p\n", m, m->size, m->memory);
Q.pop();
if (m->size) {
m->memory = (void *)glv_malloc(m->size);
m->flag = true;
#ifdef GLV_MEM_IDLE_DEBUG
printf(">\t MemIdle thread: allocated %i bytes to %p at %p\n", m-
>size, m, m->memory);
#endif
} else {
#ifdef GLV_MEM_IDLE_DEBUG
printf(">\t MemIdle thread: free %p %p\n", m, m->memory);
#endif
glv_free(m->memory);
m->memory = NULL;
m->flag = true;
}
}
}
}
} // namespace
#endif
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.create.ucsb.edu/pipermail/tdg/attachments/20070221/c39f5976/attachment-0002.html
More information about the Tdg
mailing list