How to separate between internal and user memory allocation?

Started by
8 comments, last by ApochPiQ 12 years ago
Hello,

In my memory allocator manager, I have a bunch of allocate/deallocate templates like this:

#ifndef _I_MEMORY_MANAGER_H
#define _I_MEMORY_MANAGER_H
#include "EngineDefs.h"
namespace JonsEngine
{
class ILogManager;
class Allocator;
class IMemoryManager
{
public:
virtual ~IMemoryManager() { }
virtual bool Init(ILogManager* logger) = 0;
virtual bool Init(Allocator_BackEnd allocatorBackEnd, ILogManager* logger) = 0;
virtual bool Destroy() = 0;
virtual bool Start() = 0;
virtual bool Stop() = 0;
virtual bool isRunning() = 0;
virtual void Tick() = 0;
template <class T>
inline T* AllocateObject() { return new (Allocate(sizeof(T))) T(); }
template <class T, class arg0>
inline T* AllocateObject(arg0 a0) { return new (Allocate(sizeof(T))) T(a0); }
template <class T, class arg0, class arg1>
inline T* AllocateObject(arg0 a0, arg1 a1) { return new (Allocate(sizeof(T))) T(a0,a1); }
template <class T, class arg0, class arg1, class arg2>
inline T* AllocateObject(arg0 a0, arg1 a1, arg2 a2) { return new (Allocate(sizeof(T))) T(a0,a1,a2); }
template <class T>
inline void DeAllocateObject(T* obj)
{
obj->~T();
DeAllocate(obj);
}
virtual void* Allocate(size_t size) = 0;
virtual void* ReAllocate(void* p, size_t n) = 0;
virtual void DeAllocate(void* obj) = 0;
virtual Allocator* GetAllocator() = 0;

};
}
#endif


As you can see, you can either allocate/deallocate raw memory or use the allocate/deallocate templates.
However I also want to separate between engine-allocated memory and user-allcoated memorym, such as total bytes and objects allocated.I am not sure how to do it good way - the brute way is just to duplicate each allocate-method/template and add "interrnal" prefix or something, but it takes up space, looks ugly and shouldnt be part of interface.

How can I solve this in a good way?

EDIT: Added whole interface if it helps
Advertisement
Define an Enum called MemoryArena and put in an entry for each major category of memory you have - engine, user, whatever else sounds good.

Then pass an instance of this enum to each allocator, using a default argument value of "user" or "unspecified" or whatever else makes sense.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

So that means I have to have two Allocators?
Also, I want to go through my IMemoryManager interface (which the previous snippet is a part of - the actuall allocate/deallocate is passed to the engine allocator,a member of the memorymanager) - so I still have to solve not having duplicate methods.
(Adding a specific Enum parameter makes it hard in the templated function dosn't it, to distinguish from T, arg0, arg1, etc)
Wait... so you're using your allocator to pass the constructor parameters to each object as you create it? I must have missed that on the first read-through of the code, sorry.

That seems really awkward. Any particular reason you are doing it this way?



Anyways, I don't see any reason why you can't do what I originally suggested, just using a template parameter instead of a function parameter.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I thought it would be too cumbersome and ugly to do placement new and constructor/destructor call everywhere in the code. Is there a better way to do it?
Overload the new and delete operators, globally and/or for each class you want to control allocation for.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Is that recommended? For example, overriding it globally could possibly cause conflicts with other libraries, and you'd need a static memory allocator?
Doing it by class-by-class basis (and then with polymorphism) seems like alot of work.
That said the obvious downside to what I have now is the number of constructor arguments. Is there anything else that springs to mind?

Also - say if I would pass an enum to one of my templated functions above, how would it distinct that enum/flag for say arg0, if my function would look more like this:

template <class T, class arg0>
inline T* AllocateObject(arg0 a0, AllocatorMode mode = NULL) { return new (Allocate(sizeof(T)),mode) T(a0); }
It's a tradeoff, like most everything else.

For the memory mode argument - as I said, don't use a function parameter. Use a template parameter:

template <class T, AllocationMode mode, class argT0>
T* AllocateObject(const argT0& a0) { return new (Allocate(sizeof(T), mode)) T(a0); }

// Usage:
Foo* foo = allocator.Allocate<Foo, INTERNAL_MEMORY>(fooparam);
Bar* bar = allocator.Allocate<Bar, CLIENT_MEMORY>(barparam, bazparam);


You can also experiment with making the allocation mode parameter the last template parameter and making it default to something, although I'm not sure how various compilers would cope with that much template argument deduction going on (it should work in anything relatively modern though).

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Ok, gonna try it, thanks!

Also - is there a nice solution to include an unspecified amount of template function arguments, like variadic functions in C?
Since the problem I have is I feel restricted by the amount of arguments I can pass to my template functions, and I feel like passing a container of arguments is too much of a hassle.
C++11 has variadic templates, but you need a conformant compiler; I don't know offhand which compilers have full variadic template support at this point. Another option is Boost which has some macro magic for generating the templates automatically.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement