NLMISC::CHeapAllocator Class Reference

#include <heap_allocator.h>


Small Block

enum  {
  SmallBlockGranularityShift = 3, SmallBlockGranularity = 1<<SmallBlockGranularityShift, FirstSmallBlock = 8, LastSmallBlock = 128,
  SmallBlockPoolSize = 20
}
bool checkNodeSB (const CSmallBlockPool *mainBlock, const CNodeBegin *previous, const CNodeBegin *current, const CNodeBegin *next, bool stopOnError) const
volatile CNodeBegin_FreeSmallBlocks [(1+(LastSmallBlock-FirstSmallBlock)/SmallBlockGranularity)]
CAllocatorMutex _MutexSB
volatile CSmallBlockPool_SmallBlockPool
CNodeBegingetNextSmallBlock (CNodeBegin *previous)
CNodeBegingetSmallBlock (CSmallBlockPool *smallBlock, uint blockIndex)
void setNextSmallBlock (CNodeBegin *previous, CNodeBegin *next)

Category control

void debugPopCategoryString ()
void debugPushCategoryString (const char *str)
CTDS _CategoryStack

Public Types

enum  {
  ReleaseHeaderSize = 8, CategoryStringLength = 8, BeginNodeMarkers = '<', EndNodeMarkers = '>',
  UnallocatedMemory = 0xba, UninitializedMemory = 0xbc, DeletedMemory = 0xbd, NameLength = 32
}
enum  TBlockAllocationMode { Grow, DontGrow }
typedef char TCategoryString [CategoryStringLength]
enum  TOutOfMemoryMode { ThrowException, ReturnNull }

Public Member Functions

void * allocate (uint size, const char *sourceFile, uint line, const char *category)
virtual uint8allocateBlock (uint size)
 CHeapAllocator (uint mainBlockSize=1024 *1024 *10, uint blockCount=1, TBlockAllocationMode blockAllocationMode=Grow, TOutOfMemoryMode outOfMemoryMode=ThrowException)
bool checkHeap (bool stopOnError) const
void debugAlwaysCheckMemory (bool alwaysCheck)
uint debugGetAllocatedMemoryByCategory (const char *category) const
uint debugGetDebugInfoSize () const
uint debugGetLBDebugInfoSize () const
uint debugGetSBDebugInfoSize () const
bool debugIsAlwaysCheckMemory (bool alwaysCheck) const
void debugReportMemoryLeak ()
bool debugStatisticsReport (const char *stateFile, bool memoryMap)
void free (void *ptr)
void freeAll ()
virtual void freeBlock (uint8 *block)
uint getAllocatedMemory () const
uint getAllocatedSystemMemoryByAllocator ()
TBlockAllocationMode getBlockAllocationMode () const
float getFragmentationRatio () const
uint getFreeMemory () const
uint getMainBlockCount () const
uint getMainBlockSize () const
const char * getName () const
TOutOfMemoryMode getOutOfMemoryMode () const
uint getSmallBlockMemory () const
uint getTotalMemoryUsed () const
void * reallocate (void *ptr, uint size, const char *sourceFile, uint line, const char *category)
void releaseMemory ()
void setBlockAllocationMode (TBlockAllocationMode mode)
bool setMainBlockCount (uint blockCount)
bool setMainBlockSize (uint mainBlockSize)
void setName (const char *name)
void setOutOfMemoryMode (TOutOfMemoryMode mode)
virtual ~CHeapAllocator ()

Static Public Member Functions

uint getAllocatedSystemMemory ()
uint getBlockSize (void *block)

Private Types

enum  { FreeNodeBlockSize = 128, FreeNodeBlockSizeShift = 7, FreeNodeBlockSizeMask = 0x7f }
enum  { Align = 8, BlockDataSizeMin = 1<<4 }
enum  { UserDataBlockSizeMin = sizeof(CFreeNode) }

Private Member Functions

bool checkFreeNode (const CFreeNode *current, bool stopOnError, bool recurse) const
void checkNode (const CNodeBegin *current, uint32 crc) const
bool checkNodeLB (const CMainBlock *mainBlock, const CNodeBegin *previous, const CNodeBegin *current, const CNodeBegin *next, bool stopOnError) const
void enterCriticalSection () const
void enterCriticalSectionLB () const
void enterCriticalSectionSB () const
void erase (CFreeNode *z)
CFreeNodefind (uint size)
void initEmptyBlock (CMainBlock &mainBlock)
void insert (CFreeNode *x)
bool internalCheckHeap (bool stopOnError) const
void leaveCriticalSection () const
void leaveCriticalSectionLB () const
void leaveCriticalSectionSB () const
void rotateLeft (CFreeNode *x)
void rotateRight (CFreeNode *x)
CNodeBeginsplitNode (CNodeBegin *node, uint newSize)

Static Private Member Functions

void computeCRC32 (uint32 &crc, const void *buffer, unsigned int count)
uint32 evalMagicNumber (const CNodeBegin *node)
CNodeBegingetFirstNode (CMainBlock *mainBlock)
const CNodeBegingetFirstNode (const CMainBlock *mainBlock)
CFreeNodegetFreeNode (CNodeBegin *current)
const CFreeNodegetFreeNode (const CNodeBegin *current)
CNodeBegingetNextNode (CNodeBegin *current)
const CNodeBegingetNextNode (const CNodeBegin *current)
CNodeBegingetNode (CFreeNode *current)
const CNodeBegingetNode (const CFreeNode *current)
uint getNodeSize (const CNodeBegin *current)
bool isNodeBlack (const CFreeNode *current)
bool isNodeFree (const CNodeBegin *current)
bool isNodeLast (const CNodeBegin *current)
bool isNodeRed (const CFreeNode *current)
bool isNodeSmall (const CNodeBegin *current)
bool isNodeUsed (const CNodeBegin *current)
void mergeNode (CNodeBegin *node)
void setNodeBlack (CFreeNode *current)
void setNodeColor (CFreeNode *current, bool red)
void setNodeFree (CNodeBegin *current)
void setNodeLast (CNodeBegin *current, bool last)
void setNodeRed (CFreeNode *current)
void setNodeSize (CNodeBegin *current, uint size)
void setNodeUsed (CNodeBegin *current)

Private Attributes

uint32 _AllocateCount
bool _AlwaysCheck
TBlockAllocationMode _BlockAllocationMode
uint _BlockCount
CFreeNode_FreeTreeRoot
CMainBlock_MainBlockList
uint _MainBlockSize
CAllocatorMutex _MutexLB
char _Name [NameLength]
CNullNode _NullNode
TOutOfMemoryMode _OutOfMemoryMode


Member Typedef Documentation

typedef char NLMISC::CHeapAllocator::TCategoryString[CategoryStringLength]
 

Definition at line 106 of file include/nel/misc/heap_allocator.h.


Member Enumeration Documentation

anonymous enum
 

Enumeration values:
ReleaseHeaderSize 
CategoryStringLength 
BeginNodeMarkers 
EndNodeMarkers 
UnallocatedMemory 
UninitializedMemory 
DeletedMemory 
NameLength 

Definition at line 70 of file include/nel/misc/heap_allocator.h.

00071         { 
00072                 ReleaseHeaderSize               =       8,
00073                 CategoryStringLength    =       8,
00074                 BeginNodeMarkers                =       '<',
00075                 EndNodeMarkers                  =       '>',
00076                 UnallocatedMemory               =       0xba,
00077                 UninitializedMemory             =       0xbc,
00078                 DeletedMemory                   =       0xbd,
00079                 NameLength                              =       32
00080         };

anonymous enum [private]
 

Enumeration values:
FreeNodeBlockSize 
FreeNodeBlockSizeShift 
FreeNodeBlockSizeMask 

Definition at line 205 of file include/nel/misc/heap_allocator.h.

00206         { 
00207                 FreeNodeBlockSize = 128, 
00208                 FreeNodeBlockSizeShift = 7, 
00209                 FreeNodeBlockSizeMask = 0x7f 
00210         };

anonymous enum [private]
 

Enumeration values:
Align 
BlockDataSizeMin 

Definition at line 213 of file include/nel/misc/heap_allocator.h.

00214         { 
00215                 Align = 8,
00216                 BlockDataSizeMin = 1<<4
00217         };

anonymous enum [private]
 

Enumeration values:
UserDataBlockSizeMin 

Definition at line 330 of file include/nel/misc/heap_allocator.h.

00331         {
00332                 UserDataBlockSizeMin = sizeof(CFreeNode)
00333         };

anonymous enum
 

Enumeration values:
SmallBlockGranularityShift 
SmallBlockGranularity 
FirstSmallBlock 
LastSmallBlock 
SmallBlockPoolSize 

Definition at line 403 of file include/nel/misc/heap_allocator.h.

00404         {
00405                 // Small block granularity
00406                 SmallBlockGranularityShift = 3,
00407 
00408                 // Small block granularity
00409                 SmallBlockGranularity = 1<<SmallBlockGranularityShift,
00410 
00411                 // Smallest block size
00412                 FirstSmallBlock = 8,
00413 
00414                 // Largest block size
00415                 LastSmallBlock = 128,
00416 
00417                 // Size of a smallblock pool
00418                 SmallBlockPoolSize = 20
00419         };

enum NLMISC::CHeapAllocator::TBlockAllocationMode
 

Block allocation mode.

Enumeration values:
Grow  When the allocator runs out of memory, allocate a new block.
DontGrow  When the allocator runs out of memory, returns a out of memory signal.

Definition at line 85 of file include/nel/misc/heap_allocator.h.

00086         { 
00088                 Grow, 
00089 
00091                 DontGrow 
00092         };

enum NLMISC::CHeapAllocator::TOutOfMemoryMode
 

Out of memory signal

Enumeration values:
ThrowException  When the allocator runs out of memory, throw an exception.
ReturnNull  When the allocator runs out of memory, returns NULL.

Definition at line 97 of file include/nel/misc/heap_allocator.h.

00098         { 
00100                 ThrowException, 
00101 
00103                 ReturnNull 
00104         };


Constructor & Destructor Documentation

NLMISC::CHeapAllocator::CHeapAllocator uint  mainBlockSize = 1024 *1024 *10,
uint  blockCount = 1,
TBlockAllocationMode  blockAllocationMode = Grow,
TOutOfMemoryMode  outOfMemoryMode = ThrowException
 

Definition at line 71 of file misc/heap_allocator.cpp.

References enterCriticalSection(), NLMISC::CHeapAllocator::CNullNode::FreeNode, internalAssert, leaveCriticalSection(), NLMISC::CHeapAllocator::CFreeNode::Left, NL_HEAP_NODE_END_SIZE, NL_SMALLBLOCK_COUNT, NLMISC::CHeapAllocator::CFreeNode::Parent, NLMISC::CHeapAllocator::CFreeNode::Right, setNodeBlack(), and uint.

00073 {
00074         // Critical section
00075         enterCriticalSection ();
00076 
00077         // Allocator name
00078         _Name[0] = 0;
00079 
00080         // Check size of structures must be aligned
00081         internalAssert ((sizeof (CNodeBegin) & (Align-1)) == 0);
00082         internalAssert ((NL_HEAP_NODE_END_SIZE & (Align-1)) == 0);
00083         internalAssert ((sizeof (CFreeNode) & (Align-1)) == 0);
00084 
00085         // Check small block sizes
00086         internalAssert ((FirstSmallBlock&(SmallBlockGranularity-1)) == 0);
00087         internalAssert ((LastSmallBlock&(SmallBlockGranularity-1)) == 0);
00088 
00089         _MainBlockList = NULL;
00090         _MainBlockSize = mainBlockSize;
00091         _BlockCount = blockCount;
00092         _BlockAllocationMode = blockAllocationMode;
00093         _OutOfMemoryMode = outOfMemoryMode;
00094         _FreeTreeRoot = &_NullNode.FreeNode;
00095 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00096         _AlwaysCheck = false;
00097 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00098 
00099         _NullNode.FreeNode.Left = &_NullNode.FreeNode;
00100         _NullNode.FreeNode.Right = &_NullNode.FreeNode;
00101         _NullNode.FreeNode.Parent = NULL;
00102 
00103         setNodeBlack (&_NullNode.FreeNode);
00104 
00105 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00106         _AllocateCount = 0;
00107 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00108 
00109         // *********************************************************
00110         // Small Block
00111         // *********************************************************
00112 
00113         // The free smallblock array by size
00114         const uint smallBlockSizeCount = NL_SMALLBLOCK_COUNT;
00115         uint smallBlockSize;
00116         for (smallBlockSize=0; smallBlockSize<smallBlockSizeCount; smallBlockSize++)
00117         {
00118                 _FreeSmallBlocks[smallBlockSize] = NULL;
00119         }
00120 
00121         // No small block
00122         _SmallBlockPool = NULL;
00123 
00124         leaveCriticalSection ();
00125 }

NLMISC::CHeapAllocator::~CHeapAllocator  )  [virtual]
 

Definition at line 129 of file misc/heap_allocator.cpp.

References releaseMemory().

00130 {
00131         // Release all memory used
00132         releaseMemory ();
00133 }


Member Function Documentation

void * NLMISC::CHeapAllocator::allocate uint  size,
const char *  sourceFile,
uint  line,
const char *  category
 

Definition at line 644 of file misc/heap_allocator.cpp.

