doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Heap.h
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #ifndef __HEAP_H__
30 #define __HEAP_H__
31 
32 /*
33 ===============================================================================
34 
35  Memory Management
36 
37  This is a replacement for the compiler heap code (i.e. "C" malloc() and
38  free() calls). On average 2.5-3.0 times faster than MSVC malloc()/free().
39  Worst case performance is 1.65 times faster and best case > 70 times.
40 
41 ===============================================================================
42 */
43 
44 
45 typedef struct {
46  int num;
47  int minSize;
48  int maxSize;
49  int totalSize;
51 
52 
53 void Mem_Init( void );
54 void Mem_Shutdown( void );
55 void Mem_EnableLeakTest( const char *name );
56 void Mem_ClearFrameStats( void );
57 void Mem_GetFrameStats( memoryStats_t &allocs, memoryStats_t &frees );
58 void Mem_GetStats( memoryStats_t &stats );
59 void Mem_Dump_f( const class idCmdArgs &args );
60 void Mem_DumpCompressed_f( const class idCmdArgs &args );
61 void Mem_AllocDefragBlock( void );
62 
63 
64 #ifndef ID_DEBUG_MEMORY
65 
66 void * Mem_Alloc( const int size );
67 void * Mem_ClearedAlloc( const int size );
68 void Mem_Free( void *ptr );
69 char * Mem_CopyString( const char *in );
70 void * Mem_Alloc16( const int size );
71 void Mem_Free16( void *ptr );
72 
73 #ifdef ID_REDIRECT_NEWDELETE
74 
75 __inline void *operator new( size_t s ) {
76  return Mem_Alloc( s );
77 }
78 __inline void operator delete( void *p ) {
79  Mem_Free( p );
80 }
81 __inline void *operator new[]( size_t s ) {
82  return Mem_Alloc( s );
83 }
84 __inline void operator delete[]( void *p ) {
85  Mem_Free( p );
86 }
87 
88 #endif
89 
90 #else /* ID_DEBUG_MEMORY */
91 
92 void * Mem_Alloc( const int size, const char *fileName, const int lineNumber );
93 void * Mem_ClearedAlloc( const int size, const char *fileName, const int lineNumber );
94 void Mem_Free( void *ptr, const char *fileName, const int lineNumber );
95 char * Mem_CopyString( const char *in, const char *fileName, const int lineNumber );
96 void * Mem_Alloc16( const int size, const char *fileName, const int lineNumber );
97 void Mem_Free16( void *ptr, const char *fileName, const int lineNumber );
98 
99 #ifdef ID_REDIRECT_NEWDELETE
100 
101 __inline void *operator new( size_t s, int t1, int t2, char *fileName, int lineNumber ) {
102  return Mem_Alloc( s, fileName, lineNumber );
103 }
104 __inline void operator delete( void *p, int t1, int t2, char *fileName, int lineNumber ) {
105  Mem_Free( p, fileName, lineNumber );
106 }
107 __inline void *operator new[]( size_t s, int t1, int t2, char *fileName, int lineNumber ) {
108  return Mem_Alloc( s, fileName, lineNumber );
109 }
110 __inline void operator delete[]( void *p, int t1, int t2, char *fileName, int lineNumber ) {
111  Mem_Free( p, fileName, lineNumber );
112 }
113 __inline void *operator new( size_t s ) {
114  return Mem_Alloc( s, "", 0 );
115 }
116 __inline void operator delete( void *p ) {
117  Mem_Free( p, "", 0 );
118 }
119 __inline void *operator new[]( size_t s ) {
120  return Mem_Alloc( s, "", 0 );
121 }
122 __inline void operator delete[]( void *p ) {
123  Mem_Free( p, "", 0 );
124 }
125 
126 #define ID_DEBUG_NEW new( 0, 0, __FILE__, __LINE__ )
127 #undef new
128 #define new ID_DEBUG_NEW
129 
130 #endif
131 
132 #define Mem_Alloc( size ) Mem_Alloc( size, __FILE__, __LINE__ )
133 #define Mem_ClearedAlloc( size ) Mem_ClearedAlloc( size, __FILE__, __LINE__ )
134 #define Mem_Free( ptr ) Mem_Free( ptr, __FILE__, __LINE__ )
135 #define Mem_CopyString( s ) Mem_CopyString( s, __FILE__, __LINE__ )
136 #define Mem_Alloc16( size ) Mem_Alloc16( size, __FILE__, __LINE__ )
137 #define Mem_Free16( ptr ) Mem_Free16( ptr, __FILE__, __LINE__ )
138 
139 #endif /* ID_DEBUG_MEMORY */
140 
141 
142 /*
143 ===============================================================================
144 
145  Block based allocator for fixed size objects.
146 
147  All objects of the 'type' are properly constructed.
148  However, the constructor is not called for re-used objects.
149 
150 ===============================================================================
151 */
152 
153 template<class type, int blockSize>
155 public:
156  idBlockAlloc( void );
157  ~idBlockAlloc( void );
158 
159  void Shutdown( void );
160 
161  type * Alloc( void );
162  void Free( type *element );
163 
164  int GetTotalCount( void ) const { return total; }
165  int GetAllocCount( void ) const { return active; }
166  int GetFreeCount( void ) const { return total - active; }
167 
168 private:
169  typedef struct element_s {
170  struct element_s * next;
172  } element_t;
173  typedef struct block_s {
174  element_t elements[blockSize];
175  struct block_s * next;
176  } block_t;
177 
180  int total;
181  int active;
182 };
183 
184 template<class type, int blockSize>
186  blocks = NULL;
187  free = NULL;
188  total = active = 0;
189 }
190 
191 template<class type, int blockSize>
193  Shutdown();
194 }
195 
196 template<class type, int blockSize>
198  if ( !free ) {
199  block_t *block = new block_t;
200  block->next = blocks;
201  blocks = block;
202  for ( int i = 0; i < blockSize; i++ ) {
203  block->elements[i].next = free;
204  free = &block->elements[i];
205  }
206  total += blockSize;
207  }
208  active++;
209  element_t *element = free;
210  free = free->next;
211  element->next = NULL;
212  return &element->t;
213 }
214 
215 template<class type, int blockSize>
217  element_t *element = (element_t *)( ( (unsigned char *) t ) - ( (int) &((element_t *)0)->t ) );
218  element->next = free;
219  free = element;
220  active--;
221 }
222 
223 template<class type, int blockSize>
225  while( blocks ) {
226  block_t *block = blocks;
227  blocks = blocks->next;
228  delete block;
229  }
230  blocks = NULL;
231  free = NULL;
232  total = active = 0;
233 }
234 
235 /*
236 ==============================================================================
237 
238  Dynamic allocator, simple wrapper for normal allocations which can
239  be interchanged with idDynamicBlockAlloc.
240 
241  No constructor is called for the 'type'.
242  Allocated blocks are always 16 byte aligned.
243 
244 ==============================================================================
245 */
246 
247 template<class type, int baseBlockSize, int minBlockSize>
249 public:
250  idDynamicAlloc( void );
251  ~idDynamicAlloc( void );
252 
253  void Init( void );
254  void Shutdown( void );
255  void SetFixedBlocks( int numBlocks ) {}
256  void SetLockMemory( bool lock ) {}
257  void FreeEmptyBaseBlocks( void ) {}
258 
259  type * Alloc( const int num );
260  type * Resize( type *ptr, const int num );
261  void Free( type *ptr );
262  const char * CheckMemory( const type *ptr ) const;
263 
264  int GetNumBaseBlocks( void ) const { return 0; }
265  int GetBaseBlockMemory( void ) const { return 0; }
266  int GetNumUsedBlocks( void ) const { return numUsedBlocks; }
267  int GetUsedBlockMemory( void ) const { return usedBlockMemory; }
268  int GetNumFreeBlocks( void ) const { return 0; }
269  int GetFreeBlockMemory( void ) const { return 0; }
270  int GetNumEmptyBaseBlocks( void ) const { return 0; }
271 
272 private:
273  int numUsedBlocks; // number of used blocks
274  int usedBlockMemory; // total memory in used blocks
275 
278  int numFrees;
279 
280  void Clear( void );
281 };
282 
283 template<class type, int baseBlockSize, int minBlockSize>
285  Clear();
286 }
287 
288 template<class type, int baseBlockSize, int minBlockSize>
290  Shutdown();
291 }
292 
293 template<class type, int baseBlockSize, int minBlockSize>
295 }
296 
297 template<class type, int baseBlockSize, int minBlockSize>
299  Clear();
300 }
301 
302 template<class type, int baseBlockSize, int minBlockSize>
304  numAllocs++;
305  if ( num <= 0 ) {
306  return NULL;
307  }
308  numUsedBlocks++;
309  usedBlockMemory += num * sizeof( type );
310  return Mem_Alloc16( num * sizeof( type ) );
311 }
312 
313 template<class type, int baseBlockSize, int minBlockSize>
315 
316  numResizes++;
317 
318  if ( ptr == NULL ) {
319  return Alloc( num );
320  }
321 
322  if ( num <= 0 ) {
323  Free( ptr );
324  return NULL;
325  }
326 
327  assert( 0 );
328  return ptr;
329 }
330 
331 template<class type, int baseBlockSize, int minBlockSize>
333  numFrees++;
334  if ( ptr == NULL ) {
335  return;
336  }
337  Mem_Free16( ptr );
338 }
339 
340 template<class type, int baseBlockSize, int minBlockSize>
342  return NULL;
343 }
344 
345 template<class type, int baseBlockSize, int minBlockSize>
347  numUsedBlocks = 0;
348  usedBlockMemory = 0;
349  numAllocs = 0;
350  numResizes = 0;
351  numFrees = 0;
352 }
353 
354 
355 /*
356 ==============================================================================
357 
358  Fast dynamic block allocator.
359 
360  No constructor is called for the 'type'.
361  Allocated blocks are always 16 byte aligned.
362 
363 ==============================================================================
364 */
365 
366 #include "containers/BTree.h"
367 
368 //#define DYNAMIC_BLOCK_ALLOC_CHECK
369 
370 template<class type>
372 public:
373  type * GetMemory( void ) const { return (type *)( ( (byte *) this ) + sizeof( idDynamicBlock<type> ) ); }
374  int GetSize( void ) const { return abs( size ); }
375  void SetSize( int s, bool isBaseBlock ) { size = isBaseBlock ? -s : s; }
376  bool IsBaseBlock( void ) const { return ( size < 0 ); }
377 
378 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
379  int id[3];
380  void * allocator;
381 #endif
382 
383  int size; // size in bytes of the block
384  idDynamicBlock<type> * prev; // previous memory block
385  idDynamicBlock<type> * next; // next memory block
386  idBTreeNode<idDynamicBlock<type>,int> *node; // node in the B-Tree with free blocks
387 };
388 
389 template<class type, int baseBlockSize, int minBlockSize>
391 public:
392  idDynamicBlockAlloc( void );
393  ~idDynamicBlockAlloc( void );
394 
395  void Init( void );
396  void Shutdown( void );
397  void SetFixedBlocks( int numBlocks );
398  void SetLockMemory( bool lock );
399  void FreeEmptyBaseBlocks( void );
400 
401  type * Alloc( const int num );
402  type * Resize( type *ptr, const int num );
403  void Free( type *ptr );
404  const char * CheckMemory( const type *ptr ) const;
405 
406  int GetNumBaseBlocks( void ) const { return numBaseBlocks; }
407  int GetBaseBlockMemory( void ) const { return baseBlockMemory; }
408  int GetNumUsedBlocks( void ) const { return numUsedBlocks; }
409  int GetUsedBlockMemory( void ) const { return usedBlockMemory; }
410  int GetNumFreeBlocks( void ) const { return numFreeBlocks; }
411  int GetFreeBlockMemory( void ) const { return freeBlockMemory; }
412  int GetNumEmptyBaseBlocks( void ) const;
413 
414 private:
415  idDynamicBlock<type> * firstBlock; // first block in list in order of increasing address
416  idDynamicBlock<type> * lastBlock; // last block in list in order of increasing address
417  idBTree<idDynamicBlock<type>,int,4>freeTree; // B-Tree with free memory blocks
418  bool allowAllocs; // allow base block allocations
419  bool lockMemory; // lock memory so it cannot get swapped out
420 
421 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
422  int blockId[3];
423 #endif
424 
425  int numBaseBlocks; // number of base blocks
426  int baseBlockMemory; // total memory in base blocks
427  int numUsedBlocks; // number of used blocks
428  int usedBlockMemory; // total memory in used blocks
429  int numFreeBlocks; // number of free blocks
430  int freeBlockMemory; // total memory in free blocks
431 
434  int numFrees;
435 
436  void Clear( void );
437  idDynamicBlock<type> * AllocInternal( const int num );
438  idDynamicBlock<type> * ResizeInternal( idDynamicBlock<type> *block, const int num );
439  void FreeInternal( idDynamicBlock<type> *block );
440  void LinkFreeInternal( idDynamicBlock<type> *block );
442  void CheckMemory( void ) const;
443 };
444 
445 template<class type, int baseBlockSize, int minBlockSize>
447  Clear();
448 }
449 
450 template<class type, int baseBlockSize, int minBlockSize>
452  Shutdown();
453 }
454 
455 template<class type, int baseBlockSize, int minBlockSize>
457  freeTree.Init();
458 }
459 
460 template<class type, int baseBlockSize, int minBlockSize>
462  idDynamicBlock<type> *block;
463 
464  for ( block = firstBlock; block != NULL; block = block->next ) {
465  if ( block->node == NULL ) {
466  FreeInternal( block );
467  }
468  }
469 
470  for ( block = firstBlock; block != NULL; block = firstBlock ) {
471  firstBlock = block->next;
472  assert( block->IsBaseBlock() );
473  if ( lockMemory ) {
474  idLib::sys->UnlockMemory( block, block->GetSize() + (int)sizeof( idDynamicBlock<type> ) );
475  }
476  Mem_Free16( block );
477  }
478 
479  freeTree.Shutdown();
480 
481  Clear();
482 }
483 
484 template<class type, int baseBlockSize, int minBlockSize>
486  idDynamicBlock<type> *block;
487 
488  for ( int i = numBaseBlocks; i < numBlocks; i++ ) {
489  block = ( idDynamicBlock<type> * ) Mem_Alloc16( baseBlockSize );
490  if ( lockMemory ) {
491  idLib::sys->LockMemory( block, baseBlockSize );
492  }
493 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
494  memcpy( block->id, blockId, sizeof( block->id ) );
495  block->allocator = (void*)this;
496 #endif
497  block->SetSize( baseBlockSize - (int)sizeof( idDynamicBlock<type> ), true );
498  block->next = NULL;
499  block->prev = lastBlock;
500  if ( lastBlock ) {
501  lastBlock->next = block;
502  } else {
503  firstBlock = block;
504  }
505  lastBlock = block;
506  block->node = NULL;
507 
508  FreeInternal( block );
509 
510  numBaseBlocks++;
511  baseBlockMemory += baseBlockSize;
512  }
513 
514  allowAllocs = false;
515 }
516 
517 template<class type, int baseBlockSize, int minBlockSize>
519  lockMemory = lock;
520 }
521 
522 template<class type, int baseBlockSize, int minBlockSize>
524  idDynamicBlock<type> *block, *next;
525 
526  for ( block = firstBlock; block != NULL; block = next ) {
527  next = block->next;
528 
529  if ( block->IsBaseBlock() && block->node != NULL && ( next == NULL || next->IsBaseBlock() ) ) {
530  UnlinkFreeInternal( block );
531  if ( block->prev ) {
532  block->prev->next = block->next;
533  } else {
534  firstBlock = block->next;
535  }
536  if ( block->next ) {
537  block->next->prev = block->prev;
538  } else {
539  lastBlock = block->prev;
540  }
541  if ( lockMemory ) {
542  idLib::sys->UnlockMemory( block, block->GetSize() + (int)sizeof( idDynamicBlock<type> ) );
543  }
544  numBaseBlocks--;
545  baseBlockMemory -= block->GetSize() + (int)sizeof( idDynamicBlock<type> );
546  Mem_Free16( block );
547  }
548  }
549 
550 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
551  CheckMemory();
552 #endif
553 }
554 
555 template<class type, int baseBlockSize, int minBlockSize>
557  int numEmptyBaseBlocks;
558  idDynamicBlock<type> *block;
559 
560  numEmptyBaseBlocks = 0;
561  for ( block = firstBlock; block != NULL; block = block->next ) {
562  if ( block->IsBaseBlock() && block->node != NULL && ( block->next == NULL || block->next->IsBaseBlock() ) ) {
563  numEmptyBaseBlocks++;
564  }
565  }
566  return numEmptyBaseBlocks;
567 }
568 
569 template<class type, int baseBlockSize, int minBlockSize>
571  idDynamicBlock<type> *block;
572 
573  numAllocs++;
574 
575  if ( num <= 0 ) {
576  return NULL;
577  }
578 
579  block = AllocInternal( num );
580  if ( block == NULL ) {
581  return NULL;
582  }
583  block = ResizeInternal( block, num );
584  if ( block == NULL ) {
585  return NULL;
586  }
587 
588 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
589  CheckMemory();
590 #endif
591 
592  numUsedBlocks++;
593  usedBlockMemory += block->GetSize();
594 
595  return block->GetMemory();
596 }
597 
598 template<class type, int baseBlockSize, int minBlockSize>
600 
601  numResizes++;
602 
603  if ( ptr == NULL ) {
604  return Alloc( num );
605  }
606 
607  if ( num <= 0 ) {
608  Free( ptr );
609  return NULL;
610  }
611 
612  idDynamicBlock<type> *block = ( idDynamicBlock<type> * ) ( ( (byte *) ptr ) - (int)sizeof( idDynamicBlock<type> ) );
613 
614  usedBlockMemory -= block->GetSize();
615 
616  block = ResizeInternal( block, num );
617  if ( block == NULL ) {
618  return NULL;
619  }
620 
621 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
622  CheckMemory();
623 #endif
624 
625  usedBlockMemory += block->GetSize();
626 
627  return block->GetMemory();
628 }
629 
630 template<class type, int baseBlockSize, int minBlockSize>
632 
633  numFrees++;
634 
635  if ( ptr == NULL ) {
636  return;
637  }
638 
639  idDynamicBlock<type> *block = ( idDynamicBlock<type> * ) ( ( (byte *) ptr ) - (int)sizeof( idDynamicBlock<type> ) );
640 
641  numUsedBlocks--;
642  usedBlockMemory -= block->GetSize();
643 
644  FreeInternal( block );
645 
646 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
647  CheckMemory();
648 #endif
649 }
650 
651 template<class type, int baseBlockSize, int minBlockSize>
653  idDynamicBlock<type> *block;
654 
655  if ( ptr == NULL ) {
656  return NULL;
657  }
658 
659  block = ( idDynamicBlock<type> * ) ( ( (byte *) ptr ) - (int)sizeof( idDynamicBlock<type> ) );
660 
661  if ( block->node != NULL ) {
662  return "memory has been freed";
663  }
664 
665 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
666  if ( block->id[0] != 0x11111111 || block->id[1] != 0x22222222 || block->id[2] != 0x33333333 ) {
667  return "memory has invalid id";
668  }
669  if ( block->allocator != (void*)this ) {
670  return "memory was allocated with different allocator";
671  }
672 #endif
673 
674  /* base blocks can be larger than baseBlockSize which can cause this code to fail
675  idDynamicBlock<type> *base;
676  for ( base = firstBlock; base != NULL; base = base->next ) {
677  if ( base->IsBaseBlock() ) {
678  if ( ((int)block) >= ((int)base) && ((int)block) < ((int)base) + baseBlockSize ) {
679  break;
680  }
681  }
682  }
683  if ( base == NULL ) {
684  return "no base block found for memory";
685  }
686  */
687 
688  return NULL;
689 }
690 
691 template<class type, int baseBlockSize, int minBlockSize>
693  firstBlock = lastBlock = NULL;
694  allowAllocs = true;
695  lockMemory = false;
696  numBaseBlocks = 0;
697  baseBlockMemory = 0;
698  numUsedBlocks = 0;
699  usedBlockMemory = 0;
700  numFreeBlocks = 0;
701  freeBlockMemory = 0;
702  numAllocs = 0;
703  numResizes = 0;
704  numFrees = 0;
705 
706 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
707  blockId[0] = 0x11111111;
708  blockId[1] = 0x22222222;
709  blockId[2] = 0x33333333;
710 #endif
711 }
712 
713 template<class type, int baseBlockSize, int minBlockSize>
715  idDynamicBlock<type> *block;
716  int alignedBytes = ( num * sizeof( type ) + 15 ) & ~15;
717 
718  block = freeTree.FindSmallestLargerEqual( alignedBytes );
719  if ( block != NULL ) {
720  UnlinkFreeInternal( block );
721  } else if ( allowAllocs ) {
722  int allocSize = Max( baseBlockSize, alignedBytes + (int)sizeof( idDynamicBlock<type> ) );
723  block = ( idDynamicBlock<type> * ) Mem_Alloc16( allocSize );
724  if ( lockMemory ) {
725  idLib::sys->LockMemory( block, baseBlockSize );
726  }
727 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
728  memcpy( block->id, blockId, sizeof( block->id ) );
729  block->allocator = (void*)this;
730 #endif
731  block->SetSize( allocSize - (int)sizeof( idDynamicBlock<type> ), true );
732  block->next = NULL;
733  block->prev = lastBlock;
734  if ( lastBlock ) {
735  lastBlock->next = block;
736  } else {
737  firstBlock = block;
738  }
739  lastBlock = block;
740  block->node = NULL;
741 
742  numBaseBlocks++;
743  baseBlockMemory += allocSize;
744  }
745 
746  return block;
747 }
748 
749 template<class type, int baseBlockSize, int minBlockSize>
751  int alignedBytes = ( num * sizeof( type ) + 15 ) & ~15;
752 
753 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
754  assert( block->id[0] == 0x11111111 && block->id[1] == 0x22222222 && block->id[2] == 0x33333333 && block->allocator == (void*)this );
755 #endif
756 
757  // if the new size is larger
758  if ( alignedBytes > block->GetSize() ) {
759 
760  idDynamicBlock<type> *nextBlock = block->next;
761 
762  // try to annexate the next block if it's free
763  if ( nextBlock && !nextBlock->IsBaseBlock() && nextBlock->node != NULL &&
764  block->GetSize() + (int)sizeof( idDynamicBlock<type> ) + nextBlock->GetSize() >= alignedBytes ) {
765 
766  UnlinkFreeInternal( nextBlock );
767  block->SetSize( block->GetSize() + (int)sizeof( idDynamicBlock<type> ) + nextBlock->GetSize(), block->IsBaseBlock() );
768  block->next = nextBlock->next;
769  if ( nextBlock->next ) {
770  nextBlock->next->prev = block;
771  } else {
772  lastBlock = block;
773  }
774  } else {
775  // allocate a new block and copy
776  idDynamicBlock<type> *oldBlock = block;
777  block = AllocInternal( num );
778  if ( block == NULL ) {
779  return NULL;
780  }
781  memcpy( block->GetMemory(), oldBlock->GetMemory(), oldBlock->GetSize() );
782  FreeInternal( oldBlock );
783  }
784  }
785 
786  // if the unused space at the end of this block is large enough to hold a block with at least one element
787  if ( block->GetSize() - alignedBytes - (int)sizeof( idDynamicBlock<type> ) < Max( minBlockSize, (int)sizeof( type ) ) ) {
788  return block;
789  }
790 
791  idDynamicBlock<type> *newBlock;
792 
793  newBlock = ( idDynamicBlock<type> * ) ( ( (byte *) block ) + (int)sizeof( idDynamicBlock<type> ) + alignedBytes );
794 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
795  memcpy( newBlock->id, blockId, sizeof( newBlock->id ) );
796  newBlock->allocator = (void*)this;
797 #endif
798  newBlock->SetSize( block->GetSize() - alignedBytes - (int)sizeof( idDynamicBlock<type> ), false );
799  newBlock->next = block->next;
800  newBlock->prev = block;
801  if ( newBlock->next ) {
802  newBlock->next->prev = newBlock;
803  } else {
804  lastBlock = newBlock;
805  }
806  newBlock->node = NULL;
807  block->next = newBlock;
808  block->SetSize( alignedBytes, block->IsBaseBlock() );
809 
810  FreeInternal( newBlock );
811 
812  return block;
813 }
814 
815 template<class type, int baseBlockSize, int minBlockSize>
817 
818  assert( block->node == NULL );
819 
820 #ifdef DYNAMIC_BLOCK_ALLOC_CHECK
821  assert( block->id[0] == 0x11111111 && block->id[1] == 0x22222222 && block->id[2] == 0x33333333 && block->allocator == (void*)this );
822 #endif
823 
824  // try to merge with a next free block
825  idDynamicBlock<type> *nextBlock = block->next;
826  if ( nextBlock && !nextBlock->IsBaseBlock() && nextBlock->node != NULL ) {
827  UnlinkFreeInternal( nextBlock );
828  block->SetSize( block->GetSize() + (int)sizeof( idDynamicBlock<type> ) + nextBlock->GetSize(), block->IsBaseBlock() );
829  block->next = nextBlock->next;
830  if ( nextBlock->next ) {
831  nextBlock->next->prev = block;
832  } else {
833  lastBlock = block;
834  }
835  }
836 
837  // try to merge with a previous free block
838  idDynamicBlock<type> *prevBlock = block->prev;
839  if ( prevBlock && !block->IsBaseBlock() && prevBlock->node != NULL ) {
840  UnlinkFreeInternal( prevBlock );
841  prevBlock->SetSize( prevBlock->GetSize() + (int)sizeof( idDynamicBlock<type> ) + block->GetSize(), prevBlock->IsBaseBlock() );
842  prevBlock->next = block->next;
843  if ( block->next ) {
844  block->next->prev = prevBlock;
845  } else {
846  lastBlock = prevBlock;
847  }
848  LinkFreeInternal( prevBlock );
849  } else {
850  LinkFreeInternal( block );
851  }
852 }
853 
854 template<class type, int baseBlockSize, int minBlockSize>
856  block->node = freeTree.Add( block, block->GetSize() );
857  numFreeBlocks++;
858  freeBlockMemory += block->GetSize();
859 }
860 
861 template<class type, int baseBlockSize, int minBlockSize>
863  freeTree.Remove( block->node );
864  block->node = NULL;
865  numFreeBlocks--;
866  freeBlockMemory -= block->GetSize();
867 }
868 
869 template<class type, int baseBlockSize, int minBlockSize>
871  idDynamicBlock<type> *block;
872 
873  for ( block = firstBlock; block != NULL; block = block->next ) {
874  // make sure the block is properly linked
875  if ( block->prev == NULL ) {
876  assert( firstBlock == block );
877  } else {
878  assert( block->prev->next == block );
879  }
880  if ( block->next == NULL ) {
881  assert( lastBlock == block );
882  } else {
883  assert( block->next->prev == block );
884  }
885  }
886 }
887 
888 #endif /* !__HEAP_H__ */
idDynamicBlockAlloc(void)
Definition: Heap.h:446
int GetNumFreeBlocks(void) const
Definition: Heap.h:268
void FreeEmptyBaseBlocks(void)
Definition: Heap.h:523
assert(prefInfo.fullscreenBtn)
idDynamicBlock< type > * next
Definition: Heap.h:385
int GetNumUsedBlocks(void) const
Definition: Heap.h:408
struct idBlockAlloc::block_s block_t
void UnlinkFreeInternal(idDynamicBlock< type > *block)
Definition: Heap.h:862
void lock(CURL *handle, curl_lock_data data, curl_lock_access access, void *useptr)
Definition: lib506.c:29
void LinkFreeInternal(idDynamicBlock< type > *block)
Definition: Heap.h:855
idBTree< idDynamicBlock< type >, int, 4 > freeTree
Definition: Heap.h:417
type * Alloc(const int num)
Definition: Heap.h:303
idDynamicBlock< type > * ResizeInternal(idDynamicBlock< type > *block, const int num)
Definition: Heap.h:750
ID_INLINE T Max(T x, T y)
Definition: Lib.h:158
void Mem_DumpCompressed_f(const class idCmdArgs &args)
int freeBlockMemory
Definition: Heap.h:430
bool IsBaseBlock(void) const
Definition: Heap.h:376
int numFrees
Definition: Heap.h:278
element_t * free
Definition: Heap.h:179
void FreeInternal(idDynamicBlock< type > *block)
Definition: Heap.h:816
case const int
Definition: Callbacks.cpp:52
int GetNumUsedBlocks(void) const
Definition: Heap.h:266
void SetSize(int s, bool isBaseBlock)
Definition: Heap.h:375
char * Mem_CopyString(const char *in)
Definition: Heap.cpp:1169
void SetFixedBlocks(int numBlocks)
Definition: Heap.h:485
int GetUsedBlockMemory(void) const
Definition: Heap.h:267
int GetFreeBlockMemory(void) const
Definition: Heap.h:411
int GetBaseBlockMemory(void) const
Definition: Heap.h:265
void CheckMemory(void) const
Definition: Heap.h:870
virtual bool LockMemory(void *ptr, int bytes)=0
type * Resize(type *ptr, const int num)
Definition: Heap.h:314
int numUsedBlocks
Definition: Heap.h:273
idBTreeNode< idDynamicBlock< type >, int > * node
Definition: Heap.h:386
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
void Init(void)
Definition: Heap.h:294
static class idSys * sys
Definition: Lib.h:52
GLdouble s
Definition: glext.h:2935
type * Alloc(const int num)
Definition: Heap.h:570
int i
Definition: process.py:33
GLuint GLuint num
Definition: glext.h:5390
void SetLockMemory(bool lock)
Definition: Heap.h:256
void Free(type *ptr)
Definition: Heap.h:631
int GetNumEmptyBaseBlocks(void) const
Definition: Heap.h:270
struct element_s * next
Definition: Heap.h:170
void Mem_GetStats(memoryStats_t &stats)
Definition: Heap.cpp:1018
void Mem_Dump_f(const class idCmdArgs &args)
int total
Definition: Heap.h:180
element_t elements[blockSize]
Definition: Heap.h:174
int size
Definition: Heap.h:383
idDynamicBlock< type > * AllocInternal(const int num)
Definition: Heap.h:714
virtual bool UnlockMemory(void *ptr, int bytes)=0
void Shutdown(void)
Definition: Heap.h:461
int numAllocs
Definition: Heap.h:276
int minSize
Definition: Heap.h:47
type * Resize(type *ptr, const int num)
Definition: Heap.h:599
type * GetMemory(void) const
Definition: Heap.h:373
idDynamicAlloc(void)
Definition: Heap.h:284
int GetNumEmptyBaseBlocks(void) const
Definition: Heap.h:556
type * Alloc(void)
Definition: Heap.h:197
int GetSize(void) const
Definition: Heap.h:374
#define NULL
Definition: Lib.h:88
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
void Shutdown(void)
Definition: Heap.h:224
const char * CheckMemory(const type *ptr) const
Definition: Heap.h:341
void * Mem_Alloc16(const int size)
Definition: Heap.cpp:1107
~idDynamicBlockAlloc(void)
Definition: Heap.h:451
int GetAllocCount(void) const
Definition: Heap.h:165
void Clear(void)
Definition: Heap.h:346
int maxSize
Definition: Heap.h:48
int GetBaseBlockMemory(void) const
Definition: Heap.h:407
int GetNumBaseBlocks(void) const
Definition: Heap.h:406
int GetNumBaseBlocks(void) const
Definition: Heap.h:264
int totalSize
Definition: Heap.h:49
void * Mem_ClearedAlloc(const int size)
Definition: Heap.cpp:1149
int num
Definition: Heap.h:46
void Init(void)
Definition: Heap.h:456
idBlockAlloc(void)
Definition: Heap.h:185
void Free(type *ptr)
Definition: Heap.h:332
idDynamicBlock< type > * prev
Definition: Heap.h:384
void Shutdown(void)
Definition: Heap.h:298
int usedBlockMemory
Definition: Heap.h:274
void Clear(void)
Definition: Heap.h:692
idDynamicBlock< type > * firstBlock
Definition: Heap.h:415
void Mem_AllocDefragBlock(void)
Definition: Heap.cpp:1160
void FreeEmptyBaseBlocks(void)
Definition: Heap.h:257
struct idBlockAlloc::element_s element_t
int active
Definition: Heap.h:181
GLuint in
Definition: glext.h:5388
int GetNumFreeBlocks(void) const
Definition: Heap.h:410
void Mem_ClearFrameStats(void)
Definition: Heap.cpp:996
int GetUsedBlockMemory(void) const
Definition: Heap.h:409
unsigned char byte
Definition: Lib.h:75
const GLcharARB * name
Definition: glext.h:3629
struct block_s * next
Definition: Heap.h:175
GLsizeiptr size
Definition: glext.h:3112
block_t * blocks
Definition: Heap.h:178
Definition: BTree.h:57
int numResizes
Definition: Heap.h:277
int usedBlockMemory
Definition: Heap.h:428
void Mem_EnableLeakTest(const char *name)
Definition: Heap.cpp:1219
void SetLockMemory(bool lock)
Definition: Heap.h:518
void Mem_Init(void)
Definition: Heap.cpp:1198
void Free(type *element)
Definition: Heap.h:216
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
int GetFreeBlockMemory(void) const
Definition: Heap.h:269
void Mem_Free16(void *ptr)
Definition: Heap.cpp:1128
idDynamicBlock< type > * lastBlock
Definition: Heap.h:416
GLfloat GLfloat p
Definition: glext.h:4674
~idDynamicAlloc(void)
Definition: Heap.h:289
void Mem_GetFrameStats(memoryStats_t &allocs, memoryStats_t &frees)
Definition: Heap.cpp:1008
void SetFixedBlocks(int numBlocks)
Definition: Heap.h:255
~idBlockAlloc(void)
Definition: Heap.h:192
int GetFreeCount(void) const
Definition: Heap.h:166
void Mem_Shutdown(void)
Definition: Heap.cpp:1208
int GetTotalCount(void) const
Definition: Heap.h:164
int baseBlockMemory
Definition: Heap.h:426
GLdouble GLdouble t
Definition: glext.h:2943
bool allowAllocs
Definition: Heap.h:418