Jump to content
  • Advertisement
Sign in to follow this  
King_DuckZ

Memory pool and overloaded new

This topic is 4136 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello guys. I'm writing my own memory allocator, but I need to ask something before going on. Here's the problem: when allocating objects, the allocator will return a raw block of memory with no regard to constructors (classic issue :/ ). I don't want to overload global new and dele, so here's what I came up with:
class CPoolBase;

class CPoolClient {
public:
	CPoolClient ( void ) : m_lppooMemPool(0) { return; };

	void* operator new ( size_t szSize, CPoolBase* lppooAllocator );
	void* operator new[] ( size_t szSize, CPoolBase* lppooAllocator );

	void operator delete ( void* lpBuff );
	void operator delete[] ( void* lpBuff );

private:
	static void* m_New ( size_t szSize, CPoolBase* lppooAllocator );
	static void m_Delete ( void* lpBuff );

	CPoolBase* m_lppooMemPool;
};


CPoolBase is obviously the memory pool. Ideally, each future class that will need "managed" allocations will derive from CPoolClient, inheriting new/dele and other common methods (here CPoolClient is a WiP). Of course, neither new nor delete can access m_lppooMemPool (not that I tried to :p), and that's the problem: when calling delete, it will have no idea about where to release the memory chunk. I see some people likes to use an overloaded delete that accepts the allocator as an extra argument (I don't know if that's correct, tbh), but I'd like to limit allocator-related code to the "new" statement. If that's the only solution, I'll stick to a global std::map :/

Share this post


Link to post
Share on other sites
Advertisement
Ok, I forgot to mention that :p
CPoolBase is an abstract base class, and I don't know whether the implementations will really free memory or just do nothing.
For example, I might derive an allocator that only allocates fixed size blocks. Here deallocation will be necessary so that I can mark blocks as unused.
Or I might get crazy and re-write the actual malloc behaviour, or .. or .. etc...

So, skipping delete might be no harm, but in many cases calling it would be better.

Share this post


Link to post
Share on other sites
Quote:

Original post by King_DuckZ
neither new nor delete can access m_lppooMemPool (not that I tried to :p), and that's the problem


Why not make m_lppooMemPool static? that way new and delete will have access to it, but note that if you want each class inheriting from this to have a seperate memory pool, you'll need to make this a template class (do a search for The curiously Recurring Template Pattern).

Quote:

when allocating objects, the allocator will return a raw block of memory with no regard to constructors


Actually, operator new should return a constructed object, not just a chunk of memory. You should remove the second argument and use placement new instead.

Share this post


Link to post
Share on other sites
Quote:
Why not make m_lppooMemPool static? that way new and delete will have access to it, but note that if you want each class inheriting from this to have a seperate memory pool, you'll need to make this a template class (do a search for The curiously Recurring Template Pattern).

Pretty interesting, first time I see such a construct, also. Thanks, I guess I'll spend some time working on your input o.O

Quote:

Actually, operator new should return a constructed object, not just a chunk of memory. You should remove the second argument and use placement new instead.

Yeah, my bad, I was speaking of the simple CPoolBase::Alloc() method. Placement new just won't do here, as CPoolBase implementations might be doing anything inside - like rollbacks, or the fixed size allocations example - thus it needs to know how much of the buffer is being used at a given instant and, eventually, must be able to take action when a block is freed.

Well well, I guess I have something to work on now, thanks a lot everyone :)

One last question (I hope I'm not going OT): memory alignment. Should I align everything on a 32-bit boundary? Or should I keep the 8 byte alignment as for the struct padding in the compiler options? Target machines are 32-bit x86.

Share this post


Link to post
Share on other sites
Quote:

Placement new just won't do here, as CPoolBase implementations might be doing anything inside - like rollbacks, or the fixed size allocations example - thus it needs to know how much of the buffer is being used at a given instant and, eventually, must be able to take action when a block is freed.


But if you have a static instance of CPoolBase inside your class, what's stoping you from using it to store the information you need to do what you describe (or perform the actions you describe)? I don't see how using placement new will restrict you in any way.

Share this post


Link to post
Share on other sites
I think I'll just drop any reference to the CPoolBase object in the CPoolClient class, and manually store that reference as an extra chunk after the newly allocated block. This way, I will also be sure that both ctor and dtor won't mess with my pointer :) I must evaluate risks, but I guess it's definitely a better solution than the stl map I originally planned.
Uh, I realize it's weird, but I got the idea while reading the "curiously recurring template" definition, so thanks ^^

Share this post


Link to post
Share on other sites
I handle this by using templated create() functions with 0-10 overloaded arguments instead of new, also a destroy function rather than delete. You will likely find my allocator useful or at least interesting, basically I jam a bunch of pools with different sizes together in an array and use template metaprogramming to find the correct pool at compile time. The result is a pool based allocator that can be used as a generic allocator.

I also use a macro to actually call my create() function so the source file and line number gets automatically passed in for debug build leak tracking.

There's a bunch of optimisations other than just the metaprogramming of course, you can view the memory allocator header here, the cpp here and check out the whole lib via sourceforge svn sourceforge.net/projects/ldk. It's zlib licensed.

Hope you find it useful/interesting.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!