References buffer, NLMISC::CHeapAllocator::CNodeEnd::EndMarkers, internalAssert, NLMISC::CHeapAllocator::CCategory::Name, NelAlloc, NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, NL_ALIGN_SIZE_FOR_SMALLBLOCK, NL_ALLOC_STOP, NL_HEAP_NODE_END_SIZE, NL_HEAP_SB_CATEGORY, NL_HEAP_UNKNOWN_CATEGORY, NL_SIZE_TO_SMALLBLOCK_INDEX, NL_SMALLBLOCK_COUNT, NL_UPDATE_MAGIC_NUMBER, NLMISC::CHeapAllocator::CMainBlock::Ptr, NLMISC::CHeapAllocator::CMainBlock::Size, NLMISC::CHeapAllocator::CSmallBlockPool::Size, size, NLMISC::CHeapAllocator::CNodeBegin::SizeAndFlags, uint, uint32, and uint8.

00646 {
00647         // Check size is valid
00648         if (size != 0)
00649         {
00650 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00651                 // If category is NULL
00652                 if (category == NULL)
00653                 {
00654                         // Get the current category
00655                         CCategory *cat = (CCategory*)_CategoryStack.getPointer ();
00656                         if (cat)
00657                         {
00658                                 category = cat->Name;
00659                         }
00660                         else
00661                         {
00662                                 // Not yet initialised
00663                                 category = NL_HEAP_UNKNOWN_CATEGORY;
00664                         }
00665                 }
00666 
00667                 // Checks ?
00668                 if (_AlwaysCheck)
00669                 {
00670                         // Check heap integrity
00671                         internalCheckHeap (true);
00672                 }
00673 
00674                 // Check breakpoints
00675                 /*if (_Breakpoints.find (_AllocateCount) != _Breakpoints.end())
00676                 {
00677                         // ********
00678                         // * STOP *
00679                         // ********
00680                         // * Breakpoints allocation
00681                         // ********
00682                         NL_ALLOC_STOP;
00683                 }*/
00684 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00685 
00686                 // Small or largs block ?
00687 #ifdef NLMISC_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00688                 if (0)
00689 #else // NLMISC_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00690                 if (size <= LastSmallBlock)
00691 #endif// NLMISC_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00692                 {
00693                         // *******************
00694                         // Small block
00695                         // *******************
00696                         
00697                         enterCriticalSectionSB ();
00698 
00699                         // Get pointer on the free block list
00700                         CNodeBegin **freeNode = (CNodeBegin **)_FreeSmallBlocks+NL_SIZE_TO_SMALLBLOCK_INDEX (size);
00701 
00702                         // Not found ?
00703                         if (*freeNode == NULL)
00704                         {
00705                                 leaveCriticalSectionSB ();
00706 
00707                                 // Size must be aligned
00708                                 uint alignedSize = NL_ALIGN_SIZE_FOR_SMALLBLOCK (size);
00709 
00710                                 // Use internal allocator
00711                                 CSmallBlockPool *smallBlock = (CSmallBlockPool *)NelAlloc (*this, sizeof(CSmallBlockPool) + SmallBlockPoolSize * (sizeof(CNodeBegin) + alignedSize + 
00712                                         NL_HEAP_NODE_END_SIZE), NL_HEAP_SB_CATEGORY);
00713 
00714                                 enterCriticalSectionSB ();
00715 
00716                                 // Link this new block
00717                                 smallBlock->Size = alignedSize;
00718                                 smallBlock->Next = (CSmallBlockPool*)_SmallBlockPool;
00719                                 _SmallBlockPool = smallBlock;
00720 
00721                                 // Initialize the block
00722                                 uint pool;
00723                                 CNodeBegin *nextNode = *freeNode;
00724                                 for (pool=0; pool<SmallBlockPoolSize; pool++)
00725                                 {
00726                                         // Get the pool
00727                                         CNodeBegin *node = getSmallBlock (smallBlock, pool);
00728 
00729                                         // Set as free
00730                                         node->SizeAndFlags = alignedSize;
00731 
00732                                         // Insert in the list
00733                                         setNextSmallBlock (node, nextNode);
00734                                         nextNode = node;
00735 
00736                                         // Set debug informations
00737 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00738                                         // Set node free
00739                                         setNodeFree (node);
00740                                         
00741                                         // End magic number
00742                                         node->EndMagicNumber = (uint32*)(CNodeEnd*)((uint8*)node + getNodeSize (node) + sizeof (CNodeBegin));
00743 
00744                                         // Begin markers
00745                                         memset (node->BeginMarkers, BeginNodeMarkers, CNodeBegin::MarkerSize-1);
00746                                         node->BeginMarkers[CNodeBegin::MarkerSize-1] = 0;
00747 
00748                                         // End markers
00749                                         CNodeEnd *endNode = (CNodeEnd*)((uint8*)node + getNodeSize (node) + sizeof (CNodeBegin));
00750                                         memset (endNode->EndMarkers, EndNodeMarkers, CNodeEnd::MarkerSize-1);
00751                                         endNode->EndMarkers[CNodeEnd::MarkerSize-1] = 0;
00752 
00753                                         // Unallocated memory
00754                                         memset ((uint8*)node + sizeof(CNodeBegin), UnallocatedMemory, getNodeSize (node) );
00755 
00756                                         // No source file
00757                                         memset (node->Category, 0, CategoryStringLength);
00758                                         node->File = NULL;
00759                                         node->Line = 0xffff;
00760                                         node->AllocateNumber = 0xffffffff;
00761 
00762                                         // Heap pointer
00763                                         node->Heap = this;
00764 
00765                                         NL_UPDATE_MAGIC_NUMBER (node);
00766 
00767 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00768                                 }
00769 
00770                                 // Link the new blocks
00771                                 *freeNode = nextNode;
00772                         }
00773 
00774                         // Check allocation as been done
00775                         internalAssert (*freeNode);
00776 
00777                         // Get a node
00778                         CNodeBegin *node = *freeNode;
00779 
00780                         // Checks
00781                         internalAssert (size <= getNodeSize (node));
00782                         internalAssert ((NL_SIZE_TO_SMALLBLOCK_INDEX (size)) < (NL_SMALLBLOCK_COUNT));
00783 
00784                         // Relink
00785                         *freeNode = getNextSmallBlock (node);
00786 
00787 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG           
00788                         // Check the node CRC
00789                         checkNode (node, evalMagicNumber (node));
00790 
00791                         // Set node free for checks
00792                         setNodeUsed (node);
00793 
00794                         // Fill category
00795                         strncpy (node->Category, category, CategoryStringLength-1);
00796 
00797                         // Source filename
00798                         node->File = sourceFile;
00799 
00800                         // Source line
00801                         node->Line = line;
00802 
00803                         // Allocate count
00804                         node->AllocateNumber = _AllocateCount++;
00805 
00806                         // End magic number aligned on new size
00807                         node->EndMagicNumber = (uint32*)((uint8*)node + size + sizeof (CNodeBegin));
00808 
00809                         // Uninitialised memory
00810                         memset ((uint8*)node + sizeof(CNodeBegin), UninitializedMemory, (uint32)(node->EndMagicNumber) - ( (uint32)node + sizeof(CNodeBegin) ) );
00811 
00812                         // Crc node
00813                         NL_UPDATE_MAGIC_NUMBER (node);
00814 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00815 
00816                         leaveCriticalSectionSB ();
00817 
00818                         // Return the user pointer
00819                         return (void*)((uint)node + sizeof (CNodeBegin));
00820                 }
00821                 else
00822                 {
00823                         // *******************
00824                         // Large block
00825                         // *******************
00826 
00827                         // Check size
00828                         if ( (size & ~CNodeBegin::SizeMask) != 0)
00829                         {
00830                                 // ********
00831                                 // * STOP *
00832                                 // ********
00833                                 // * Attempt to allocate more than 1 Go
00834                                 // ********
00835                                 NL_ALLOC_STOP;
00836 
00837                                 // Select outofmemory mode
00838                                 if (_OutOfMemoryMode == ReturnNull)
00839                                         return NULL;
00840                                 else
00841                                         throw std::bad_alloc();
00842                         }
00843 
00844                         enterCriticalSectionLB ();
00845 
00846                         // Find a free node
00847                         CHeapAllocator::CFreeNode *freeNode = CHeapAllocator::find (size);
00848 
00849                         // The node
00850                         CNodeBegin *node;
00851 
00852                         // Node not found ?
00853                         if (freeNode == NULL)
00854                         {
00855                                 // Block allocation mode
00856                                 if ((_BlockAllocationMode == DontGrow) && (_MainBlockList != NULL))
00857                                 {
00858                                         // Select outofmemory mode
00859                                         if (_OutOfMemoryMode == ReturnNull)
00860                                                 return NULL;
00861                                         else
00862                                                 throw std::bad_alloc();
00863                                 }
00864 
00865                                 // The node
00866                                 uint8 *buffer;
00867 
00868                                 // Alloc size
00869                                 uint allocSize;
00870 
00871                                 // Aligned size
00872                                 uint allignedSize = (size&~(Align-1)) + (( (size&(Align-1))==0 ) ? 0 : Align);
00873                                 if (allignedSize < BlockDataSizeMin)
00874                                         allignedSize = BlockDataSizeMin;
00875 
00876                                 // Does the node bigger than mainNodeSize ?
00877                                 if (allignedSize > (_MainBlockSize-sizeof (CNodeBegin)-NL_HEAP_NODE_END_SIZE))
00878                                         // Allocate a specific block
00879                                         allocSize = allignedSize + sizeof (CNodeBegin) + NL_HEAP_NODE_END_SIZE;
00880                                 else
00881                                         // Allocate a new block
00882                                         allocSize = _MainBlockSize;
00883 
00884                                 // Allocate the buffer
00885                                 buffer = allocateBlock (allocSize+Align);
00886 
00887                                 // Add the buffer
00888                                 CMainBlock *mainBlock = (CMainBlock*)allocateBlock (sizeof(CMainBlock)); 
00889                                 mainBlock->Size = allocSize+Align;
00890                                 mainBlock->Ptr = buffer;
00891                                 mainBlock->Next = _MainBlockList;
00892                                 _MainBlockList = mainBlock;
00893 
00894                                 // Init the new block
00895                                 initEmptyBlock (*mainBlock);
00896 
00897                                 // Get the first node
00898                                 node = getFirstNode (mainBlock);
00899                         }
00900                         else
00901                         {
00902                                 // Get the node
00903                                 node = getNode (freeNode);
00904 
00905                                 // Remove the node from free blocks and get the removed block
00906                                 erase (freeNode);
00907                         }
00908 
00909 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00910                         // Check the node CRC
00911                         checkNode (node, evalMagicNumber (node));
00912 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00913 
00914                         // Split the node
00915                         CNodeBegin *rest = splitNode (node, size);
00916 
00917                         // Fill informations for the first part of the node
00918 
00919                         // Clear free flag
00920                         setNodeUsed (node);
00921 
00922 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00923                         // Fill category
00924                         strncpy (node->Category, category, CategoryStringLength-1);
00925 
00926                         // Source filename
00927                         node->File = sourceFile;
00928 
00929                         // Source line
00930                         node->Line = line;
00931 
00932                         // Allocate count
00933                         node->AllocateNumber = _AllocateCount++;
00934 
00935                         // Crc node
00936                         NL_UPDATE_MAGIC_NUMBER (node);
00937 
00938                         // Uninitialised memory
00939                         memset ((uint8*)node + sizeof(CNodeBegin), UninitializedMemory, (uint32)(node->EndMagicNumber) - ( (uint32)node + sizeof(CNodeBegin) ) );
00940 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00941 
00942                         // Node has been splited ?
00943                         if (rest)
00944                         {
00945                                 // Fill informations for the second part of the node
00946 
00947                                 // Get the freeNode
00948                                 freeNode = getFreeNode (rest);
00949 
00950                                 // Insert the free node
00951                                 insert (freeNode);
00952 
00953                                 // Crc node
00954                                 NL_UPDATE_MAGIC_NUMBER (rest);
00955                         }
00956 
00957                         // Check the node size
00958                         internalAssert ( size <= getNodeSize (node) );
00959                         internalAssert ( std::max ((uint)BlockDataSizeMin, size + (uint)Align) + sizeof (CNodeBegin) + sizeof (CNodeEnd) + sizeof (CNodeBegin) + sizeof (CNodeEnd) + BlockDataSizeMin >= getNodeSize (node) );
00960 
00961                         // Check pointer alignment
00962                         internalAssert (((uint32)node&(Align-1)) == 0);
00963                         internalAssert (((uint32)((char*)node + sizeof(CNodeBegin))&(Align-1)) == 0);
00964 
00965                         // Check size
00966                         internalAssert ((uint32)node->EndMagicNumber <= (uint32)((uint8*)node+sizeof(CNodeBegin)+getNodeSize (node) ));
00967                         internalAssert ((uint32)node->EndMagicNumber > (uint32)(((uint8*)node+sizeof(CNodeBegin)+getNodeSize (node) ) - BlockDataSizeMin - BlockDataSizeMin - sizeof(CNodeBegin) - sizeof(CNodeEnd)));
00968 
00969                         leaveCriticalSectionLB ();
00970 
00971                         // Return the user pointer
00972                         return (void*)((uint)node + sizeof (CNodeBegin));
00973                 }
00974         }
00975         else
00976         {
00977                 // ********
00978                 // * STOP *
00979                 // ********
00980                 // * Attempt to allocate 0 bytes
00981                 // ********
00982                 NL_ALLOC_STOP;
00983                 return NULL;
00984         }
00985 }

