# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

heap_allocator_inline.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #ifndef NL_HEAP_ALLOCATOR_INLINE_H
00027 #define NL_HEAP_ALLOCATOR_INLINE_H
00028 
00029 #ifdef NL_HEAP_ALLOCATOR_INTERNAL_CHECKS
00030 #define internalAssert(a) memory_assert(a)
00031 #else // NL_HEAP_ALLOCATOR_INTERNAL_CHECKS
00032 #define internalAssert(a) ((void)0)
00033 #endif // NL_HEAP_ALLOCATOR_INTERNAL_CHECKS
00034 
00035 #ifdef  NL_HEAP_ALLOCATION_NDEBUG
00036 
00037 #define NL_UPDATE_MAGIC_NUMBER(node) ((void)0)
00038 #define NL_UPDATE_MAGIC_NUMBER_FREE_NODE(node) ((void)0)
00039 
00040 #else // NL_HEAP_ALLOCATION_NDEBUG
00041 
00042 #define NL_UPDATE_MAGIC_NUMBER(node) {\
00043                 uint32 crc = evalMagicNumber (node);\
00044                 *(node->EndMagicNumber) = crc;\
00045         }
00046 
00047 #define NL_UPDATE_MAGIC_NUMBER_FREE_NODE(node) {\
00048                 if (node != &_NullNode.FreeNode) \
00049                 { \
00050                         uint32 crc = evalMagicNumber (getNode (node));\
00051                         *(getNode (node)->EndMagicNumber) = crc;\
00052                 } \
00053         }
00054 
00055 #endif // NL_HEAP_ALLOCATION_NDEBUG
00056 
00057 #if defined (NL_OS_WINDOWS)
00058 #define NL_ALLOC_STOP _asm { int 3 }
00059 #else
00060 #define NL_ALLOC_STOP abort()
00061 #endif
00062 
00063 // *********************************************************
00064 // Set / Get methods
00065 // *********************************************************
00066 
00067 inline bool     CHeapAllocator::isNodeFree              (const CNodeBegin *node)
00068 {
00069         return (node->SizeAndFlags & CNodeBegin::Free) != 0;
00070 }
00071 
00072 // *********************************************************
00073 
00074 inline bool     CHeapAllocator::isNodeUsed              (const CNodeBegin *node)
00075 {
00076         return (node->SizeAndFlags & CNodeBegin::Free) == 0;
00077 }
00078 
00079 // *********************************************************
00080 
00081 inline bool     CHeapAllocator::isNodeLast              (const CNodeBegin *node)
00082 {
00083         return (node->SizeAndFlags & CNodeBegin::Last) != 0;
00084 }
00085 
00086 // *********************************************************
00087 
00088 inline bool     CHeapAllocator::isNodeSmall             (const CNodeBegin *node)
00089 {
00090 #ifdef NL_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00091         return false;
00092 #else // NL_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00093         return getNodeSize (node) <= LastSmallBlock;
00094 #endif // NL_HEAP_NO_SMALL_BLOCK_OPTIMIZATION
00095 }
00096 
00097 // *********************************************************
00098 
00099 inline bool     CHeapAllocator::isNodeRed               (const CFreeNode *node)
00100 {
00101         return (node->Flags & CFreeNode::Red) != 0;
00102 }
00103 
00104 // *********************************************************
00105 
00106 inline bool     CHeapAllocator::isNodeBlack             (const CFreeNode *node)
00107 {
00108         return (node->Flags & CFreeNode::Red) == 0;
00109 }
00110 
00111 // *********************************************************
00112 
00113 inline void     CHeapAllocator::setNodeFree     (CNodeBegin *node)
00114 {
00115         node->SizeAndFlags |= CNodeBegin::Free;
00116 }
00117 
00118 // *********************************************************
00119 
00120 inline void     CHeapAllocator::setNodeUsed     (CNodeBegin *node)
00121 {
00122         node->SizeAndFlags &= ~CNodeBegin::Free;
00123 }
00124 
00125 // *********************************************************
00126 
00127 inline void     CHeapAllocator::setNodeLast     (CNodeBegin *node, bool last)
00128 {
00129         if (last)
00130                 node->SizeAndFlags |= CNodeBegin::Last;
00131         else
00132                 node->SizeAndFlags &= ~CNodeBegin::Last;
00133 }
00134 
00135 // *********************************************************
00136 
00137 inline void     CHeapAllocator::setNodeSize     (CNodeBegin *node, uint size)
00138 {
00139         // Size must be < 1 Go
00140         internalAssert ((size&0xc0000000) == 0);
00141 
00142         // Set the size
00143         node->SizeAndFlags &= ~CNodeBegin::SizeMask;
00144         node->SizeAndFlags |= size;
00145 }
00146 
00147 // *********************************************************
00148 
00149 inline void     CHeapAllocator::setNodeColor (CFreeNode *node, bool red)
00150 {
00151         if (red)
00152                 node->Flags |= CFreeNode::Red;
00153         else
00154                 node->Flags &= ~CFreeNode::Red;
00155 }
00156 
00157 // *********************************************************
00158 
00159 inline void     CHeapAllocator::setNodeRed (CFreeNode *node)
00160 {
00161         node->Flags |= CFreeNode::Red;
00162 }
00163 
00164 // *********************************************************
00165 
00166 inline void     CHeapAllocator::setNodeBlack (CFreeNode *node)
00167 {
00168         node->Flags &= ~CFreeNode::Red;
00169 }
00170 
00171 // *********************************************************
00172 // Free tree management
00173 // *********************************************************
00174 
00175 inline void CHeapAllocator::rotateLeft (CHeapAllocator::CFreeNode *x)
00176 {   
00177         // Rotate node x to left
00178 
00179         // Establish x->Right link
00180         CHeapAllocator::CFreeNode *y = x->Right;
00181         x->Right = y->Left;
00182         if (y->Left != &_NullNode.FreeNode) 
00183         {
00184                 y->Left->Parent = x;
00185                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Left);
00186         }
00187 
00188         // Establish y->Parent link
00189         if (y != &_NullNode.FreeNode) 
00190                 y->Parent = x->Parent;
00191 
00192         // x is the root ?
00193         if (x->Parent)
00194         {
00195                 // Link its parent to y
00196                 if (x == x->Parent->Left)
00197                         x->Parent->Left = y;
00198                 else
00199                 {
00200                         internalAssert (x == x->Parent->Right);
00201                         x->Parent->Right = y;
00202                 }
00203                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00204         }
00205         else
00206         {
00207                 internalAssert (x == _FreeTreeRoot);
00208                 _FreeTreeRoot = y;
00209         }
00210 
00211         // Link x and y
00212         y->Left = x;
00213         if (x != &_NullNode.FreeNode)
00214                 x->Parent = y;
00215         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x);
00216         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y);
00217 }
00218 
00219 // *********************************************************
00220 
00221 inline void CHeapAllocator::rotateRight (CHeapAllocator::CFreeNode *x)
00222 {
00223         // Rotate node x to right
00224 
00225         // Establish x->Left link
00226         CHeapAllocator::CFreeNode *y = x->Left;
00227         x->Left = y->Right;
00228         if (y->Right != &_NullNode.FreeNode)
00229         {
00230                 y->Right->Parent = x;
00231                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y->Right);
00232         }
00233 
00234         // Establish y->parent link
00235         if (y != &_NullNode.FreeNode)
00236                 y->Parent = x->Parent;
00237 
00238         // x is the root ?
00239         if (x->Parent)
00240         {
00241                 // Link its parent to y
00242                 if (x == x->Parent->Right)
00243                 {
00244                         x->Parent->Right = y;
00245                 }
00246                 else
00247                 {
00248                         internalAssert (x == x->Parent->Left);
00249                         x->Parent->Left = y;
00250                 }
00251                 NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x->Parent);
00252         } 
00253         else 
00254         {        
00255                 internalAssert (x == _FreeTreeRoot);
00256                 _FreeTreeRoot = y;
00257         }
00258 
00259     // Link x and y
00260         y->Right = x;    
00261         if (x != &_NullNode.FreeNode) 
00262                 x->Parent = y;
00263 
00264         // Crc
00265         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (x);
00266         NL_UPDATE_MAGIC_NUMBER_FREE_NODE (y);
00267 }
00268 
00269 // *********************************************************
00270 
00271 inline CHeapAllocator::CFreeNode *CHeapAllocator::find (uint size)
00272 {
00273         CHeapAllocator::CFreeNode       *current = _FreeTreeRoot;
00274         CHeapAllocator::CFreeNode       *smallest = NULL;
00275         while (current != &_NullNode.FreeNode)
00276         {
00277                 // Smaller than this node ?
00278                 if (size <= getNodeSize (getNode (current)))
00279                 {
00280                         // This is good
00281                         smallest = current;
00282 
00283                         // Go left
00284                         current = current->Left;
00285                 }
00286                 else
00287                 {
00288                         // Go right
00289                         current = current->Right;
00290                 }
00291         }
00292         return smallest;
00293 }
00294 
00295 // *********************************************************
00296 // Node methods
00297 // *********************************************************
00298 
00299 #ifndef NL_HEAP_ALLOCATION_NDEBUG
00300 
00301 inline void CHeapAllocator::computeCRC32(uint32 &crc, const void* buffer, unsigned int count)
00302 {
00303         internalAssert ( (count&3) == 0);
00304         count >>= 2;
00305         
00306         const uint32* ptr = (uint32*) buffer;
00307         while (count--)
00308         {
00309                 crc ^= *(ptr++);
00310         }
00311 /*      Real CRC, too slow
00312         
00313         const uint8* ptr = (uint8*) buffer;
00314         while (count--)
00315         {
00316                 uint8 value = *(ptr++);
00317                 crc ^= ((uint)value << 24);
00318                 for (int i = 0; i < 8; i++)
00319                 {
00320                         if (crc & 0x80000000)
00321                         {
00322                                 crc = (crc << 1) ^ 0x04C11DB7;
00323                         }
00324                         else
00325                         {
00326                                 crc <<= 1;
00327                         }
00328                 }
00329         }
00330 */
00331 }
00332 
00333 #endif // NL_HEAP_ALLOCATION_NDEBUG
00334 
00335 // *********************************************************
00336 
00337 inline const CHeapAllocator::CNodeBegin *CHeapAllocator::getFirstNode (const CMainBlock *mainBlock)
00338 {
00339         // Align the node pointer
00340         return (CNodeBegin*)(((uint32)mainBlock->Ptr&~(Align-1)) + ((((uint32)mainBlock->Ptr&(Align-1))==0)? 0 : Align));
00341 }
00342 
00343 // *********************************************************
00344 
00345 inline CHeapAllocator::CNodeBegin *CHeapAllocator::getFirstNode (CMainBlock *mainBlock)
00346 {
00347         // todo align
00348         return (CNodeBegin*)(((uint32)mainBlock->Ptr&~(Align-1)) + ((((uint32)mainBlock->Ptr&(Align-1))==0)? 0 : Align));
00349 }
00350 
00351 // *********************************************************
00352 
00353 inline const CHeapAllocator::CNodeBegin *CHeapAllocator::getNextNode (const CNodeBegin *current)
00354 {
00355         // Last ?
00356         if (isNodeLast (current))
00357                 return NULL;
00358 
00359         // todo align
00360         return (const CNodeBegin*)((uint8*)current + sizeof (CNodeBegin) + NL_HEAP_NODE_END_SIZE + getNodeSize (current) );
00361 }
00362 
00363 // *********************************************************
00364 
00365 inline CHeapAllocator::CNodeBegin *CHeapAllocator::getNextNode (CNodeBegin *current)
00366 {
00367         // Last ?
00368         if (isNodeLast (current))
00369                 return NULL;
00370 
00371         // todo align
00372         return (CNodeBegin*)((uint8*)current + sizeof (CNodeBegin) + NL_HEAP_NODE_END_SIZE + getNodeSize (current) );
00373 }
00374 
00375 // *********************************************************
00376 
00377 inline const CHeapAllocator::CFreeNode *CHeapAllocator::getFreeNode     (const CNodeBegin *current)
00378 {
00379         return (const CHeapAllocator::CFreeNode *)((uint8*)current + sizeof(CNodeBegin));
00380 }
00381 
00382 // *********************************************************
00383 
00384 inline CHeapAllocator::CFreeNode *CHeapAllocator::getFreeNode (CNodeBegin *current)
00385 {
00386         return (CHeapAllocator::CFreeNode *)((uint8*)current + sizeof(CNodeBegin));
00387 }
00388 
00389 // *********************************************************
00390 
00391 inline const CHeapAllocator::CNodeBegin *CHeapAllocator::getNode (const CFreeNode *current)
00392 {
00393         return (const CHeapAllocator::CNodeBegin *)((uint8*)current - sizeof(CNodeBegin));
00394 }
00395 
00396 // *********************************************************
00397 
00398 inline CHeapAllocator::CNodeBegin *CHeapAllocator::getNode (CFreeNode *current)
00399 {
00400         return (CHeapAllocator::CNodeBegin *)((uint8*)current - sizeof(CNodeBegin));
00401 }
00402 
00403 // *********************************************************
00404 
00405 inline uint CHeapAllocator::getNodeSize (const CNodeBegin *current)
00406 {
00407         return current->SizeAndFlags & CNodeBegin::SizeMask;
00408 }
00409 
00410 // *********************************************************
00411 
00412 #ifndef NL_HEAP_ALLOCATION_NDEBUG
00413 
00414 inline uint32 CHeapAllocator::evalMagicNumber (const CNodeBegin *node)
00415 {
00416         uint32 crc = (uint32)node;
00417 
00418         // Make the CRC of the rest of the node header
00419         computeCRC32 (crc, node, sizeof(CNodeBegin));
00420 
00421         // If the node is free and LARGE, crc the free tree node
00422         if ( isNodeFree (node) && !isNodeSmall (node) )
00423                 computeCRC32 (crc, getFreeNode (node), sizeof(CFreeNode));
00424 
00425         // Return the magic number
00426         return crc;
00427 }
00428 
00429 #endif // NL_HEAP_ALLOCATION_NDEBUG
00430 
00431 // *********************************************************
00432 // Integrity checks
00433 // *********************************************************
00434 
00435 inline bool CHeapAllocator::checkNodeSB (const CSmallBlockPool *mainBlock, const CNodeBegin *previous, const CNodeBegin *current, const CNodeBegin *next, bool stopOnError) const
00436 {
00437 #ifndef NL_HEAP_ALLOCATION_NDEBUG
00438         // Get the theorical CRC check
00439         uint32 crc = evalMagicNumber (current);
00440 
00441         // Compare the magic number
00442         if (*(current->EndMagicNumber) != crc)
00443         {
00444                 // Stop on error ?
00445                 if (stopOnError)
00446                 {
00447                         // ********
00448                         // * STOP *
00449                         // ********
00450                         // * The bottom CRC32 of the current node is wrong: Check if a node has overflowed. Node by top and bottom,
00451                         // * the next by the top and the previous by the bottom.
00452                         // * overflow or the next node by the top.
00453                         // ********
00454                         // * (*previous):       previous node
00455                         // * (*current):        current node
00456                         // * (*next):           next node
00457                         // ********
00458                         NL_ALLOC_STOP;
00459                 }
00460 
00461                 // CRC is wrong
00462                 return false;
00463         }
00464 #endif // NL_HEAP_ALLOCATION_NDEBUG
00465 
00466         // *** Release node control
00467 
00468         // Check node
00469         if      (
00470                         ( (uint)current < ((uint)mainBlock) + sizeof (CSmallBlockPool)) ||
00471                         ( (uint)current + getNodeSize (current) + sizeof(CNodeBegin) + NL_HEAP_NODE_END_SIZE >
00472                                 ((uint)mainBlock) + sizeof (CSmallBlockPool) + SmallBlockPoolSize * (sizeof(CNodeBegin)+ mainBlock->Size  + NL_HEAP_NODE_END_SIZE) )
00473                 )
00474         {
00475                 // Stop on error ?
00476                 if (stopOnError)
00477                 {
00478                         // ********
00479                         // * STOP *
00480                         // ********
00481                         // * The size value is corrupted: Check if the current node has
00482                         // * overflow by the top or the previous node by the bottom.
00483                         // ********
00484                         // * (*previous):       previous node
00485                         // * (*current):        current node
00486                         // * (*next):           next node
00487                         // ********
00488                         NL_ALLOC_STOP;
00489                 }
00490 
00491                 // Node size is corrupted
00492                 return false;
00493         }
00494 
00495         // Ok
00496         return true;
00497 }
00498 
00499 // *********************************************************
00500 
00501 inline bool CHeapAllocator::checkNodeLB (const CMainBlock *mainBlock, const CNodeBegin *previous, const CNodeBegin *current, const CNodeBegin *next, bool stopOnError) const
00502 {
00503 #ifndef NL_HEAP_ALLOCATION_NDEBUG
00504         // Get the theorical CRC check
00505         uint32 crc = evalMagicNumber (current);
00506 
00507         // Compare the magic number
00508         if (*(current->EndMagicNumber) != crc)
00509         {
00510                 // Stop on error ?
00511                 if (stopOnError)
00512                 {
00513                         // ********
00514                         // * STOP *
00515                         // ********
00516                         // * The bottom CRC32 of the current node is wrong: Check if a node has overflowed. Node by top and bottom,
00517                         // * the next by the top and the previous by the bottom.
00518                         // * overflow or the next node by the top.
00519                         // ********
00520                         // * (*previous):       previous node
00521                         // * (*current):        current node
00522                         // * (*next):           next node
00523                         // ********
00524                         NL_ALLOC_STOP;
00525                 }
00526 
00527                 // CRC is wrong
00528                 return false;
00529         }
00530 #endif // NL_HEAP_ALLOCATION_NDEBUG
00531 
00532         // *** Release node control
00533 
00534         // Check node
00535         if      (
00536                         ( (uint)current < (uint)mainBlock->Ptr ) ||
00537                         ( (uint)current + getNodeSize (current) + sizeof(CNodeBegin) + NL_HEAP_NODE_END_SIZE > 
00538                                 (uint)mainBlock->Ptr + mainBlock->Size )
00539                 )
00540         {
00541                 // Stop on error ?
00542                 if (stopOnError)
00543                 {
00544                         // ********
00545                         // * STOP *
00546                         // ********
00547                         // * The size value is corrupted: Check if the current node has
00548                         // * overflow by the top or the previous node by the bottom.
00549                         // ********
00550                         // * (*previous):       previous node
00551                         // * (*current):        current node
00552                         // * (*next):           next node
00553                         // ********
00554                         NL_ALLOC_STOP;
00555                 }
00556 
00557                 // Node size is corrupted
00558                 return false;
00559         }
00560 
00561         // Check Previous node pointer
00562         if ( !(current->Previous == NULL || 
00563                 ( ((uint)current->Previous <= (uint)current - sizeof (CNodeBegin) - NL_HEAP_NODE_END_SIZE) && 
00564                 ((uint)current->Previous >= (uint)mainBlock->Ptr) )
00565                 ) )
00566         {
00567                 // Stop on error ?
00568                 if (stopOnError)
00569                 {
00570                         // ********
00571                         // * STOP *
00572                         // ********
00573                         // * The previous value is corrupted: Check if the current node has
00574                         // * overflow by the top or the previous node by the bottom.
00575                         // ********
00576                         // * (*previous):       previous node
00577                         // * (*current):        current node
00578                         // * (*next):           next node
00579                         // ********
00580                         NL_ALLOC_STOP;
00581                 }
00582 
00583                 // Node flag is corrupted
00584                 return false;
00585         }
00586 
00587         // Check FreeNode node pointer
00588         if (isNodeFree (current))
00589         {
00590                 // Get only this free node
00591                 const CFreeNode *freeNode = getFreeNode (current);
00592                 checkFreeNode (freeNode, stopOnError, false);
00593         }
00594 
00595         // Ok
00596         return true;
00597 }
00598 
00599 // *********************************************************
00600 
00601 inline bool CHeapAllocator::checkFreeNode (const CFreeNode *current, bool stopOnError, bool recurse) const
00602 {
00603         // Not NULL ?
00604         if (current != &_NullNode.FreeNode)
00605         {
00606                 // Get the node
00607                 const CNodeBegin *node = getNode (current);
00608 
00609                 // 1st rule: Node must be free
00610                 if ( !isNodeFree(node) )
00611                 {
00612                         // Stop on error ?
00613                         if (stopOnError)
00614                         {
00615                                 // ********
00616                                 // * STOP *
00617                                 // ********
00618                                 // * Node should be free : Free tree is corrupted.
00619                                 // ********
00620                                 NL_ALLOC_STOP;
00621                         }
00622 
00623                         // Node Color is corrupted
00624                         return false;
00625                 }
00626                 
00627                 // 2nd rule: Node must be sorted 
00628                 if      ( 
00629                                 ( current->Left != &_NullNode.FreeNode && getNodeSize (getNode (current->Left)) > getNodeSize (node) ) ||
00630                                 ( current->Right != &_NullNode.FreeNode && getNodeSize (getNode (current->Right)) < getNodeSize (node) )
00631                         )
00632                 {
00633                         // Stop on error ?
00634                         if (stopOnError)
00635                         {
00636                                 // ********
00637                                 // * STOP *
00638                                 // ********
00639                                 // * Node order is corrupted: Free tree is corrupted.
00640                                 // ********
00641                                 NL_ALLOC_STOP;
00642                         }
00643 
00644                         // Node Data is corrupted
00645                         return false;
00646                 }
00647                 
00648                 // 3rd rule: if red, must have two black nodes
00649                 bool leftBlack = (current->Left == &_NullNode.FreeNode) || isNodeBlack(current->Left);
00650                 bool rightBlack = (current->Right == &_NullNode.FreeNode) || isNodeBlack(current->Right);
00651                 if ( !leftBlack && !rightBlack && isNodeRed (getFreeNode (node)) )
00652                 {
00653                         // Stop on error ?
00654                         if (stopOnError)
00655                         {
00656                                 // ********
00657                                 // * STOP *
00658                                 // ********
00659                                 // * Color is corrupted: Free tree is corrupted.
00660                                 // ********
00661                                 NL_ALLOC_STOP;
00662                         }
00663 
00664                         // Node Color is corrupted
00665                         return false;
00666                 }
00667 
00668                 // If Parent NULL, must be the root
00669                 if ( ( (current->Parent == NULL) && (_FreeTreeRoot != current) ) || ( (current->Parent != NULL) && (_FreeTreeRoot == current) ) )
00670                 {
00671                         // Stop on error ?
00672                         if (stopOnError)
00673                         {
00674                                 // ********
00675                                 // * STOP *
00676                                 // ********
00677                                 // * Parent pointer corrupted: Free tree is corrupted.
00678                                 // ********
00679                                 NL_ALLOC_STOP;
00680                         }
00681 
00682                         // Node Parent is corrupted
00683                         return false;
00684                 }
00685 
00686                 // Recuse childern
00687                 if (recurse)
00688                 {
00689                         if (!checkFreeNode (current->Left, stopOnError, recurse))
00690                                 return false;
00691                         if (!checkFreeNode (current->Right, stopOnError, recurse))
00692                                 return false;
00693                 }
00694         }
00695 
00696         // Ok
00697         return true;
00698 }
00699 
00700 // *********************************************************
00701 // Synchronisation methods
00702 // *********************************************************
00703 
00704 inline void CHeapAllocator::enterCriticalSectionSB () const
00705 {
00706         _MutexSB.enter ();
00707 }
00708 
00709 // *********************************************************
00710 
00711 inline void CHeapAllocator::leaveCriticalSectionSB () const
00712 {
00713         _MutexSB.leave ();
00714 }
00715 
00716 // *********************************************************
00717 
00718 inline void CHeapAllocator::enterCriticalSectionLB () const
00719 {
00720         _MutexLB.enter ();
00721 }
00722 
00723 // *********************************************************
00724 
00725 inline void CHeapAllocator::leaveCriticalSectionLB () const
00726 {
00727         _MutexLB.leave ();
00728 }
00729 
00730 // *********************************************************
00731 
00732 inline void CHeapAllocator::enterCriticalSection () const
00733 {
00734         enterCriticalSectionSB ();
00735         enterCriticalSectionLB ();
00736 }
00737 
00738 // *********************************************************
00739 
00740 inline void CHeapAllocator::leaveCriticalSection () const
00741 {
00742         leaveCriticalSectionLB ();
00743         leaveCriticalSectionSB ();
00744 }
00745 
00746 // *********************************************************
00747 
00748 
00749 
00750 
00751 
00752 
00753 // *********************************************************
00754 // *********************************************************
00755 
00756 // Synchronized methods
00757 
00758 // *********************************************************
00759 // *********************************************************
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 // *********************************************************
00768 
00769 inline uint CHeapAllocator::getMainBlockCount () const
00770 {
00771         uint count = 0;
00772         CMainBlock *currentBlock = _MainBlockList;
00773         while (currentBlock)
00774         {
00775                 currentBlock = currentBlock->Next;
00776                 count++;
00777         }
00778         return count;
00779 }
00780 
00781 // *********************************************************
00782 // Debug functions
00783 // *********************************************************
00784 
00785 #ifndef NL_HEAP_ALLOCATION_NDEBUG
00786 
00787 /*inline void CHeapAllocator::debugAddBreakpoint (uint32 allocateNumber)
00788 {
00789         _Breakpoints.insert (allocateNumber);
00790 }*/
00791 
00792 // *********************************************************
00793 
00794 /*inline void CHeapAllocator::debugRemoveBreakpoints ()
00795 {
00796         _Breakpoints.clear ();
00797 }*/
00798 
00799 #endif // NL_HEAP_ALLOCATION_NDEBUG
00800 
00801 // *********************************************************
00802 
00803 inline void     CHeapAllocator::setOutOfMemoryMode (TOutOfMemoryMode mode)
00804 {
00805         enterCriticalSection ();
00806 
00807         _OutOfMemoryMode = mode;
00808 
00809         leaveCriticalSection ();
00810 }
00811 
00812 // *********************************************************
00813 
00814 inline CHeapAllocator::TOutOfMemoryMode CHeapAllocator::getOutOfMemoryMode () const
00815 {
00816         return _OutOfMemoryMode;
00817 }
00818 
00819 // *********************************************************
00820 
00821 inline void     CHeapAllocator::setBlockAllocationMode (TBlockAllocationMode mode)
00822 {
00823         enterCriticalSection ();
00824 
00825         _BlockAllocationMode = mode;
00826 
00827         leaveCriticalSection ();
00828 }
00829 
00830 // *********************************************************
00831 
00832 inline CHeapAllocator::TBlockAllocationMode     CHeapAllocator::getBlockAllocationMode () const
00833 {
00834         return _BlockAllocationMode;
00835 }
00836 
00837 // *********************************************************
00838 
00839 
00840 inline const char *CHeapAllocator::getName () const
00841 {
00842         return _Name;
00843 }
00844 
00845 // *********************************************************
00846 
00847 inline uint CHeapAllocator::getMainBlockSize () const
00848 {
00849         return _MainBlockSize;
00850 }
00851 
00852 
00853 // *********************************************************
00854 // Small Block
00855 // *********************************************************
00856 
00857 inline CHeapAllocator::CNodeBegin *CHeapAllocator::getSmallBlock (CHeapAllocator::CSmallBlockPool *smallBlock, uint blockIndex)
00858 {
00859         return (CHeapAllocator::CNodeBegin*)((uint8*)smallBlock + sizeof (CSmallBlockPool) + blockIndex * (sizeof(CNodeBegin) + smallBlock->Size + NL_HEAP_NODE_END_SIZE) );
00860 }
00861 
00862 // *********************************************************
00863 
00864 inline CHeapAllocator::CNodeBegin *CHeapAllocator::getNextSmallBlock (CNodeBegin *previous)
00865 {
00866         return previous->Previous;
00867 }
00868 
00869 // *********************************************************
00870 
00871 inline void CHeapAllocator::setNextSmallBlock (CNodeBegin *previous, CNodeBegin *next)
00872 {
00873         previous->Previous = next;
00874 }
00875 
00876 // *********************************************************
00877 
00878 /*
00879 void                                    *reallocate (void *ptr, uint size, const char *sourceFile, uint line, const char *category);
00880 void                                    freeAll ();
00881 void                                    releaseMemory ();
00882 void                                    setMainBlockSize (uint mainBlockSize);
00883 uint                                    getMainBlockSize () const;
00884 bool                                    setMainBlockCount (uint blockCount);
00885 uint                                    debugGetDebugInfoSize () const;
00886 uint                                    debugGetAllocatedMemoryByCatgegory (const char* category) const;
00887 void                                    debugReportMemoryLeak (std::vector<CMemoryLeakBlock> &result);
00888 */
00889 
00890 #endif // NL_HEAP_ALLOCATOR_H