This document provides a brief description of the PPMalloc modules and
then provides some basic information on using these modules. You will
want to consult documentation for individual modules for more detailed
information about them.
PPMalloc Modules
| Module |
Description | Source |
Dependencies |
| GeneralAllocator |
Implements a general purpose allocator. | EAGeneralAllocator.h/cpp |
EABase |
| GeneralAllocatorDebug |
Implements a user-level debug layer on top of GeneralAllocator. Useful for doing named allocations, recording stack traces, doing delayed frees, etc. | EAGeneralAllocatorDebug.h/cpp EAGeneralAllocatorDebugPS2.cpp, EAGeneralAllocatorDebugWin32.cpp, etc. |
GeneralAllocator SystemAllocator |
| StackAllocator |
Implements a fast allocator that works by incrementing a pointer through a block of memory. | EAStackAllocator.h/cpp |
EABase |
| FixedAllocator |
Implements a pool of same-sized objects, for fast allocation and tight object packing and good similar-object locality. | EAFixedAllocator.h/cpp |
EABase |
| NonLocalAllocator |
Implements an allocator for memory that is inaccessable by the entity allocating it. | EANonLocalAllocator.h/cpp |
GeneralAllocator |
| SmallObjectAllocator |
Implements an allocator specialized for non-fragmenting small-sized blocks | EASmallObjectAllocator.h/cpp |
EABase |
| SmallBlockAllocator | Alternative to SmallObjectAllocator. | extras/EASmallObjectAllocator.h/cpp | EABase |
| ScratchpadAllocator | Implements a per-thread stack allocator for fast temporary per-thread memory. More flexible than alloca, similar to C99 dynamically sized automatic arrays but portable and more flexible. | ||
| HandleAllocator |
Implements a handle-based allocator with conventional lock semantics and heap compaction. Useful for preventing heap fragmentation problems. | EAHandleAllocator.h/cpp |
GeneralAllocator |
| SystemAllocator |
Implements an allocator which uses the underlying operating system or kernel libraries for memory allocation. Useful for implementing underneath custom allocators such as those here. | EASystemAllocator.h |
EABase |
| AllocationRecorder |
Implements an automated allocation activity recording and playback system for any generalized allocator, such as GeneralAllocator. Useful for doing offline testing of memory allocation patterns and behaviour. | EAAllocationRecorder.h/cpp |
EABase |
| AllocatorInterface |
Implements the EA IAllocator interface on top of GeneralAllocator. | EAAllocatorInterface.h/cpp |
GeneralAllocator GeneralAllocatorDebug |
| NewDelete |
Implements overrides for the C++ new and delete operators. |
EANewDelete/cpp | EABase |
| GeneralAllocatorSTL |
Defines a custom STL allocator which uses GeneralAllocator as the allocation source. |
EAGeneralAllocatorSTL.h | GeneralAllocator |
The Basics
Most likely, what you are primarily interested in is GeneralAllocator.
The other modules provide more esoteric functionality that you may want
to consider for advanced systems. Either way, GeneralAllocator stands
by itself has has no dependencies on the other modules; you can just
grab GeneralAllocator.h/cpp and throw the rest away if that suits your
needs.
All code is in C++ and largely follows the EA coding guidelines as of
January of 2004. All classes are in the EA::Allocator C++ namespace.
Thus, the fully qualified name of GeneralAllocator is
EA::Allocator::GeneralAllocator. Most of the code is plain C++ and
doesn't attempt to be very academic with the language. Thus RTTI is not
used, template usage is used only in one module (FixedAllocator),
exception handling is not used, etc. Unit tests have been set up for
most of the functionality and are available with the full package. The
headers are heavily commented in Doxygen-savvy format and the source
code for the primary modules has been heavily commented as well.
GeneralAllocator Examples
Here we provide some basic examples showing how to use GeneralAllocator.
#include "PPMalloc/EAGeneralAllocator.h" using namespace EA::Allocator; GeneralAllocator allocator; void* p = allocator.Malloc(20); allocator.Free(p);
To use GeneralAllocatorDebug, you simply substitute that class for GeneralAllocator, like this:
#include "PPMalloc/EAGeneralAllocatorDebug.h" using namespace EA::Allocator; GeneralAllocatorDebug allocator; void* p = allocator.Malloc(20); allocator.Free(p);
If you want to initialize the allocator with a large block of existing memory, you simply pass that memory into the constructor or Init function, like so:
GeneralAllocator allocator(pMemory, nMemorySize);
If you would like to use GeneralAllocatorDebug to allocate memory with a name attached to it, you would do this:
allocator.MallocDebug(20, 0, "model");
If you would like to use GeneralAllocatorDebug to allocate memory which tracks the full call stack and the allocation time along with a name, you would do this:
unsigned flags = (1 << GeneralAllocatorDebug::kDebugDataIdCallStack) ||
(1 << GeneralAllocatorDebug::kDebugDataIdAllocationTime);
allocator.MallocDebug(20, flags, "model");
If you would like to validate the heap to see if there has been any corruption, you would do this:
allocator.ValidateHeap(GeneralAllocator::kHeapValidationLevelFull);
If you would like to provide a C++ hook function to track all allocation activity, you would use SetHookFunction like this:
void SomeClass::SetupHook()
{
allocator.SetHookFunction(HookFunction, this);
}
static void HookFunction(const GeneralAllocator::HookInfo* pHI, void* pContext)
{
SomeClass* const pSomeClass = (SomeClass*)pContext; // Possibly use this.
if(!pHookInfo->mbEntry) // If we are being called at the end of the function (so we can see the result)...
{
if(pHookInfo->mHookType == GeneralAllocator::kHookTypeMalloc)
pHookInfo->mnSizeInputTotal, pHookInfo->mpDataOutput;
else if(pHookInfo->mHookType == GeneralAllocator::kHookTypeFree)
pHookInfo->mpDataInput;
}
}
If you would like to use GeneralAllocator as a sub heap of some other heap (e.g. another GeneralAllocator), you would simply do this:
GeneralAllocator gaParent;
GeneralAllocator gaChild(gParent.Malloc(1000000), 1000000, false);
If you want to have a sub heap that grows on demaind, you would do this:
size_t SubHeapCoreFreeFunction(GeneralAllocator* /*pChild*/, void* pCore, size_t nSize, void* pContext)
{
GeneralAllocator* const pParent = (GeneralAllocator*)pContext;
pParent->Free(pCore);
return nSize;
}
bool MallocFailureFunction(GeneralAllocator* pChild, size_t nSize, void* pContext)
{
GeneralAllocator* const pParent = (GeneralAllocator*)pContext;
if(nSize < 1000000) // Allocate at least N bytes of new core.
nSize = 1000000;
void* const pNewCore = pParent->Malloc(nSize);
if(pNewCore)
pChild->AddCore(pNewCore, nSize, true, false, SubHeapCoreFreeFunction, pParent);
return (pNewCore != NULL);
}
// Create a main heap.
GeneralAllocator gaParent;
// Create a sub heap from the main heap.
GeneralAllocator gaChild(gaParent.Malloc(1000000), 1000000, false, false, SubHeapCoreFreeFunction, &gaParent);
gaChild.SetMallocFailureFunction(MallocFailureFunction, &gaParent);
gaChild.SetOption(GeneralAllocator::kOptionEnableSystemAlloc, 0);