uint8 * NLMISC::CHeapAllocator::allocateBlock uint  size  )  [virtual]
 

Definition at line 2059 of file misc/heap_allocator.cpp.

References size, uint, and uint8.

02060 {
02061 #undef malloc
02062         return (uint8*)::malloc (size);
02063 }

bool NLMISC::CHeapAllocator::checkFreeNode const CFreeNode current,
bool  stopOnError,
bool  recurse
const [private]
 

Referenced by internalCheckHeap().

bool NLMISC::CHeapAllocator::checkHeap bool  stopOnError  )  const
 

Definition at line 2050 of file misc/heap_allocator.cpp.

References internalCheckHeap(), and res.

02051 {
02052         bool res = internalCheckHeap (stopOnError);
02053 
02054         return res;
02055 }

void NLMISC::CHeapAllocator::checkNode const CNodeBegin current,
uint32  crc
const [private]
 

Definition at line 2214 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNodeBegin::EndMagicNumber, NLMISC::CHeapAllocator::CNodeBegin::Heap, NL_ALLOC_STOP, and uint32.

Referenced by debugReportMemoryLeak(), free(), getAllocatedMemory(), and getFreeMemory().

02215 {
02216         // Check the bottom CRC of the node 
02217         if (crc != *(node->EndMagicNumber))
02218         {
02219                 // ********
02220                 // * STOP *
02221                 // ********
02222                 // * The bottom CRC32 of the current node is wrong. Use checkMemory() to debug the heap.
02223                 // ********
02224                 // * (*node) Check for more informations
02225                 // ********
02226                 NL_ALLOC_STOP;
02227         }
02228 
02229         // Check the node is hold by this heap
02230         if (node->Heap != this)
02231         {
02232                 // ********
02233                 // * STOP *
02234                 // ********
02235                 // * This node is not hold by this heap. It has been allocated with another heap.
02236                 // ********
02237                 // * (*node) Check for more informations
02238                 // ********
02239                 NL_ALLOC_STOP;
02240         }
02241 }

bool NLMISC::CHeapAllocator::checkNodeLB const CMainBlock mainBlock,
const CNodeBegin previous,
const CNodeBegin current,
const CNodeBegin next,
bool  stopOnError
const [private]
 

Referenced by internalCheckHeap().

bool NLMISC::CHeapAllocator::checkNodeSB const CSmallBlockPool mainBlock,
const CNodeBegin previous,
const CNodeBegin current,
const CNodeBegin next,
bool  stopOnError
const [private]
 

Referenced by internalCheckHeap().

void NLMISC::CHeapAllocator::computeCRC32 uint32 crc,
const void *  buffer,
unsigned int  count
[inline, static, private]
 

void NLMISC::CHeapAllocator::debugAlwaysCheckMemory bool  alwaysCheck  ) 
 

Definition at line 2143 of file misc/heap_allocator.cpp.

02144 {
02145         _AlwaysCheck = alwaysCheck;
02146 }

uint NLMISC::CHeapAllocator::debugGetAllocatedMemoryByCategory const char *  category  )  const
 

Definition at line 1245 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNodeBegin::Category, enterCriticalSection(), getFirstNode(), getNextNode(), getNodeSize(), getSmallBlock(), isNodeUsed(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, and uint.

01246 {
01247         enterCriticalSection ();
01248 
01249         // Sum allocated memory
01250         uint memory = 0;
01251 
01252         // For each small block
01253         CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01254         while (currentSB)
01255         {
01256                 // For each node in this small block pool
01257                 uint block;
01258                 for (block=0; block<SmallBlockPoolSize; block++)
01259                 {
01260                         // Get the node
01261                         const CNodeBegin *current = getSmallBlock (currentSB, block);
01262 
01263                         // Node allocated ?
01264                         if ((isNodeUsed (current)) && (strcmp (current->Category, category)==0))
01265                                 memory += getNodeSize (current);
01266 
01267                         memory += getNodeSize (current);
01268                 }
01269 
01270                 // Next block
01271                 currentSB = currentSB->Next;
01272         }
01273 
01274         // For each main block
01275         CMainBlock *currentBlock = _MainBlockList;
01276         while (currentBlock)
01277         {
01278                 // Get the first node
01279                 const CNodeBegin *current = getFirstNode (currentBlock);
01280                 while (current)
01281                 {
01282                         // Node allocated ?
01283                         if ((isNodeUsed (current)) && (strcmp (current->Category, category)==0))
01284                                 memory += getNodeSize (current);
01285 
01286                         // Next node
01287                         current = getNextNode (current);
01288                 }
01289 
01290                 // Next block
01291                 currentBlock = currentBlock->Next;
01292         }
01293 
01294         leaveCriticalSection ();
01295 
01296         // Return memory used
01297         return memory;
01298 }

uint NLMISC::CHeapAllocator::debugGetDebugInfoSize  )  const
 

Definition at line 1304 of file misc/heap_allocator.cpp.

References debugGetLBDebugInfoSize(), debugGetSBDebugInfoSize(), and uint.

01305 {
01306         // Return memory used
01307         return debugGetSBDebugInfoSize () + debugGetLBDebugInfoSize ();
01308 }

uint NLMISC::CHeapAllocator::debugGetLBDebugInfoSize  )  const
 

Definition at line 1310 of file misc/heap_allocator.cpp.

References enterCriticalSection(), getFirstNode(), getNextNode(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, and uint.

Referenced by debugGetDebugInfoSize().

01311 {
01312         enterCriticalSection ();
01313 
01314         // Sum memory used by debug header
01315         uint memory = 0;
01316 
01317         // For each main block
01318         CMainBlock *currentBlock = _MainBlockList;
01319         while (currentBlock)
01320         {
01321                 // Get the first node
01322                 const CNodeBegin *current = getFirstNode (currentBlock);
01323                 while (current)
01324                 {
01325                         // Node allocated ?
01326                         memory  += sizeof(CNodeBegin) - ReleaseHeaderSize + sizeof(CNodeEnd);
01327 
01328                         // Next node
01329                         current = getNextNode (current);
01330                 }
01331 
01332                 // Next block
01333                 currentBlock = currentBlock->Next;
01334         }
01335 
01336         leaveCriticalSection ();
01337 
01338         // Return memory used
01339         return memory;
01340 }

uint NLMISC::CHeapAllocator::debugGetSBDebugInfoSize  )  const
 

Definition at line 1342 of file misc/heap_allocator.cpp.

References enterCriticalSection(), leaveCriticalSection(), NLMISC::CHeapAllocator::CSmallBlockPool::Next, and uint.

Referenced by debugGetDebugInfoSize().

01343 {
01344         enterCriticalSection ();
01345 
01346         // Sum memory used by debug header
01347         uint memory = 0;
01348 
01349         // For each small blocks
01350         CSmallBlockPool *pool = (CSmallBlockPool*)_SmallBlockPool;
01351         while (pool)
01352         {
01353                 memory  += SmallBlockPoolSize * (sizeof(CNodeBegin) - ReleaseHeaderSize + sizeof(CNodeEnd));
01354 
01355                 // Next pool
01356                 pool = pool->Next;
01357         }
01358 
01359         leaveCriticalSection ();
01360 
01361         // Return memory used
01362         return memory;
01363 }

bool NLMISC::CHeapAllocator::debugIsAlwaysCheckMemory bool  alwaysCheck  )  const
 

Definition at line 2152 of file misc/heap_allocator.cpp.

02153 {
02154         return _AlwaysCheck;
02155 }

void NLMISC::CHeapAllocator::debugPopCategoryString  ) 
 

Definition at line 2189 of file misc/heap_allocator.cpp.

References free(), NLMISC::CTDS::getPointer(), NLMISC::CHeapAllocator::CCategory::Next, and NLMISC::CTDS::setPointer().

Referenced by debugReportMemoryLeak(), and debugStatisticsReport().

02190 {
02191         // Get the category stack pointer
02192         CCategory *last = (CCategory*)_CategoryStack.getPointer ();
02193         // nlassertex (last, ("(CHeapAllocator::debugPopCategoryString ()) Pop category wihtout Push"));
02194         if (last)
02195         {
02196                 CCategory *next = last->Next;
02197 
02198                 // Free last node, no need to be thread safe here, because we use thread specifc storage
02199                 free (last);
02200 
02201                 /* Push it, no need to be thread safe here, because we use thread specifc storage */
02202                 _CategoryStack.setPointer (next);
02203         }
02204 }

void NLMISC::CHeapAllocator::debugPushCategoryString const char *  str  ) 
 

Definition at line 2173 of file misc/heap_allocator.cpp.

References NLMISC::CTDS::getPointer(), NLMISC::CHeapAllocator::CCategory::Name, NelAlloc, NLMISC::CHeapAllocator::CCategory::Next, NL_HEAP_CATEGORY_BLOCK_CATEGORY, and NLMISC::CTDS::setPointer().

Referenced by debugReportMemoryLeak(), and debugStatisticsReport().

02174 {
02175         // Get the category stack pointer
02176         CCategory *last = (CCategory*)_CategoryStack.getPointer ();
02177 
02178         // New category node
02179         CCategory *_new = (CCategory *)NelAlloc (*this, sizeof(CCategory), NL_HEAP_CATEGORY_BLOCK_CATEGORY);
02180         _new->Name = str;
02181         _new->Next = last;
02182 
02183         /* Push it, no need to be thread safe here, because we use thread specifc storage */
02184         _CategoryStack.setPointer (_new);
02185 }

void NLMISC::CHeapAllocator::debugReportMemoryLeak  ) 
 

Definition at line 1916 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocatorOutputError(), checkNode(), debugPopCategoryString(), debugPushCategoryString(), getFirstNode(), getNextNode(), getNodeSize(), getSmallBlock(), isNodeUsed(), NLMISC::CHeapAllocator::CSmallBlockPool::Next, NLMISC::CHeapAllocator::CMainBlock::Next, NL_HEAP_MEM_DEBUG_CATEGORY, NLMISC::report(), NLMISC::smprintf(), NLMISC::TLinkMap, and uint.

01917 {
01918         // enterCriticalSection ();
01919 
01920         debugPushCategoryString (NL_HEAP_MEM_DEBUG_CATEGORY);
01921 
01922         // Sum allocated memory
01923         uint memory = 0;
01924 
01925         // Leak map
01926         TLinkMap leakMap;
01927 
01928         // Header
01929         char report[2048];
01930         smprintf (report, 2048, "Report Memory leak for allocator \"%s\"\n", _Name);
01931         CHeapAllocatorOutputError (report);
01932 
01933         // For each small block
01934         CMainBlock *currentBlock = _MainBlockList;
01935         while (currentBlock)
01936         {
01937                 // Get the first node
01938                 const CNodeBegin *current = getFirstNode (currentBlock);
01939                 while (current)
01940                 {
01941                         // Check node
01942                         checkNode (current, evalMagicNumber (current));
01943 
01944                         // Node allocated ?
01945                         if (isNodeUsed (current) && ( (current->Category == NULL) || (current->Category[0] != '_')) )
01946                         {
01947                                 // Make a report
01948                                 smprintf (report, 2048, "%s(%d)\t: \"%s\"", current->File, current->Line, current->Category);
01949 
01950                                 // Look for this leak
01951                                 TLinkMap::iterator ite = leakMap.find (report);
01952 
01953                                 // Not found ?
01954                                 if (ite == leakMap.end ())
01955                                 {
01956                                         ite = leakMap.insert (TLinkMap::value_type (report, CLeak ())).first;
01957                                         ite->second.Count = 0;
01958                                         ite->second.Memory = 0;
01959                                 }
01960 
01961                                 // One more leak
01962                                 ite->second.Count++;
01963                                 ite->second.Memory += getNodeSize (current);
01964 
01965                                 memory += getNodeSize (current);
01966                         }
01967 
01968                         // Next node
01969                         current = getNextNode (current);
01970                 }
01971 
01972                 // Next block
01973                 currentBlock = currentBlock->Next;
01974         }
01975 
01976         // For each small block
01977         CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01978         while (currentSB)
01979         {
01980                 // For each node in this small block pool
01981                 uint block;
01982                 for (block=0; block<SmallBlockPoolSize; block++)
01983                 {
01984                         // Get the node
01985                         const CNodeBegin *current = getSmallBlock (currentSB, block);
01986                         // Check node
01987                         checkNode (current, evalMagicNumber (current));
01988 
01989                         // Node allocated ?
01990                         if (isNodeUsed (current) && ( (current->Category == NULL) || (current->Category[0] != '_')) )
01991                         {
01992                                 // Make a report
01993                                 smprintf (report, 2048, "%s(%d)\t: \"%s\"",     current->File, current->Line, current->Category);
01994 
01995                                 // Look for this leak
01996                                 TLinkMap::iterator ite = leakMap.find (report);
01997 
01998                                 // Not found ?
01999                                 if (ite == leakMap.end ())
02000                                 {
02001                                         ite = leakMap.insert (TLinkMap::value_type (report, CLeak ())).first;
02002                                         ite->second.Count = 0;
02003                                         ite->second.Memory = 0;
02004                                 }
02005 
02006                                 // One more leak
02007                                 ite->second.Count++;
02008                                 ite->second.Memory += getNodeSize (current);
02009 
02010                                 memory += getNodeSize (current);
02011                         }
02012                 }
02013 
02014                 // Next block
02015                 currentSB = currentSB->Next;
02016         }
02017 
02018         // Look for this leak
02019         TLinkMap::iterator ite = leakMap.begin ();
02020         while (ite != leakMap.end ())
02021         {
02022                 // Make a report
02023                 smprintf (report, 2048, "%s,\tLeak count : %d,\tMemory allocated : %d\n", ite->first.c_str (), ite->second.Count, ite->second.Memory);
02024 
02025                 // Report on stderr
02026                 CHeapAllocatorOutputError (report);
02027 
02028                 ite++;
02029         }
02030 
02031         // Make a report
02032         if (memory)
02033         {
02034                 smprintf (report, 2048, "%d byte(s) found\n", memory);
02035         }
02036         else
02037         {
02038                 smprintf (report, 2048, "No memory leak\n");
02039         }
02040         CHeapAllocatorOutputError (report);
02041 
02042         debugPopCategoryString ();
02043 
02044         // leaveCriticalSection ();
02045 }

