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_