H
Hanzo
I'm currently fighting my way through an example of Single-Threaded
Memory Pooling in a chapter of the Efficient C++ book by Dov Bulka &
David Mayhew. Unfortuantely, I'm starting to get code that won't
compile and I am having a hard time finding an online errata or
contacting the authors.
For those familiar with the book, Chapter 6 covers rolling your own
memory manager. The first section, dealing with a Specialized Rational
Memory Manager (Rational is a custom class to handle fractions)
compiles fine, however the next sections fail. The first of these
sections is the Fixed-Size Object Memory Pool. The code, line for
line, reads at the end of this post.
My compile errors are with the lines referring to static_cast, saying
"Cannot convert from 'char *' to 'class MemoryPool<class Rational>*'.
I'd love to be able to figure this out, but sadly, that's why I'm
reading the book; I am not sure how this is failing. Any help would be
appreciated.
- Hanzo
=========
template<class T>
class MemoryPool
{
public:
MemoryPool(size_t size = EXPANSION_SIZE) {
expandTheFreeList(size); }
~MemoryPool();
// Allocate a T element from the free list
inline void *alloc(size_t size);
// Return a T element to the firee list
inline void free(void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next;
// if the freeList is empty, expand it by this amount
enum { EXPANSION_SIZE = 32 };
// add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
};
template<class T>
MemoryPool<T>::~MemoryPool()
{
MemoryPool<T> *nextPtr = next;
for (nextPtr = next; nextPtr != NULL; nextPtr = next)
{
next = next->next;
delete [] nextPtr;
}
}
template<class T>
inline void* MemoryPool<T>::alloc(size_t size)
{
if (!next)
expandTheFreeList();
MemoryPool<T> *head = next;
next = head->next;
return head;
}
template<class T>
inline void MemoryPool<T>::free(void *doomed)
{
MemoryPool<T> *head = static_cast<MemoryPool<T>*>(doomed);
head->next = next;
next = head;
}
template<class T>
void MemoryPool<T>::expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer
size_t size = (sizeof(T) > sizeof(MemoryPool<T>*)) ? sizeof(T)
: sizeof(MemoryPool<T>*);
MemoryPool<T> *runner = static_cast<MemoryPool<T>*>(new
char[size]);
next = runner;
for (int i=0; i<howMany; i++)
{
runner->next = static_cast<MemoryPool<T>*>(new
char[size]);
runner = runner->next;
}
runner->next = NULL;
}
// ===========================
class Rational {
public:
Rational(int a=0, int b=1) : n(a), d(b) {}
void *operator new(size_t size) { return memPool->alloc(size);
}
void operator delete(void *doomed, size_t size) {
memPool->free(doomed); }
static void newMemPool() { memPool = new MemoryPool<Rational>;
}
static void deleteMemPool() { delete memPool; }
private:
int n;
int d;
static MemoryPool<Rational> *memPool;
};
MemoryPool<Rational> *Rational::memPool = NULL;
int main()
{
Rational *array[1000];
Rational::newMemPool();
int start = timeGetTime();
for (int j=0; j<1; j++)
{
for (int i=0; i<1; i++)
{
array = new Rational(i);
}
for (i=0; i<1; i++)
{
delete array;
}
}
int end = timeGetTime();
Rational::deleteMemPool();
cout << "The time was " << end-start << endl;
return 0;
}
Memory Pooling in a chapter of the Efficient C++ book by Dov Bulka &
David Mayhew. Unfortuantely, I'm starting to get code that won't
compile and I am having a hard time finding an online errata or
contacting the authors.
For those familiar with the book, Chapter 6 covers rolling your own
memory manager. The first section, dealing with a Specialized Rational
Memory Manager (Rational is a custom class to handle fractions)
compiles fine, however the next sections fail. The first of these
sections is the Fixed-Size Object Memory Pool. The code, line for
line, reads at the end of this post.
My compile errors are with the lines referring to static_cast, saying
"Cannot convert from 'char *' to 'class MemoryPool<class Rational>*'.
I'd love to be able to figure this out, but sadly, that's why I'm
reading the book; I am not sure how this is failing. Any help would be
appreciated.
- Hanzo
=========
template<class T>
class MemoryPool
{
public:
MemoryPool(size_t size = EXPANSION_SIZE) {
expandTheFreeList(size); }
~MemoryPool();
// Allocate a T element from the free list
inline void *alloc(size_t size);
// Return a T element to the firee list
inline void free(void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next;
// if the freeList is empty, expand it by this amount
enum { EXPANSION_SIZE = 32 };
// add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
};
template<class T>
MemoryPool<T>::~MemoryPool()
{
MemoryPool<T> *nextPtr = next;
for (nextPtr = next; nextPtr != NULL; nextPtr = next)
{
next = next->next;
delete [] nextPtr;
}
}
template<class T>
inline void* MemoryPool<T>::alloc(size_t size)
{
if (!next)
expandTheFreeList();
MemoryPool<T> *head = next;
next = head->next;
return head;
}
template<class T>
inline void MemoryPool<T>::free(void *doomed)
{
MemoryPool<T> *head = static_cast<MemoryPool<T>*>(doomed);
head->next = next;
next = head;
}
template<class T>
void MemoryPool<T>::expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer
size_t size = (sizeof(T) > sizeof(MemoryPool<T>*)) ? sizeof(T)
: sizeof(MemoryPool<T>*);
MemoryPool<T> *runner = static_cast<MemoryPool<T>*>(new
char[size]);
next = runner;
for (int i=0; i<howMany; i++)
{
runner->next = static_cast<MemoryPool<T>*>(new
char[size]);
runner = runner->next;
}
runner->next = NULL;
}
// ===========================
class Rational {
public:
Rational(int a=0, int b=1) : n(a), d(b) {}
void *operator new(size_t size) { return memPool->alloc(size);
}
void operator delete(void *doomed, size_t size) {
memPool->free(doomed); }
static void newMemPool() { memPool = new MemoryPool<Rational>;
}
static void deleteMemPool() { delete memPool; }
private:
int n;
int d;
static MemoryPool<Rational> *memPool;
};
MemoryPool<Rational> *Rational::memPool = NULL;
int main()
{
Rational *array[1000];
Rational::newMemPool();
int start = timeGetTime();
for (int j=0; j<1; j++)
{
for (int i=0; i<1; i++)
{
array = new Rational(i);
}
for (i=0; i<1; i++)
{
delete array;
}
}
int end = timeGetTime();
Rational::deleteMemPool();
cout << "The time was " << end-start << endl;
return 0;
}