bool NLMISC::CHeapAllocator::debugStatisticsReport const char *  stateFile,
bool  memoryMap
 

Definition at line 1393 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNodeBegin::Category, count, debugPopCategoryString(), debugPushCategoryString(), file, getAllocatedSystemMemory(), getAllocatedSystemMemoryByAllocator(), getFirstNode(), getNextNode(), getNodeSize(), getSmallBlock(), index, isNodeFree(), isNodeUsed(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, NL_HEAP_MEM_DEBUG_CATEGORY, NL_HEAP_NODE_END_SIZE, NL_SIZE_TO_SMALLBLOCK_INDEX, NL_SMALLBLOCK_COUNT, NLMISC::CHeapAllocator::CSmallBlockPool::Size, size, and uint.

01394 {
01395         // Status
01396         bool status = false;
01397 
01398         debugPushCategoryString (NL_HEAP_MEM_DEBUG_CATEGORY);
01399 
01400         // Open files
01401         FILE *file = fopen (stateFile, "wt");
01402 
01403         // Block map
01404         typedef std::map<std::string, CCategoryMap> TBlockMap;
01405         TBlockMap blockMap;
01406 
01407         // Both OK
01408         if (file)
01409         {
01410                 // **************************
01411 
01412                 // For each small block
01413                 uint smallBlockCount = 0;
01414                 uint largeBlockCount = 0;
01415                 CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01416                 while (currentSB)
01417                 {
01418                         // For each node in this small block pool
01419                         uint block;
01420                         for (block=0; block<SmallBlockPoolSize; block++)
01421                         {
01422                                 // Get the node
01423                                 const CNodeBegin *current = getSmallBlock (currentSB, block);
01424 
01425                                 // Node allocated ?
01426                                 if (isNodeUsed (current))
01427                                 {
01428                                         // Find the node
01429                                         TBlockMap::iterator ite = blockMap.find ((const char*)current->Category);
01430 
01431                                         // Found ?
01432                                         if (ite == blockMap.end ())
01433                                         {
01434                                                 ite = blockMap.insert (TBlockMap::value_type (current->Category, CCategoryMap ())).first;
01435                                         }
01436                                         uint size = getNodeSize (current) + ReleaseHeaderSize;
01437                                         ite->second.BlockCount++;
01438                                         ite->second.Size += size;
01439                                         if (size < ite->second.Min)
01440                                                 ite->second.Min = size;
01441                                         if (size > ite->second.Max)
01442                                                 ite->second.Max = size;
01443                                 }
01444 
01445                                 // Next node
01446                                 smallBlockCount++;
01447                         }
01448 
01449                         // Next block
01450                         currentSB = currentSB->Next;
01451                 }
01452 
01453                 // For each main block
01454                 CMainBlock *currentBlock = _MainBlockList;
01455                 while (currentBlock)
01456                 {
01457                         // Get the first node
01458                         const CNodeBegin *current = getFirstNode (currentBlock);
01459                         while (current)
01460                         {
01461                                 // Node is used ?
01462                                 if (isNodeUsed (current))
01463                                 {
01464                                         // Find the node
01465                                         TBlockMap::iterator ite = blockMap.find ((const char*)current->Category);
01466 
01467                                         // Found ?
01468                                         if (ite == blockMap.end ())
01469                                         {
01470                                                 ite = blockMap.insert (TBlockMap::value_type (current->Category, CCategoryMap ())).first;
01471                                         }
01472                                         uint size = getNodeSize (current) + ReleaseHeaderSize;
01473                                         ite->second.BlockCount++;
01474                                         ite->second.Size += size;
01475                                         if (size < ite->second.Min)
01476                                                 ite->second.Min = size;
01477                                         if (size > ite->second.Max)
01478                                                 ite->second.Max = size;
01479                                 }
01480 
01481                                 // Next node
01482                                 current = getNextNode (current);
01483                                 largeBlockCount++;
01484                         }
01485 
01486                         // Next block
01487                         currentBlock = currentBlock->Next;
01488                 }
01489 
01490                 // Write the heap info file
01491                 fprintf (file, "HEAP STATISTICS\n");
01492                 fprintf (file, "HEAP, TOTAL MEMORY USED, ALLOCATED MEMORY, FREE MEMORY, FRAGMENTATION RATIO, MAIN BLOCK SIZE, MAIN BLOCK COUNT\n");
01493 
01494                 fprintf (file, "%s, %d, %d, %d, %f%%, %d, %d\n", _Name, getTotalMemoryUsed (),
01495                         getAllocatedMemory (), getFreeMemory (), 100.f*getFragmentationRatio (), getMainBlockSize (), getMainBlockCount ());
01496 
01497                 fprintf (file, "\n\nHEAP BLOCKS\n");
01498                 fprintf (file, "SMALL BLOCK MEMORY, SMALL BLOCK COUNT, LARGE BLOCK COUNT\n");
01499 
01500                 fprintf (file, "%d, %d, %d\n", getSmallBlockMemory (), smallBlockCount, largeBlockCount);
01501 
01502                 fprintf (file, "\n\nHEAP DEBUG INFOS\n");
01503                 fprintf (file, "SB DEBUG INFO, LB DEBUG INFO, TOTAL DEBUG INFO\n");
01504 
01505                 fprintf (file, "%d, %d, %d\n", debugGetSBDebugInfoSize (), debugGetLBDebugInfoSize (), debugGetDebugInfoSize ());
01506 
01507                 // **************************
01508 
01509                 // Write the system heap info file
01510                 uint systemMemory = getAllocatedSystemMemory ();
01511                 uint nelSystemMemory = getAllocatedSystemMemoryByAllocator ();
01512 
01513                 fprintf (file, "\n\nSYSTEM HEAP STATISTICS\n");
01514                 fprintf (file, "TOTAL ALLOCATED MEMORY, NEL ALLOCATED MEMORY, OTHER ALLOCATED MEMORY\n");
01515                 fprintf (file, "%d, %d, %d\n", systemMemory, nelSystemMemory, systemMemory-nelSystemMemory);
01516 
01517                 // Write the category map file
01518                 fprintf (file, "\n\n\nCATEGORY STATISTICS\n");
01519                 fprintf (file, "CATEGORY, BLOCK COUNT, MEMORY ALLOCATED, MIN BLOCK SIZE, MAX BLOCK SIZE, AVERAGE BLOCK SIZE, SB COUNT 8, SB COUNT 16, SB COUNT 24, SB COUNT 32, SB COUNT 40, SB COUNT 48, SB COUNT 56, SB COUNT 64, SB COUNT 72, SB COUNT 80, SB COUNT 88, SB COUNT 96, SB COUNT 104, SB COUNT 112, SB COUNT 120, SB COUNT 128\n");
01520 
01521                 TBlockMap::iterator ite = blockMap.begin();
01522                 while (ite != blockMap.end())
01523                 {
01524                         // Number of small blocks
01525                         uint smallB[NL_SMALLBLOCK_COUNT];
01526 
01527                         // Clean
01528                         uint smallBlock;
01529                         for (smallBlock=0; smallBlock<NL_SMALLBLOCK_COUNT; smallBlock++)
01530                         {
01531                                 smallB[smallBlock] = 0;
01532                         }
01533                         
01534                         // Scan small block for this category
01535                         currentSB = (CSmallBlockPool *)_SmallBlockPool;
01536                         while (currentSB)
01537                         {
01538                                 // For each node in this small block pool
01539                                 uint block;
01540                                 for (block=0; block<SmallBlockPoolSize; block++)
01541                                 {
01542                                         // Get the node
01543                                         const CNodeBegin *current = getSmallBlock (currentSB, block);
01544 
01545                                         // Node allocated ?
01546                                         if (isNodeUsed (current))
01547                                         {
01548                                                 // Good node ?
01549                                                 if (current->Category == ite->first)
01550                                                 {
01551                                                         // Get the small block index
01552                                                         uint index = NL_SIZE_TO_SMALLBLOCK_INDEX (getNodeSize (current));
01553 
01554                                                         // One more node
01555                                                         smallB[index]++;
01556                                                 }
01557                                         }
01558                                 }
01559 
01560                                 // Next block
01561                                 currentSB = currentSB->Next;
01562                         }
01563 
01564                         // Average
01565                         uint average = ite->second.Size / ite->second.BlockCount;
01566 
01567                         // Print the line
01568                         fprintf (file, "%s, %d, %d, %d, %d, %d", ite->first.c_str(), ite->second.BlockCount, ite->second.Size, 
01569                                 ite->second.Min, ite->second.Max, average);
01570 
01571                         // Print small blocks
01572                         for (smallBlock=0; smallBlock<NL_SMALLBLOCK_COUNT; smallBlock++)
01573                         {
01574                                 fprintf (file, ", %d", smallB[smallBlock]);
01575                         }
01576 
01577                         fprintf (file, "\n");
01578 
01579                         ite++;
01580                 }
01581 
01582                 // **************************
01583 
01584                 // Write the small block statistics
01585                 fprintf (file, "\n\n\nSMALL BLOCK STATISTICS\n");
01586                 fprintf (file, "SIZE, BLOCK COUNT, BLOCK FREE, BLOCK USED, TOTAL MEMORY USED\n");
01587 
01588                 // Number of small blocks
01589                 uint count[NL_SMALLBLOCK_COUNT];
01590                 uint free[NL_SMALLBLOCK_COUNT];
01591 
01592                 uint smallBlock;
01593                 for (smallBlock=0; smallBlock<NL_SMALLBLOCK_COUNT; smallBlock++)
01594                 {
01595                         count[smallBlock] = 0;
01596                         free[smallBlock] = 0;
01597                 }
01598 
01599                 // For each small block
01600                 currentSB = (CSmallBlockPool *)_SmallBlockPool;
01601                 while (currentSB)
01602                 {
01603                         // For each node in this small block pool
01604                         uint block;
01605                         for (block=0; block<SmallBlockPoolSize; block++)
01606                         {
01607                                 // Get the node
01608                                 const CNodeBegin *current = getSmallBlock (currentSB, block);
01609 
01610                                 // Get the small block index
01611                                 uint index = NL_SIZE_TO_SMALLBLOCK_INDEX (getNodeSize (current));
01612 
01613                                 // Add a block
01614                                 count[index]++;
01615 
01616                                 // Node allocated ?
01617                                 if (isNodeFree (current))
01618                                 {
01619                                         // Add a free block
01620                                         free[index]++;
01621                                 }
01622 
01623                                 // Next node
01624                                 current = getNextNode (current);
01625                         }
01626 
01627                         // Next block
01628                         currentSB = currentSB->Next;
01629                 }
01630 
01631                 // Print stats
01632                 for (smallBlock=0; smallBlock<NL_SMALLBLOCK_COUNT; smallBlock++)
01633                 {
01634                         uint size = (smallBlock+1)*SmallBlockGranularity;
01635                         fprintf (file,"%d, %d, %d, %d, %d\n",size, count[smallBlock], free[smallBlock], 
01636                                 count[smallBlock]-free[smallBlock], count[smallBlock]*(sizeof (CNodeBegin) + size + NL_HEAP_NODE_END_SIZE));
01637                 }
01638                 
01639                 // **************************
01640 
01641                 // Write the memory map file
01642                 if (memoryMap)
01643                 {
01644                         fprintf (file, "\n\n\nHEAP LARGE BLOCK DUMP\n");
01645                         fprintf (file, "ADDRESS, SIZE, CATEGORY, HEAP, STATE, SOURCE, LINE\n");
01646 
01647                         // For each main block
01648                         currentBlock = _MainBlockList;
01649                         while (currentBlock)
01650                         {
01651                                 // Get the first node
01652                                 const CNodeBegin *current = getFirstNode (currentBlock);
01653                                 while (current)
01654                                 {
01655                                         // Write the entry
01656                                         fprintf (file, "0x%08x, %d, %s, %s, %s, %s, %d\n", (uint)current + sizeof(CNodeBegin),
01657                                                 getNodeSize (current), current->Category, _Name, 
01658                                                 isNodeFree (current)?"free":"used", current->File, current->Line);
01659 
01660                                         // Next node
01661                                         current = getNextNode (current);
01662                                 }
01663 
01664                                 // Next block
01665                                 currentBlock = currentBlock->Next;
01666                         }
01667                 }
01668 
01669                 // File created successfuly
01670                 status = true;
01671         }
01672 
01673         // Close
01674         if (file)
01675                 fclose (file);
01676 
01677         debugPopCategoryString ();
01678 
01679         return status;
01680 }

void NLMISC::CHeapAllocator::enterCriticalSection  )  const [private]
 

