patterncppMinor
Super simple templated memory pool in C++
Viewed 0 times
templatedsimplesupermemorypool
Problem
I have a small program where I have a background thread that plays sound, so it needs to run really fast, but it also needs to do a small amount of memory management. I didn't want to use normal new and delete in a time critical area, so I threw this together, but set it up so I could reuse it elsewhere.
The intended usage is something like this:
Now when calling
template
class MemoryPool
{
public:
MemoryPool()
{
for (unsigned int i = 0; i int MemoryPool::myUnusedIndex = capacity-1;
template T MemoryPool::myMemory[capacity];
template T* MemoryPool::myUnusedMemory[capacity];The intended usage is something like this:
struct Sound : public ag::util::MemoryPool
{
// ...
};Now when calling
new Sound() I get one from my memory pool, which should be super fast. The only things that I can think of that could be improved are making operator new throw an exception when at capacity. I think I might be able to do away with typename T. The only reason it's needed is so that myMemory knows the size of its elements, but I feel like there's another solution here.Solution
This currently will not work.
As every-time you create an object derived from
This line:
Is also not good as you are actually initializing the objects. Thus, when you are calling
I suppose you could call the destructor inside the
You could do this:
But unfortunately this is not guaranteed to be correctly aligned.
If you dynamically allocate the memory then it will be fine. Use
As every-time you create an object derived from
MemoryPool you re-initialize the myUnusedMemory structure thus potentially messing up your management.struct Game : public ag::util::MemoryPool {};
int main()
{
Game* p1 = new Game;
Game* p2 = new Game;
delete p1;
delete p2;
// myUnusedMemory now set like this:
// myUnusedMemory[0] = &myMemory[1];
// myUnusedMemory[1] = &myMemory[0];
// Now when we create the next one it resets the array:
Game* p3 = new Game;
// myUnusedMemory now set like this: (because the constructor reset the array)
// myUnusedMemory[0] = &myMemory[0];
// myUnusedMemory[1] = &myMemory[1];
Game* p4 = new Game; // Now p3 and p4 point at the same memory location
}This line:
static T myMemory[capacity];Is also not good as you are actually initializing the objects. Thus, when you are calling
new your new operator is returning a pointer to an already initialized object . The constructor will then be re-called. Thus overriding the original content without the destructor being called (thus leaking any memory that should have been deleted).I suppose you could call the destructor inside the
new operator but that seems wasteful (and may be expensive) and sort of counter intuitive. So you want to use uninitialized memory for your pool.You could do this:
static char myMemory[capacity * sizeof(T)];But unfortunately this is not guaranteed to be correctly aligned.
If you dynamically allocate the memory then it will be fine. Use
std::vector and it will be dynamically allocated and safe.static std::vector myMemory(capacity * sizeof(T));Code Snippets
struct Game : public ag::util::MemoryPool<Game, 2> {};
int main()
{
Game* p1 = new Game;
Game* p2 = new Game;
delete p1;
delete p2;
// myUnusedMemory now set like this:
// myUnusedMemory[0] = &myMemory[1];
// myUnusedMemory[1] = &myMemory[0];
// Now when we create the next one it resets the array:
Game* p3 = new Game;
// myUnusedMemory now set like this: (because the constructor reset the array)
// myUnusedMemory[0] = &myMemory[0];
// myUnusedMemory[1] = &myMemory[1];
Game* p4 = new Game; // Now p3 and p4 point at the same memory location
}static T myMemory[capacity];static char myMemory[capacity * sizeof(T)];static std::vector<char> myMemory(capacity * sizeof(T));Context
StackExchange Code Review Q#7133, answer score: 8
Revisions (0)
No revisions yet.