1

I'm making a small game engine and need to have a memory pool associated with it. My question is, how do I actually share that memory to users who got their own classes?

For example, I have a user who got this class in his game;

class Monkey : public GameObject {
public:
    Monkey();
    ~Monkey();

    void Eat();
    void Sleep();

    unsigned long size();

private:
    int health;
};

I got a baseclass which, at the moment, just returns the size of the derived class. I figured this would be needed to know how much space this would occupy in the pool.

public GameObject {
public:
    virtual unsigned long size()=0;
};

And he wants to allocate a new instance of this class in my memory pool. I do not know the class definition at compile time,so I just can't figure out how the actual method call would look like. He cannot pass me an object inheriting from GameObject, because that means he already has allocated it, which defeats the purpose of pre-allocated memory pool. So how does the reserving of memory actually work for any arbitary class instance?

Sorry if its unclear

7
  • 1
    First, this belongs over on gamedev.se. Second, why do you need to have user-derived objects allocated in a memory pool? Commented Dec 25, 2011 at 0:04
  • Memory pools allocate fixed-size blocks, I don't get why you need the size, as it's constant. Commented Dec 25, 2011 at 0:06
  • Not necessarily game-related though, more general on memory-pools, game engine is an example. The reason to have the allocate the users objects in a memory pool, as I imagine, is so avoid having to allocate it on the heap which would take time to allocate/deallocate, no? In real-time apps a memory pool with fast allocation sounds good Commented Dec 25, 2011 at 0:08
  • The memory pool is a fixed size, but the objects that are to be fitted in the pool should be able to vary in size, otherwise I can only allocate one type of object in the pool right? Commented Dec 25, 2011 at 0:09
  • @KaiserJohaan: "sounds good"? You don't do something like this because it "sounds good". You do it because you have a known performance problem (either from profiling or experience), and memory pools will fix it. Otherwise, it's just a premature optimization. Commented Dec 25, 2011 at 0:14

4 Answers 4

4

Memory pools only allow allocations of a fixed size. Therefore, if you're trying to allocate variable size objects with one, then the fixed size of the allocation is the maximum size you can allocate.

If you want to overload the allocation behavior, you need to overload operator new/delete on your base class. It should throw std::bad_alloc if the user attempts to allocate a type beyond the max size of the memory pool. Also, you should overload operator new[]/delete[] to just throw std::bad_alloc, since allocating arrays of these will probably not be a good idea.

The overloaded operator new/delete will be given the proper size of the type it is allocating. All derived classes will inherit the overloaded operators... unless the user overrides it. And if they do... smack them.

The overloading itself is simple:

public GameObject {
public:
    void *operator new(size_t size);
    void operator delete(void *memory);
};

You will implement those by calling your pool to fetch a block of memory, or to deallocate the block of memory.

Sign up to request clarification or add additional context in comments.

Comments

1

Your memory pool will provide an API for allocating memory and you'll either implement operator new static member functions that use your pool for the base class, or make clients use placement new to construct any objects they want in memory allocated in your pool.

In the first case allocation and destruction will be exactly as normal, because the standard new operator and delete operator will end up calling your custom operator new and operator delete. So it should be completely transparent to your clients. However only objects in that inheritance heirarchy will be able to be allocated in your pool.

The second method will be slightly different because it will require the participation of clients. Either they have to allocate/free memory and construct/destroy objects manually (which is difficult and unsafe), or they'll use smart pointers with a custom deleter that destroys the object and frees the memory. With this method the client can put anything they want in your pool, including types that don't inherit from anything, such a large array of doubles.

Comments

0

Have your pool act like malloc. Construct the objects outside of the pool using placement new:

object1* x = new (alloc()) object1();
object2* y = new (alloc()) object2();

x->~object1(); free(x);
y->~object2(); free(y);

// this can (and should) be wrapped in functions, such as operator new/delete

There are much better ways to do this, but this will work with the pool not knowing the declaration of your classes.

2 Comments

Note that if object1 or object2 are too large for the pool, this will cause all manor of badness.
@NicolBolas Added the parens. And yeah, client should make sure the objects are small enough.
0

KaiserJohann, what you seem to be specifying is a system that allows dynamic allocation for variable sized elements. That is pretty much a request for a dynamic allocator.

Here is my article on Dynamic/Pool Hybrid Allocation, which should help you with your situation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.