Referenced by CHeapAllocator(), debugGetAllocatedMemoryByCategory(), debugGetLBDebugInfoSize(), debugGetSBDebugInfoSize(), freeAll(), getAllocatedMemory(), getFragmentationRatio(), getFreeMemory(), getSmallBlockMemory(), getTotalMemoryUsed(), internalCheckHeap(), releaseMemory(), and setName().

void NLMISC::CHeapAllocator::enterCriticalSectionLB  )  const [private]
 

Referenced by free().

void NLMISC::CHeapAllocator::enterCriticalSectionSB  )  const [private]
 

Referenced by free().

void NLMISC::CHeapAllocator::erase CFreeNode z  )  [inline, private]
 

Definition at line 260 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNullNode::FreeNode, internalAssert, isNodeBlack(), isNodeRed(), NL_UPDATE_MAGIC_NUMBER_FREE_NODE, rotateLeft(), rotateRight(), setNodeBlack(), setNodeColor(), setNodeRed(), w, x, y, and z.

Referenced by free().

00261 {
00262         CFreeNode *x, *y;
00263         if (z->Left == &_NullNode.FreeNode || z->Right == &_NullNode.FreeNode)
00264         {
00265                 // y has a NULL node as a child
00266                 y = z;
00267         }
00268         else
00269         {
00270                 // Find tree successor with a &_NullNode.FreeNode node as a child
00271                 y = z->Right;
00272                 while (y->Left != &_NullNode.FreeNode)
00273                         y = y->Left;
00274         }
00275         
00276         // x is y's only child
00277         if (y->Left != &_NullNode.FreeNode)
00278                 x = y->Left;
00279         else
00280                 x = y->Right;
00281 
00282         // Remove y from the parent chain
00283         x->Parent = y->Parent;
00284 
00285         if (y->Parent)
00286         {
00287                 if (y == y->Parent->Left)
00288                         y->Parent->Left = x;
00289                 else
00290                 {
00291                         internalAssert (y == y->Parent->Right);
00292                         y->Parent->Right = x;
00293                 }
00294                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Parent);
00295         }
00296         else
00297                 _FreeTreeRoot = x;
00298 
00299         bool yRed = isNodeRed (y);
00300 
00301         if (y != z)
00302         {
00303                 // Replace y by z
00304                 *y = *z;
00305                 setNodeColor (y, isNodeRed (z));
00306                 if (y->Parent)
00307                 {
00308                         if (y->Parent->Left == z)
00309                         {
00310                                 y->Parent->Left = y;
00311                         }
00312                         else
00313                         {
00314                                 internalAssert (y->Parent->Right == z);
00315                                 y->Parent->Right = y;
00316                         }
00317                 }
00318                 else
00319                 {
00320                         internalAssert (_FreeTreeRoot == z);
00321                         _FreeTreeRoot = y;
00322                 }
00323 
00324                 if (y->Left)
00325                 {
00326                         internalAssert (y->Left->Parent == z);
00327                         y->Left->Parent = y;
00328                         
00329                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Left);
00330                 }
00331                 if (y->Right)
00332                 {
00333                         internalAssert (y->Right->Parent == z);
00334                         y->Right->Parent = y;
00335         
00336                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Right);
00337                 }
00338         }
00339 
00340         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x);
00341         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y);
00342         if (y->Parent)
00343                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Parent);
00344 
00345         if (!yRed)
00346         {
00347                 // Maintain Red-Black tree balance
00348                 // After deleting node x
00349                 while (x != _FreeTreeRoot && isNodeBlack (x))
00350                 {
00351                         if (x == x->Parent->Left)
00352                         {
00353                                 CFreeNode *w = x->Parent->Right;
00354                                 if (isNodeRed (w))
00355                                 {
00356                                         setNodeBlack (w);
00357                                         setNodeRed (x->Parent);
00358                                         rotateLeft (x->Parent);
00359 
00360                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00361 
00362                                         w = x->Parent->Right;
00363                                 }
00364                                 if (isNodeBlack (w->Left) && isNodeBlack (w->Right))
00365                                 {
00366                                         setNodeRed (w);
00367                                         x = x->Parent;
00368 
00369                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00370                                 }
00371                                 else
00372                                 {
00373                                         if (isNodeBlack (w->Right))
00374                                         {
00375                                                 setNodeBlack (w->Left);
00376                                                 setNodeRed (w);
00377                                                 rotateRight (w);
00378                                                 w = x->Parent->Right;
00379                                         }
00380                                         setNodeColor (w, isNodeRed (x->Parent));
00381                                         setNodeBlack (x->Parent);
00382                                         setNodeBlack (w->Right);
00383                                         rotateLeft (x->Parent);
00384 
00385                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00386                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w->Right);
00387 
00388                                         x = _FreeTreeRoot;
00389                                 }
00390                         }
00391                         else
00392                         {
00393                                 CFreeNode *w = x->Parent->Left;
00394                                 if (isNodeRed (w))
00395                                 {
00396                                         setNodeBlack (w);
00397                                         setNodeRed (x->Parent);
00398                                         rotateRight (x->Parent);
00399 
00400                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00401 
00402                                         w = x->Parent->Left;
00403                                 }
00404                                 if ( isNodeBlack (w->Right) && isNodeBlack (w->Left) )
00405                                 {
00406                                         setNodeRed (w);
00407                                         x = x->Parent;
00408 
00409                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00410                                 }
00411                                 else
00412                                 {
00413                                         if ( isNodeBlack (w->Left) )
00414                                         {
00415                                                 setNodeBlack (w->Right);
00416                                                 setNodeRed (w);
00417                                                 rotateLeft (w);
00418                                                 w = x->Parent->Left;
00419                                         }
00420                                         setNodeColor (w, isNodeRed (x->Parent) );
00421                                         setNodeBlack (x->Parent);
00422                                         setNodeBlack (w->Left);
00423 
00424                                         rotateRight (x->Parent);
00425 
00426                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w);
00427                                         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (w->Left);
00428 
00429                                         x = _FreeTreeRoot;
00430                                 }
00431                         }
00432                 }
00433                 setNodeBlack (x);
00434                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x);
00435         }
00436 }

uint32 NLMISC::CHeapAllocator::evalMagicNumber const CNodeBegin node  )  [static, private]
 

CFreeNode* NLMISC::CHeapAllocator::find uint  size  )  [inline, private]
 

void NLMISC::CHeapAllocator::free void *  ptr  ) 
 

Definition at line 989 of file misc/heap_allocator.cpp.

References checkNode(), NLMISC::CHeapAllocator::CNodeBegin::EndMagicNumber, enterCriticalSectionLB(), enterCriticalSectionSB(), erase(), getNextNode(), getNodeSize(), insert(), internalCheckHeap(), isNodeFree(), leaveCriticalSectionLB(), leaveCriticalSectionSB(), mergeNode(), NL_ALLOC_STOP, NL_SIZE_TO_SMALLBLOCK_INDEX, NL_UPDATE_MAGIC_NUMBER, NLMISC::CHeapAllocator::CNodeBegin::Previous, setNodeFree(), size, uint, uint32, and uint8.

Referenced by debugPopCategoryString().

00990 {
00991         // Delete a null pointer ?
00992         if (ptr == NULL)
00993         {
00994                 // ********
00995                 // * STOP *
00996                 // ********
00997                 // * Attempt to delete a NULL pointer
00998                 // ********
00999 #ifdef NLMISC_HEAP_STOP_NULL_FREE
01000                 NL_ALLOC_STOP;
01001 #endif // NLMISC_HEAP_STOP_NULL_FREE
01002         }
01003         else
01004         {
01005 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01006                 // Checks ?
01007                 if (_AlwaysCheck)
01008                 {
01009                         // Check heap integrity
01010                         internalCheckHeap (true);
01011                 }
01012 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01013                 
01014                 // Get the node pointer
01015                 CNodeBegin *node = (CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin));
01016 
01017 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01018                 // Check the node CRC
01019                 enterCriticalSectionSB ();
01020                 enterCriticalSectionLB ();
01021                 checkNode (node, evalMagicNumber (node));
01022                 leaveCriticalSectionLB ();
01023                 leaveCriticalSectionSB ();
01024 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01025 
01026                 // Large or small block ?
01027 #ifdef NLMISC_HEAP_ALLOCATION_NDEBUG
01028                 uint size = (((CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin))))->SizeAndFlags;
01029 #else // NLMISC_HEAP_ALLOCATION_NDEBUG
01030                 uint size = getNodeSize (((CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin))));
01031 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01032                 if (size <= LastSmallBlock)
01033                 {
01034                         // *******************
01035                         // Small block
01036                         // *******************
01037 
01038                         // Check the node has not been deleted
01039                         if (isNodeFree (node))
01040                         {
01041                                 // ********
01042                                 // * STOP *
01043                                 // ********
01044                                 // * Attempt to delete a pointer already deleted
01045                                 // ********
01046                                 // * (*node):   the already deleted node
01047                                 // ********
01048                                 NL_ALLOC_STOP;
01049                         }
01050                         else
01051                         {
01052                                 enterCriticalSectionSB ();
01053 
01054 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01055                                 // Uninitialised memory
01056                                 memset ((uint8*)node + sizeof(CNodeBegin), DeletedMemory, size );
01057 
01058                                 // Set end pointers
01059                                 node->EndMagicNumber = (uint32*)((uint8*)node + size + sizeof (CNodeBegin));
01060 
01061                                 // Mark has free
01062                                 setNodeFree (node);
01063 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01064 
01065                                 // Add in the free list
01066                                 CNodeBegin **freeNode = (CNodeBegin **)_FreeSmallBlocks+NL_SIZE_TO_SMALLBLOCK_INDEX (size);
01067                                 ((CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin)))->Previous = *freeNode;
01068                                 *freeNode = ((CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin)));
01069 
01070                                 // Update smallblock crc
01071                                 NL_UPDATE_MAGIC_NUMBER (node);
01072 
01073                                 leaveCriticalSectionSB ();
01074                         }
01075                 }
01076                 else
01077                 {
01078 #ifdef NLMISC_HEAP_ALLOCATION_NDEBUG
01079                         // Get the real size
01080                         size = getNodeSize (((CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin))));
01081 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01082 
01083                         // Get the node pointer
01084                         CNodeBegin *node = (CNodeBegin*) ((uint)ptr - sizeof (CNodeBegin));
01085 
01086                         // Check the node has not been deleted
01087                         if (isNodeFree (node))
01088                         {
01089                                 // ********
01090                                 // * STOP *
01091                                 // ********
01092                                 // * Attempt to delete a pointer already deleted
01093                                 // ********
01094                                 // * (*node):   the already deleted node
01095                                 // ********
01096                                 NL_ALLOC_STOP;
01097                         }
01098                         else
01099                         {
01100                                 enterCriticalSectionLB ();
01101 
01102 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01103                                 // Uninitialised memory
01104                                 memset ((uint8*)node + sizeof(CNodeBegin), DeletedMemory, size );
01105 
01106                                 // Set end pointers
01107                                 node->EndMagicNumber = (uint32*)((uint8*)node + size + sizeof (CNodeBegin));
01108 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01109 
01110                                 // Mark has free
01111                                 setNodeFree (node);
01112 
01113                                 // *******************
01114                                 // Large block
01115                                 // *******************
01116 
01117                                 // A free node
01118                                 //CHeapAllocator::CFreeNode *freeNode = NULL;
01119 
01120                                 // Previous node
01121                                 CNodeBegin *previous = node->Previous;
01122                                 if (previous)
01123                                 {
01124 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01125                                         // Check the previous node
01126                                         checkNode (previous, evalMagicNumber (previous));
01127 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01128 
01129                                         // Is it free ?
01130                                         if (isNodeFree (previous))
01131                                         {
01132                                                 // Merge the two nodes
01133                                                 mergeNode (node);
01134 
01135                                                 // Get its free node
01136                                                 erase (getFreeNode (previous));
01137 
01138                                                 // Curent node
01139                                                 node = previous;
01140                                         }
01141                                 }
01142 
01143                                 // Mark has free
01144                                 setNodeFree (node);
01145 
01146                                 // Next node
01147                                 CNodeBegin *next = getNextNode (node);
01148                                 if (next)
01149                                 {
01150 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01151                                         // Check the next node
01152                                         checkNode (next, evalMagicNumber (next));
01153 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01154 
01155                                         // Is it free ?
01156                                         if (isNodeFree (next))
01157                                         {
01158                                                 // Free the new one
01159                                                 erase (getFreeNode (next));
01160 
01161                                                 // Merge the two nodes
01162                                                 mergeNode (next);
01163                                         }
01164                                 }
01165 
01166                                 // Insert it into the tree
01167                                 insert (getFreeNode (node));
01168 
01169                                 NL_UPDATE_MAGIC_NUMBER (node);
01170                                 
01171                                 leaveCriticalSectionLB ();
01172                         }
01173                 }
01174         }
01175 }

void NLMISC::CHeapAllocator::freeAll  ) 
 

Definition at line 1845 of file misc/heap_allocator.cpp.

References enterCriticalSection(), NLMISC::CHeapAllocator::CNullNode::FreeNode, getFirstNode(), initEmptyBlock(), insert(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, and NL_UPDATE_MAGIC_NUMBER.

01846 {
01847         enterCriticalSection ();
01848 
01849         // Sum free memory
01850         //uint memory = 0;
01851 
01852         // Clear the free tree
01853         _FreeTreeRoot = &_NullNode.FreeNode;
01854 
01855         // For each main block
01856         CMainBlock *currentBlock = _MainBlockList;
01857         while (currentBlock)
01858         {
01859                 // Reinit this block
01860                 initEmptyBlock (*currentBlock);
01861 
01862                 // Get first block
01863                 CNodeBegin *node = getFirstNode (currentBlock);
01864 
01865                 // Insert the free node
01866                 insert (getFreeNode (node));
01867 
01868                 NL_UPDATE_MAGIC_NUMBER (node);
01869 
01870                 // Next block
01871                 currentBlock = currentBlock->Next;
01872         }
01873 
01874         leaveCriticalSection ();
01875 }

void NLMISC::CHeapAllocator::freeBlock uint8 block  )  [virtual]
 

Definition at line 2067 of file misc/heap_allocator.cpp.

References uint8.

Referenced by releaseMemory().

02068 {
02069         ::free (block);
02070 }

uint NLMISC::CHeapAllocator::getAllocatedMemory  )  const
 

Definition at line 1181 of file misc/heap_allocator.cpp.

References checkNode(), enterCriticalSection(), getFirstNode(), getNextNode(), getNodeSize(), getSmallBlock(), isNodeUsed(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, NL_HEAP_SB_CATEGORY, and uint.

01182 {
01183         enterCriticalSection ();
01184 
01185         // Sum allocated memory
01186         uint memory = 0;
01187 
01188         // For each small block
01189         CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01190         while (currentSB)
01191         {
01192                 // For each node in this small block pool
01193                 uint block;
01194                 for (block=0; block<SmallBlockPoolSize; block++)
01195                 {
01196                         // Get the node
01197                         const CNodeBegin *current = getSmallBlock (currentSB, block);
01198 
01199                         // Node allocated ?
01200                         if (isNodeUsed (current))
01201                                 memory += getNodeSize (current) + ReleaseHeaderSize;
01202                 }
01203 
01204                 // Next block
01205                 currentSB = currentSB->Next;
01206         }
01207 
01208         // For each main block
01209         CMainBlock *currentBlock = _MainBlockList;
01210         while (currentBlock)
01211         {
01212                 // Get the first node
01213                 const CNodeBegin *current = getFirstNode (currentBlock);
01214                 while (current)
01215                 {
01216 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01217                         // Check node
01218                         checkNode (current, evalMagicNumber (current));
01219 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01220 
01221                         // Node allocated ? Don't sum small blocks..
01222                         if (isNodeUsed (current))
01223 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01224                                 if (strcmp (current->Category, NL_HEAP_SB_CATEGORY) != 0)
01225 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01226                                         memory += getNodeSize (current) + ReleaseHeaderSize;
01227 
01228                         // Next node
01229                         current = getNextNode (current);
01230                 }
01231 
01232                 // Next block
01233                 currentBlock = currentBlock->Next;
01234         }
01235 
01236         leaveCriticalSection ();
01237 
01238         // Return memory used
01239         return memory;
01240 }

uint NLMISC::CHeapAllocator::getAllocatedSystemMemory  )  [static]
 

Definition at line 2269 of file misc/heap_allocator.cpp.

References buffer, len, nlwarning, NLMISC::skipToken(), NLMISC::skipWS(), and uint.

Referenced by debugStatisticsReport().

02270 {
02271         uint systemMemory = 0;
02272 #ifdef NL_OS_WINDOWS
02273         // Get system memory informations
02274         HANDLE hHeap[100];
02275         DWORD heapCount = GetProcessHeaps (100, hHeap);
02276 
02277         uint heap;
02278         for (heap = 0; heap < heapCount; heap++)
02279         {
02280                 PROCESS_HEAP_ENTRY entry;
02281                 entry.lpData = NULL;
02282                 while (HeapWalk (hHeap[heap], &entry))
02283                 {
02284                         if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
02285                         {
02286                                 systemMemory += entry.cbData + entry.cbOverhead;
02287                         }
02288                 }
02289         }
02290 
02291 #elif defined NL_OS_UNIX
02292         
02293         int fd = open("/proc/self/stat", O_RDONLY);
02294         if (fd == -1)
02295         {
02296                 nlwarning ("HA: Can't get OS from /proc/self/stat: %s", strerror (errno));
02297         }
02298         else
02299         {
02300                 char buffer[4096], *p;
02301                 int len = read(fd, buffer, sizeof(buffer)-1);
02302                 close(fd);
02303         
02304                 buffer[len] = '\0';
02305                 
02306                 p = buffer;
02307                 p = strchr(p, ')')+1;                   /* skip pid */
02308                 p = skipWS(p);
02309                 p++;
02310                 
02311                 p = skipToken(p);                               /* skip ppid */
02312                 p = skipToken(p);                               /* skip pgrp */
02313                 p = skipToken(p);                               /* skip session */
02314                 p = skipToken(p);                               /* skip tty */
02315                 p = skipToken(p);                               /* skip tty pgrp */
02316                 p = skipToken(p);                               /* skip flags */
02317                 p = skipToken(p);                               /* skip min flt */
02318                 p = skipToken(p);                               /* skip cmin flt */
02319                 p = skipToken(p);                               /* skip maj flt */
02320                 p = skipToken(p);                               /* skip cmaj flt */
02321                 p = skipToken(p);                               /* utime */
02322                 p = skipToken(p);                               /* stime */
02323                 p = skipToken(p);                               /* skip cutime */
02324                 p = skipToken(p);                               /* skip cstime */
02325                 p = skipToken(p);                               /* priority */
02326                 p = skipToken(p);                               /* nice */
02327                 p = skipToken(p);                               /* skip timeout */
02328                 p = skipToken(p);                               /* skip it_real_val */
02329                 p = skipToken(p);                               /* skip start_time */
02330                 
02331                 systemMemory = strtoul(p, &p, 10);      /* vsize in bytes */
02332         }
02333 
02334 #endif // NL_OS_WINDOWS
02335         return systemMemory;
02336 }

uint NLMISC::CHeapAllocator::getAllocatedSystemMemoryByAllocator  ) 
 

Definition at line 2340 of file misc/heap_allocator.cpp.

References uint.

Referenced by debugStatisticsReport().

02341 {
02342         uint nelSystemMemory = 0;
02343 
02344         // Build a set of allocated system memory pointers
02345         std::set<void*> ptrInUse;
02346 
02347         // For each main block
02348         CMainBlock *currentBlock = _MainBlockList;
02349         while (currentBlock)
02350         {
02351                 // Save pointers
02352                 ptrInUse.insert ((void*)currentBlock);
02353                 ptrInUse.insert ((void*)(currentBlock->Ptr));
02354 
02355                 // Next block
02356                 currentBlock = currentBlock->Next;
02357         }
02358 
02359 #ifdef NL_OS_WINDOWS
02360         // Get system memory informations
02361         HANDLE hHeap[100];
02362         DWORD heapCount = GetProcessHeaps (100, hHeap);
02363 
02364         uint heap;
02365         for (heap = 0; heap < heapCount; heap++)
02366         {
02367                 PROCESS_HEAP_ENTRY entry;
02368                 entry.lpData = NULL;
02369                 while (HeapWalk (hHeap[heap], &entry))
02370                 {
02371                         if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
02372                         {
02373                                 // This pointer is already used ?
02374                                 if ( (ptrInUse.find ((void*)((char*)entry.lpData)) != ptrInUse.end ()) || 
02375                                         (ptrInUse.find ((void*)((char*)entry.lpData+32)) != ptrInUse.end ()) )
02376                                         nelSystemMemory += entry.cbData + entry.cbOverhead;
02377                         }
02378                 }
02379         }
02380 #endif // NL_OS_WINDOWS
02381         return nelSystemMemory;
02382 }

TBlockAllocationMode NLMISC::CHeapAllocator::getBlockAllocationMode  )  const
 

uint NLMISC::CHeapAllocator::getBlockSize void *  block  )  [static]
 

Definition at line 631 of file misc/heap_allocator.cpp.

References getNodeSize(), and uint.

00632 {
00633         // Get the node pointer
00634   //CNodeBegin *node = (CNodeBegin*) ((uint)block - sizeof (CNodeBegin));
00635 
00636         return getNodeSize (((CNodeBegin*) ((uint)block - sizeof (CNodeBegin))));
00637 }

CNodeBegin* NLMISC::CHeapAllocator::getFirstNode CMainBlock mainBlock  )  [static, private]
 

const CNodeBegin* NLMISC::CHeapAllocator::getFirstNode const CMainBlock mainBlock  )  [static, private]
 

Referenced by debugGetAllocatedMemoryByCategory(), debugGetLBDebugInfoSize(), debugReportMemoryLeak(), debugStatisticsReport(), freeAll(), getAllocatedMemory(), getFragmentationRatio(), getFreeMemory(), initEmptyBlock(), and internalCheckHeap().

float NLMISC::CHeapAllocator::getFragmentationRatio  )  const
 

Definition at line 1804 of file misc/heap_allocator.cpp.

References enterCriticalSection(), getFirstNode(), getNextNode(), isNodeUsed(), leaveCriticalSection(), and NLMISC::CHeapAllocator::CMainBlock::Next.

01805 {
01806         enterCriticalSection ();
01807 
01808         // Sum free and used node
01809         float free = 0;
01810         float used = 0;
01811 
01812         // For each main block
01813         CMainBlock *currentBlock = _MainBlockList;
01814         while (currentBlock)
01815         {
01816                 // Get the first node
01817                 const CNodeBegin *current = getFirstNode (currentBlock);
01818                 while (current)
01819                 {
01820                         // Node allocated ?
01821                         if (isNodeUsed (current))
01822                                 used++;
01823                         else
01824                                 free++;
01825 
01826                         // Next node
01827                         current = getNextNode (current);
01828                 }
01829 
01830                 // Next block
01831                 currentBlock = currentBlock->Next;
01832         }
01833 
01834         leaveCriticalSection ();
01835 
01836         // Return the memory
01837         if (used != 0)
01838                 return free / used;
01839         else
01840                 return 0;
01841 }

uint NLMISC::CHeapAllocator::getFreeMemory  )  const
 

Definition at line 1685 of file misc/heap_allocator.cpp.

References checkNode(), enterCriticalSection(), getFirstNode(), getNextNode(), getNodeSize(), getSmallBlock(), isNodeFree(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, and uint.

01686 {
01687         enterCriticalSection ();
01688 
01689         // Sum free memory
01690         uint memory = 0;
01691 
01692         // For each small block
01693         CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01694         while (currentSB)
01695         {
01696                 // For each node in this small block pool
01697                 uint block;
01698                 for (block=0; block<SmallBlockPoolSize; block++)
01699                 {
01700                         // Get the node
01701                         const CNodeBegin *current = getSmallBlock (currentSB, block);
01702 
01703                         // Node allocated ?
01704                         if (isNodeFree (current))
01705                                 memory  += getNodeSize (current) + ReleaseHeaderSize;
01706 
01707                         // Next node
01708                         current = getNextNode (current);
01709                 }
01710 
01711                 // Next block
01712                 currentSB = currentSB->Next;
01713         }
01714 
01715         // For each main block
01716         CMainBlock *currentBlock = _MainBlockList;
01717         while (currentBlock)
01718         {
01719                 // Get the first node
01720                 const CNodeBegin *current = getFirstNode (currentBlock);
01721                 while (current)
01722                 {
01723 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
01724                         // Check node
01725                         checkNode (current, evalMagicNumber (current));
01726 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
01727 
01728                         // Node allocated ?
01729                         if (isNodeFree (current))
01730                                 memory  += getNodeSize (current) + ReleaseHeaderSize;
01731 
01732                         // Next node
01733                         current = getNextNode (current);
01734                 }
01735 
01736                 // Next block
01737                 currentBlock = currentBlock->Next;
01738         }
01739 
01740         leaveCriticalSection ();
01741 
01742         // Return memory used
01743         return memory;
01744 }

CFreeNode* NLMISC::CHeapAllocator::getFreeNode CNodeBegin current  )  [static, private]
 

const CFreeNode* NLMISC::CHeapAllocator::getFreeNode const CNodeBegin current  )  [static, private]
 

uint NLMISC::CHeapAllocator::getMainBlockCount  )  const
 

uint NLMISC::CHeapAllocator::getMainBlockSize  )  const
 

const char* NLMISC::CHeapAllocator::getName  )  const
 

CNodeBegin* NLMISC::CHeapAllocator::getNextNode CNodeBegin current  )  [static, private]
 

const CNodeBegin* NLMISC::CHeapAllocator::getNextNode const CNodeBegin current  )  [static, private]
 

Referenced by debugGetAllocatedMemoryByCategory(), debugGetLBDebugInfoSize(), debugReportMemoryLeak(), debugStatisticsReport(), free(), getAllocatedMemory(), getFragmentationRatio(), getFreeMemory(), internalCheckHeap(), mergeNode(), and splitNode().

CNodeBegin* NLMISC::CHeapAllocator::getNextSmallBlock CNodeBegin previous  )  [static, private]
 

CNodeBegin* NLMISC::CHeapAllocator::getNode CFreeNode current  )  [static, private]
 

const CNodeBegin* NLMISC::CHeapAllocator::getNode const CFreeNode current  )  [static, private]
 

uint NLMISC::CHeapAllocator::getNodeSize const CNodeBegin current  )  [static, private]
 

Referenced by debugGetAllocatedMemoryByCategory(), debugReportMemoryLeak(), debugStatisticsReport(), free(), getAllocatedMemory(), getBlockSize(), getFreeMemory(), initEmptyBlock(), insert(), mergeNode(), and splitNode().

TOutOfMemoryMode NLMISC::CHeapAllocator::getOutOfMemoryMode  )  const
 

CNodeBegin* NLMISC::CHeapAllocator::getSmallBlock CSmallBlockPool smallBlock,
uint  blockIndex
[static, private]
 

Referenced by debugGetAllocatedMemoryByCategory(), debugReportMemoryLeak(), debugStatisticsReport(), getAllocatedMemory(), getFreeMemory(), and internalCheckHeap().

uint NLMISC::CHeapAllocator::getSmallBlockMemory  )  const
 

Definition at line 1777 of file misc/heap_allocator.cpp.

References enterCriticalSection(), leaveCriticalSection(), NLMISC::CHeapAllocator::CSmallBlockPool::Next, NL_HEAP_NODE_END_SIZE, NLMISC::CHeapAllocator::CSmallBlockPool::Size, and uint.

01778 {
01779         enterCriticalSection ();
01780 
01781         // Sum total memory
01782         uint memory = 0;
01783 
01784         // For each small block
01785         CSmallBlockPool *currentSB = (CSmallBlockPool *)_SmallBlockPool;
01786         while (currentSB)
01787         {
01788                 // Get block size
01789                 memory += sizeof(CSmallBlockPool) + SmallBlockPoolSize * (sizeof(CNodeBegin) + currentSB->Size + 
01790                                         NL_HEAP_NODE_END_SIZE);
01791 
01792                 // Next block
01793                 currentSB = currentSB->Next;
01794         }
01795 
01796         leaveCriticalSection ();
01797 
01798         // Return the memory
01799         return memory;
01800 }

uint NLMISC::CHeapAllocator::getTotalMemoryUsed  )  const
 

Definition at line 1748 of file misc/heap_allocator.cpp.

References enterCriticalSection(), leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CMainBlock::Size, and uint.

01749 {
01750         enterCriticalSection ();
01751 
01752         // Sum total memory
01753         uint memory = 0;
01754 
01755         // For each main block
01756         CMainBlock *currentBlock = _MainBlockList;
01757         while (currentBlock)
01758         {
01759                 // Get block size
01760                 memory += currentBlock->Size;
01761 
01762                 // Sum the arrays
01763                 memory += sizeof (CMainBlock);
01764 
01765                 // Next block
01766                 currentBlock = currentBlock->Next;
01767         }
01768 
01769         leaveCriticalSection ();
01770 
01771         // Return the memory
01772         return memory;
01773 }

void NLMISC::CHeapAllocator::initEmptyBlock CMainBlock mainBlock  )  [inline, private]
 

Definition at line 576 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNodeBegin::BeginMarkers, NLMISC::CHeapAllocator::CNodeBegin::EndMagicNumber, NLMISC::CHeapAllocator::CNodeEnd::EndMarkers, getFirstNode(), getNodeSize(), internalAssert, NL_HEAP_NODE_END_SIZE, NL_UPDATE_MAGIC_NUMBER, NLMISC::CHeapAllocator::CNodeBegin::Previous, NLMISC::CHeapAllocator::CMainBlock::Ptr, setNodeFree(), setNodeLast(), setNodeSize(), NLMISC::CHeapAllocator::CMainBlock::Size, uint, uint32, and uint8.

Referenced by freeAll().

00577 {
00578         // Get the node pointer
00579         CNodeBegin *node = getFirstNode (&mainBlock);
00580 
00581         // Allocated size remaining after alignment
00582         internalAssert ((uint32)node - (uint32)mainBlock.Ptr >= 0);
00583         uint allocSize = mainBlock.Size - ((uint32)node - (uint32)mainBlock.Ptr);
00584 
00585         // *** Fill the new node header
00586 
00587         // User data size
00588         setNodeSize (node, allocSize-sizeof (CNodeBegin)-NL_HEAP_NODE_END_SIZE);
00589 
00590         // Node is free
00591         setNodeFree (node);
00592 
00593         // Node is last
00594         setNodeLast (node, true);
00595 
00596         // No previous node
00597         node->Previous = NULL;
00598 
00599         // Debug info
00600 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00601         // End magic number
00602         node->EndMagicNumber = (uint32*)((uint8*)node + getNodeSize (node) + sizeof (CNodeBegin));
00603 
00604         // Begin markers
00605         memset (node->BeginMarkers, BeginNodeMarkers, CNodeBegin::MarkerSize-1);
00606         node->BeginMarkers[CNodeBegin::MarkerSize-1] = 0;
00607 
00608         // End markers
00609         CNodeEnd *endNode = (CNodeEnd*)node->EndMagicNumber;
00610         memset (endNode->EndMarkers, EndNodeMarkers, CNodeEnd::MarkerSize-1);
00611         endNode->EndMarkers[CNodeEnd::MarkerSize-1] = 0;
00612 
00613         // Unallocated memory
00614         memset ((uint8*)node + sizeof(CNodeBegin), UnallocatedMemory, getNodeSize (node) );
00615 
00616         // No source file
00617         memset (node->Category, 0, CategoryStringLength);
00618         node->File = NULL;
00619         node->Line = 0xffff;
00620         node->AllocateNumber = 0xffffffff;
00621 
00622         // Heap pointer
00623         node->Heap = this;
00624 
00625         NL_UPDATE_MAGIC_NUMBER (node);
00626 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00627 }

void NLMISC::CHeapAllocator::insert CFreeNode x  )  [inline, private]
 

Definition at line 137 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNullNode::FreeNode, getNodeSize(), isNodeRed(), NLMISC::CHeapAllocator::CFreeNode::Left, NL_UPDATE_MAGIC_NUMBER_FREE_NODE, NLMISC::CHeapAllocator::CFreeNode::Right, rotateLeft(), rotateRight(), setNodeBlack(), setNodeRed(), x, and y.

Referenced by free(), and freeAll().

00138 {
00139     CHeapAllocator::CFreeNode *current, *parent;
00140 
00141     // Find future parent
00142         current = _FreeTreeRoot;
00143         parent = NULL;
00144         while (current != &_NullNode.FreeNode)
00145         {
00146                 parent = current;
00147                 current = (getNodeSize (getNode (x)) <= getNodeSize (getNode (current)) ) ? current->Left : current->Right;
00148         }
00149 
00150         // Setup new node
00151         x->Parent = parent;
00152         x->Left = &_NullNode.FreeNode;
00153         x->Right = &_NullNode.FreeNode;
00154         setNodeRed (x);
00155 
00156         // Insert node in tree
00157         if (parent)
00158         {
00159                 if(getNodeSize (getNode (x)) <= getNodeSize (getNode (parent)))
00160                         parent->Left = x;
00161                 else
00162                         parent->Right = x;
00163                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (parent);
00164         }
00165         else
00166         {
00167                 _FreeTreeRoot = x;
00168         }
00169 
00170         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x);
00171 
00172     // Maintain Red-Black tree balance
00173     // After inserting node x
00174         // Check Red-Black properties
00175 
00176         while (x != _FreeTreeRoot && isNodeRed (x->Parent))
00177         {
00178                 // We have a violation
00179                 if (x->Parent == x->Parent->Parent->Left)
00180                 {
00181                         CHeapAllocator::CFreeNode *y = x->Parent->Parent->Right;
00182                         if (isNodeRed (y))
00183                         {
00184                                 // Uncle is RED
00185                 setNodeBlack (x->Parent);
00186                                 setNodeBlack (y);
00187                                 setNodeRed (x->Parent->Parent);
00188 
00189                                 // Crc node
00190                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y);
00191                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00192                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent->Parent);
00193 
00194                                 x = x->Parent->Parent;
00195                         }
00196                         else
00197                         {
00198                 // Uncle is Black
00199                                 if (x == x->Parent->Right)
00200                                 {
00201                     // Make x a left child
00202                                         x = x->Parent;
00203                     rotateLeft(x);
00204                                 }
00205 
00206                                 // Recolor and rotate
00207                                 setNodeBlack (x->Parent);
00208                                 setNodeRed (x->Parent->Parent);
00209 
00210                                 rotateRight (x->Parent->Parent);
00211 
00212                                 // Crc node
00213                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00214                         }
00215                 }
00216                 else
00217                 {
00218                         // Mirror image of above code
00219                         CHeapAllocator::CFreeNode *y = x->Parent->Parent->Left;
00220                         if (isNodeRed (y))
00221                         {                
00222                                 // Uncle is Red
00223                                 setNodeBlack (x->Parent);
00224                                 setNodeBlack (y);
00225                                 setNodeRed (x->Parent->Parent);
00226 
00227                                 // Crc node
00228                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y);
00229                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00230                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent->Parent);
00231 
00232                                 x = x->Parent->Parent;
00233                         }
00234                         else
00235                         {
00236                 // Uncle is Black
00237                 if (x == x->Parent->Left) 
00238                                 {
00239                     x = x->Parent;                    
00240                                         rotateRight(x);
00241                 }
00242                                 setNodeBlack (x->Parent);
00243                 setNodeRed (x->Parent->Parent);
00244 
00245                 rotateLeft (x->Parent->Parent);
00246 
00247                                 // Crc node
00248                                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00249                         }        
00250                 }    
00251         }
00252     setNodeBlack (_FreeTreeRoot);
00253 
00254         // Crc node
00255         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (_FreeTreeRoot);
00256 }

bool NLMISC::CHeapAllocator::internalCheckHeap bool  stopOnError  )  const [private]
 

Definition at line 2074 of file misc/heap_allocator.cpp.

References checkFreeNode(), checkNodeLB(), checkNodeSB(), enterCriticalSection(), getFirstNode(), getNextNode(), getSmallBlock(), internalAssert, leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, NLMISC::CHeapAllocator::CSmallBlockPool::Next, and uint.

Referenced by checkHeap(), and free().

02075 {
02076         enterCriticalSection ();
02077 
02078         // For each small blocks
02079         CSmallBlockPool *pool = (CSmallBlockPool*)_SmallBlockPool;
02080         while (pool)
02081         {
02082                 // For each small block
02083                 uint smallBlock;
02084                 CNodeBegin      *previous = NULL;
02085                 for (smallBlock=0; smallBlock<SmallBlockPoolSize; smallBlock++)
02086                 {
02087                         // Get the small block
02088                         CNodeBegin      *node = getSmallBlock (pool, smallBlock);
02089                         CNodeBegin      *next = (smallBlock+1<SmallBlockPoolSize) ? getSmallBlock (pool, smallBlock+1) : NULL;
02090 
02091                         // Check node
02092                         checkNodeSB (pool, previous, node, next, stopOnError);
02093 
02094                         previous = node;
02095                 }
02096 
02097                 // Next pool
02098                 pool = pool->Next;
02099         }
02100         
02101         // For each main block
02102         CMainBlock *currentBlock = _MainBlockList;
02103         while (currentBlock)
02104         {
02105                 // Get the nodes
02106                 const CNodeBegin *previous = NULL;
02107                 const CNodeBegin *current = getFirstNode (currentBlock);
02108                 internalAssert (current);       // Should have at least one block in the main block
02109                 const CNodeBegin *next;
02110                 
02111                 // For each node
02112                 while (current)
02113                 {
02114                         // Get next
02115                         next = getNextNode (current);
02116 
02117                         // Return Error ?
02118                         if (!checkNodeLB (currentBlock, previous, current, next, stopOnError))
02119                                 return false;
02120 
02121                         // Next
02122                         previous = current;
02123                         current = next;
02124                 }
02125 
02126                 // Next block
02127                 currentBlock = currentBlock->Next;
02128         }
02129 
02130         // Check free tree
02131         if (!checkFreeNode (_FreeTreeRoot, stopOnError, true))
02132                 return false;
02133 
02134         leaveCriticalSection ();
02135 
02136         // Ok, no problem
02137         return true;
02138 }

bool NLMISC::CHeapAllocator::isNodeBlack const CFreeNode current  )  [static, private]
 

Referenced by erase().

bool NLMISC::CHeapAllocator::isNodeFree const CNodeBegin current  )  [static, private]
 

Referenced by debugStatisticsReport(), free(), and getFreeMemory().

bool NLMISC::CHeapAllocator::isNodeLast const CNodeBegin current  )  [static, private]
 

bool NLMISC::CHeapAllocator::isNodeRed const CFreeNode current  )  [static, private]
 

Referenced by erase(), and insert().

