UTMemDebugTracker.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _UT_MEMDEBUG_TRACKER_H_
00026 #define _UT_MEMDEBUG_TRACKER_H_
00027
00028 #if UT_MEMDEBUG
00029
00030
00031
00032
00033
00034 #include "UTLists.h"
00035 #include "UTMutex.h"
00036
00037
00038
00039
00040
00041 class MemDebugPool_t;
00042
00043
00044
00045
00046
00047 const int c_memdebug_num_stack_frames = 12;
00048 const int c_memdebug_guard_size = 63;
00049 const byte c_memdebug_guard_val = 0xca;
00050 const int c_memdebug_num_block_sizes = 20;
00051 struct MemDebugBlockSize_t
00052 {
00053 size_t max_block_size;
00054 int allocate_per_pool;
00055 };
00056
00057
00058
00059 struct Alloc_t
00060
00061 {
00062 Alloc_t* norecycle_newer;
00063 size_t alloc_size;
00064 size_t max_realloc_size;
00065 void* stack[c_memdebug_num_stack_frames];
00066 byte checksum;
00067 byte head_guard[c_memdebug_guard_size];
00068 };
00069
00070
00071
00072 class MemDebugTracker_t
00073
00074 {
00075
00076 public:
00077
00078 MemDebugTracker_t();
00079 ~MemDebugTracker_t();
00080
00081 void* Malloc(size_t size);
00082 void Free(void* ptr);
00083 void* Realloc( void* ptr, size_t size );
00084
00085 void ReportError( const char* message,
00086 Alloc_t* alloc );
00087
00088
00089 private:
00090
00091 void SetNoRecycleLimit();
00092 void* LargeMalloc(size_t size);
00093 MemDebugPool_t* CreatePool(size_t block_size);
00094 void DeleteOldestPoolIfStale();
00095 void CheckNorecycleMemoryUsage();
00096 void SetCaller(Alloc_t* alloc);
00097
00098
00099 private:
00100
00101 MemDebugBlockSize_t m_pool_size_info[c_memdebug_num_block_sizes];
00102
00103 Mutex_t m_mutex;
00104 bool m_already_in_memdebug_tracker;
00105 bool m_error;
00106
00107 OwnedBTree_t< MemDebugPool_t, MemDebugPool_t* > m_all_pools_by_addr;
00108 BTree_t< MemDebugPool_t, size_t > m_avail_pools_by_size;
00109 LinkedList_t<MemDebugPool_t> m_delete_pools_by_age;
00110 BTree_t< MemDebugPool_t, size_t > m_delete_pools_by_size;
00111
00112 Alloc_t* m_norecycle_oldest;
00113 Alloc_t* m_norecycle_newest;
00114 size_t m_norecycle_current_bytes;
00115 uint32 m_norecycle_max_kb;
00116 size_t m_allocations_until_next_system_memcheck;
00117 };
00118
00119
00120
00121 class MemDebugPool_t
00122
00123 : public BTreeNode_t< MemDebugPool_t, MemDebugPool_t* >,
00124 public BTreeNode_t< MemDebugPool_t, size_t >,
00125 public LinkedListNode_t<MemDebugPool_t>
00126 {
00127
00128 public:
00129
00130 void* operator new( size_t size, int capacity, size_t block_size );
00131 MemDebugPool_t( int capacity, size_t block_size );
00132 ~MemDebugPool_t();
00133 void operator delete(void* malloced_block);
00134
00135 inline size_t BlockSize() const;
00136 inline int Capacity() const;
00137 inline bool AllBlocksAllocated() const;
00138 inline bool AllBlocksAvailable() const;
00139 bool Contains(byte* block) const;
00140 inline void InitDeleteCounter(int count);
00141 inline bool DecrementDeleteCounter();
00142
00143 Alloc_t* Allocate();
00144 void Release(Alloc_t* block);
00145
00146 inline int Compare(MemDebugPool_t* address) const;
00147 inline operator MemDebugPool_t*() const;
00148 inline int Compare(size_t block_size) const;
00149 inline operator size_t() const;
00150
00151
00152 private:
00153
00154 size_t m_block_size;
00155 int m_capacity;
00156 uint32 m_avail_bitmap;
00157 uint32 m_avail_bitmap_when_all_avail;
00158 int m_delete_counter;
00159 };
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 inline size_t
00172 MemDebugPool_t::BlockSize() const
00173 {
00174 return m_block_size;
00175 }
00176
00177
00178 inline int
00179 MemDebugPool_t::Capacity() const
00180 {
00181 return m_capacity;
00182 }
00183
00184
00185 inline bool
00186 MemDebugPool_t::AllBlocksAllocated() const
00187 {
00188 return (m_avail_bitmap == 0);
00189 }
00190
00191
00192 inline bool
00193 MemDebugPool_t::AllBlocksAvailable() const
00194 {
00195 return (m_avail_bitmap == m_avail_bitmap_when_all_avail);
00196 }
00197
00198
00199 inline void
00200 MemDebugPool_t::InitDeleteCounter(int count)
00201 {
00202 m_delete_counter = count;
00203 }
00204
00205
00206 inline bool
00207 MemDebugPool_t::DecrementDeleteCounter()
00208 {
00209 assert(m_delete_counter > 0);
00210 m_delete_counter--;
00211 return (m_delete_counter == 0);
00212 }
00213
00214
00215 inline int
00216 MemDebugPool_t::Compare(MemDebugPool_t* address) const
00217 {
00218
00219 if(this < address)
00220 return -1;
00221 else if(this == address)
00222 return 0;
00223 return 1;
00224 }
00225
00226
00227 inline
00228 MemDebugPool_t::operator MemDebugPool_t*() const
00229 {
00230 return const_cast<MemDebugPool_t*>(this);
00231 }
00232
00233
00234 inline int
00235 MemDebugPool_t::Compare(size_t block_size) const
00236 {
00237
00238 if(m_block_size < block_size)
00239 return -1;
00240 else if(m_block_size == block_size)
00241 return 0;
00242 return 1;
00243 }
00244
00245
00246 inline
00247 MemDebugPool_t::operator size_t() const
00248 {
00249 return m_block_size;
00250 }
00251
00252
00253 #endif // UT_MEMDEBUG
00254
00255 #endif // _UT_MEMDEBUG_TRACKER_H_