bool NLMISC::CHeapAllocator::isNodeSmall const CNodeBegin current  )  [static, private]
 

bool NLMISC::CHeapAllocator::isNodeUsed const CNodeBegin current  )  [static, private]
 

Referenced by debugGetAllocatedMemoryByCategory(), debugReportMemoryLeak(), debugStatisticsReport(), getAllocatedMemory(), and getFragmentationRatio().

void NLMISC::CHeapAllocator::leaveCriticalSection  )  const [private]
 

Referenced by CHeapAllocator(), debugGetAllocatedMemoryByCategory(), debugGetLBDebugInfoSize(), debugGetSBDebugInfoSize(), freeAll(), getAllocatedMemory(), getFragmentationRatio(), getFreeMemory(), getSmallBlockMemory(), getTotalMemoryUsed(), internalCheckHeap(), releaseMemory(), and setName().

void NLMISC::CHeapAllocator::leaveCriticalSectionLB  )  const [private]
 

Referenced by free().

void NLMISC::CHeapAllocator::leaveCriticalSectionSB  )  const [private]
 

Referenced by free().

void NLMISC::CHeapAllocator::mergeNode CNodeBegin node  )  [inline, static, private]
 

Definition at line 527 of file misc/heap_allocator.cpp.

References getNextNode(), getNodeSize(), internalAssert, NL_HEAP_NODE_END_SIZE, NL_UPDATE_MAGIC_NUMBER, NLMISC::CHeapAllocator::CNodeBegin::Previous, setNodeLast(), setNodeSize(), uint32, and uint8.

Referenced by free().

00528 {
00529         // Get the previous node to merge with
00530         CNodeBegin *previous = node->Previous;
00531         internalAssert (getNextNode (previous) == node);
00532         internalAssert (previous);
00533         internalAssert (isNodeFree (previous));
00534 
00535         // New size
00536         setNodeSize (previous, getNodeSize (previous) + getNodeSize (node) + sizeof (CNodeBegin) + NL_HEAP_NODE_END_SIZE);
00537 
00538 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00539         // Set end pointers
00540         previous->EndMagicNumber = (uint32*)((uint8*)previous + getNodeSize (previous) + sizeof (CNodeBegin));
00541 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00542 
00543         // Get the next node to relink
00544         CNodeBegin *next = getNextNode (node);
00545         if (next)
00546         {
00547                 // Relink
00548                 next->Previous = previous;
00549 
00550                 NL_UPDATE_MAGIC_NUMBER (next);
00551         }
00552 
00553         // Get the last flag
00554         setNodeLast (previous, isNodeLast (node));
00555 
00556 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00557 
00558         // todo align
00559 
00560         // Clear the node informations
00561         memset (((uint8*)node + getNodeSize (node) + sizeof (CNodeBegin)), DeletedMemory, NL_HEAP_NODE_END_SIZE);
00562         memset (node, DeletedMemory, sizeof (CNodeBegin));
00563 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00564 }

void* NLMISC::CHeapAllocator::reallocate void *  ptr,
uint  size,
const char *  sourceFile,
uint  line,
const char *  category
 

void NLMISC::CHeapAllocator::releaseMemory  ) 
 

Definition at line 1879 of file misc/heap_allocator.cpp.

References enterCriticalSection(), freeBlock(), NLMISC::CHeapAllocator::CNullNode::FreeNode, leaveCriticalSection(), NLMISC::CHeapAllocator::CMainBlock::Next, and NLMISC::CHeapAllocator::CMainBlock::Ptr.

Referenced by ~CHeapAllocator().

01880 {
01881         enterCriticalSection ();
01882 
01883         // Clear the free tree
01884         _FreeTreeRoot = &_NullNode.FreeNode;
01885 
01886         // For each main block
01887         CMainBlock *currentBlock = _MainBlockList;
01888         while (currentBlock)
01889         {
01890                 freeBlock (currentBlock->Ptr);
01891 
01892                 // Next block
01893                 CMainBlock *toDelete = currentBlock;
01894                 currentBlock = toDelete->Next;
01895                 ::free (toDelete);
01896         }
01897 
01898         // Erase block node
01899         _MainBlockList = NULL;
01900 
01901         leaveCriticalSection ();
01902 }

void NLMISC::CHeapAllocator::rotateLeft CFreeNode x  )  [inline, private]
 

Referenced by erase(), and insert().

void NLMISC::CHeapAllocator::rotateRight CFreeNode x  )  [inline, private]
 

Referenced by erase(), and insert().

void NLMISC::CHeapAllocator::setBlockAllocationMode TBlockAllocationMode  mode  ) 
 

bool NLMISC::CHeapAllocator::setMainBlockCount uint  blockCount  ) 
 

bool NLMISC::CHeapAllocator::setMainBlockSize uint  mainBlockSize  ) 
 

void NLMISC::CHeapAllocator::setName const char *  name  ) 
 

Definition at line 2160 of file misc/heap_allocator.cpp.

References enterCriticalSection(), and leaveCriticalSection().

02161 {
02162         enterCriticalSection ();
02163 
02164         strncpy (_Name, name, NameLength-1);
02165 
02166         leaveCriticalSection ();
02167 }

void NLMISC::CHeapAllocator::setNextSmallBlock CNodeBegin previous,
CNodeBegin next
[static, private]
 

void NLMISC::CHeapAllocator::setNodeBlack CFreeNode current  )  [static, private]
 

Referenced by CHeapAllocator(), erase(), and insert().

void NLMISC::CHeapAllocator::setNodeColor CFreeNode current,
bool  red
[static, private]
 

Referenced by erase().

void NLMISC::CHeapAllocator::setNodeFree CNodeBegin current  )  [static, private]
 

Referenced by free(), initEmptyBlock(), and splitNode().

void NLMISC::CHeapAllocator::setNodeLast CNodeBegin current,
bool  last
[static, private]
 

Referenced by initEmptyBlock(), mergeNode(), and splitNode().

void NLMISC::CHeapAllocator::setNodeRed CFreeNode current  )  [static, private]
 

Referenced by erase(), and insert().

void NLMISC::CHeapAllocator::setNodeSize CNodeBegin current,
uint  size
[static, private]
 

Referenced by initEmptyBlock(), mergeNode(), and splitNode().

void NLMISC::CHeapAllocator::setNodeUsed CNodeBegin current  )  [static, private]
 

void NLMISC::CHeapAllocator::setOutOfMemoryMode TOutOfMemoryMode  mode  ) 
 

CHeapAllocator::CNodeBegin * NLMISC::CHeapAllocator::splitNode CNodeBegin node,
uint  newSize
[inline, private]
 

Definition at line 442 of file misc/heap_allocator.cpp.

References NLMISC::CHeapAllocator::CNodeBegin::BeginMarkers, NLMISC::CHeapAllocator::CNodeBegin::Category, NLMISC::CHeapAllocator::CNodeBegin::EndMagicNumber, NLMISC::CHeapAllocator::CNodeEnd::EndMarkers, NLMISC::CHeapAllocator::CNodeBegin::File, getNextNode(), getNodeSize(), NLMISC::CHeapAllocator::CNodeBegin::Heap, internalAssert, NLMISC::CHeapAllocator::CNodeBegin::Line, NL_HEAP_NODE_END_SIZE, NL_UPDATE_MAGIC_NUMBER, NLMISC::CHeapAllocator::CNodeBegin::Previous, setNodeFree(), setNodeLast(), setNodeSize(), uint, uint32, and uint8.

00443 {
00444         // Should be smaller than node size
00445         internalAssert (newSize <= getNodeSize (node));
00446 
00447         // Align size
00448         uint allignedSize = (newSize&~(Align-1)) + (( (newSize&(Align-1))==0 ) ? 0 : Align);
00449         if (allignedSize <= UserDataBlockSizeMin)
00450                 allignedSize = UserDataBlockSizeMin;
00451 
00452 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00453         // End magic number aligned on new size
00454         node->EndMagicNumber = (uint32*)((uint8*)node + newSize + sizeof (CNodeBegin));
00455 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00456 
00457         // Rest is empty ?
00458         if ( getNodeSize (node) - allignedSize < UserDataBlockSizeMin + sizeof (CNodeBegin) + NL_HEAP_NODE_END_SIZE )
00459                 // No split
00460                 return NULL;
00461 
00462         // New node begin structure
00463         CNodeBegin *newNode = (CNodeBegin*)((uint8*)node + sizeof (CNodeBegin) + allignedSize + NL_HEAP_NODE_END_SIZE );
00464 
00465         // Fill the new node header
00466 
00467         // Size
00468         setNodeSize (newNode, getNodeSize (node) - allignedSize - sizeof (CNodeBegin) - NL_HEAP_NODE_END_SIZE);
00469 
00470         // Set the node free
00471         setNodeFree (newNode);
00472 
00473         // Set the previous node pointer
00474         newNode->Previous = node;
00475 
00476         // Last flag
00477         setNodeLast (newNode, isNodeLast (node));
00478 
00479 #ifndef NLMISC_HEAP_ALLOCATION_NDEBUG
00480         // Begin markers
00481         memset (newNode->BeginMarkers, BeginNodeMarkers, CNodeBegin::MarkerSize-1);
00482         newNode->BeginMarkers[CNodeBegin::MarkerSize-1] = 0;
00483 
00484         // End pointer
00485         newNode->EndMagicNumber = (uint32*)((uint8*)newNode + getNodeSize (newNode) + sizeof (CNodeBegin));
00486 
00487         // End markers
00488         CNodeEnd *endNode = (CNodeEnd*)((uint8*)newNode + getNodeSize (newNode) + sizeof (CNodeBegin));
00489         memset (endNode->EndMarkers, EndNodeMarkers, CNodeEnd::MarkerSize-1);
00490         endNode->EndMarkers[CNodeEnd::MarkerSize-1] = 0;
00491 
00492         // No source informations
00493         newNode->File = NULL;
00494         newNode->Line = 0xffff;
00495         node->AllocateNumber = 0xffffffff;
00496         memset (newNode->Category, 0, CategoryStringLength);
00497 
00498         // Heap pointer
00499         newNode->Heap = this;
00500 #endif // NLMISC_HEAP_ALLOCATION_NDEBUG
00501 
00502         // Get next node
00503         CNodeBegin *next = getNextNode (node);
00504         if (next)
00505         {
00506                 // Set previous
00507                 next->Previous = newNode;
00508 
00509                 NL_UPDATE_MAGIC_NUMBER (next);
00510         }
00511 
00512         // Should be big enough
00513         internalAssert (getNodeSize (newNode) >= UserDataBlockSizeMin);
00514 
00515         // New size of the first node
00516         setNodeSize (node, allignedSize);
00517 
00518         // No more the last
00519         setNodeLast (node, false);
00520 
00521         // Return new node
00522         return newNode;
00523 }


Field Documentation

uint32 NLMISC::CHeapAllocator::_AllocateCount [private]
 

Definition at line 393 of file include/nel/misc/heap_allocator.h.

bool NLMISC::CHeapAllocator::_AlwaysCheck [private]
 

Definition at line 380 of file include/nel/misc/heap_allocator.h.

TBlockAllocationMode NLMISC::CHeapAllocator::_BlockAllocationMode [private]
 

Definition at line 377 of file include/nel/misc/heap_allocator.h.

uint NLMISC::CHeapAllocator::_BlockCount [private]
 

Definition at line 376 of file include/nel/misc/heap_allocator.h.

CTDS NLMISC::CHeapAllocator::_CategoryStack [private]
 

Definition at line 479 of file include/nel/misc/heap_allocator.h.

volatile CNodeBegin* NLMISC::CHeapAllocator::_FreeSmallBlocks[ (1+(LastSmallBlock - FirstSmallBlock)/SmallBlockGranularity) ] [private]
 

Definition at line 452 of file include/nel/misc/heap_allocator.h.

CFreeNode* NLMISC::CHeapAllocator::_FreeTreeRoot [private]
 

Definition at line 387 of file include/nel/misc/heap_allocator.h.

CMainBlock* NLMISC::CHeapAllocator::_MainBlockList [private]
 

Definition at line 384 of file include/nel/misc/heap_allocator.h.

uint NLMISC::CHeapAllocator::_MainBlockSize [private]
 

Definition at line 375 of file include/nel/misc/heap_allocator.h.

CAllocatorMutex NLMISC::CHeapAllocator::_MutexLB [mutable, private]
 

Definition at line 389 of file include/nel/misc/heap_allocator.h.

CAllocatorMutex NLMISC::CHeapAllocator::_MutexSB [mutable, private]
 

Definition at line 455 of file include/nel/misc/heap_allocator.h.

char NLMISC::CHeapAllocator::_Name[NameLength] [private]
 

Definition at line 391 of file include/nel/misc/heap_allocator.h.

CNullNode NLMISC::CHeapAllocator::_NullNode [private]
 

Definition at line 388 of file include/nel/misc/heap_allocator.h.

TOutOfMemoryMode NLMISC::CHeapAllocator::_OutOfMemoryMode [private]
 

Definition at line 378 of file include/nel/misc/heap_allocator.h.

volatile CSmallBlockPool* NLMISC::CHeapAllocator::_SmallBlockPool [private]
 

Definition at line 453 of file include/nel/misc/heap_allocator.h.


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 13:16:09 2004 for NeL by doxygen 1.3.6