00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <spl/Exception.h>
00018 #include <spl/io/File.h>
00019 #include <spl/math/Math.h>
00020 #include <spl/collection/MemoryPool.h>
00021
00022 static const int FREEED_MEMORY_CONTENT = 0xAA ;
00023 static const int NEW_ALLOCATED_MEMORY_CONTENT = 0xFF ;
00024 static const int MP_MAJIC = 27013;
00025
00026 MemoryPool::MemoryPool(const int blockSize, bool setMemoryData)
00027 : m_totalMemoryPoolSize(0),
00028 m_usedMemoryPoolSize(0),
00029 m_freeMemoryPoolSize(0),
00030 m_memoryBlockSize(blockSize),
00031 m_memoryBlockCount(0),
00032 m_setMemoryData(setMemoryData)
00033 {
00034 m_head.m_data = NULL;
00035 m_head.m_size = 0;
00036 m_head.m_pos = 0;
00037 m_head.m_next = NULL;
00038 m_head.m_checkBits = MP_MAJIC;
00039 }
00040
00041 MemoryPool::~MemoryPool()
00042 {
00043 ASSERT(m_head.m_checkBits == MP_MAJIC);
00044
00045 MemoryBlock *mb = m_head.m_next;
00046 while ( NULL != mb )
00047 {
00048 ASSERT(mb->m_checkBits == MP_MAJIC);
00049 ASSERT_MEM(mb, sizeof(MemoryBlock));
00050 ASSERT_MEM(mb->m_data, mb->m_size);
00051
00052 MemoryBlock *next = mb->m_next;
00053 free(mb->m_data);
00054 delete mb;
00055 mb = next;
00056 }
00057 m_head.m_next = NULL;
00058 }
00059
00060 void *MemoryPool::Malloc(int size)
00061 {
00062 ASSERT(m_head.m_checkBits == MP_MAJIC);
00063
00064 m_freeMemoryPoolSize -= size;
00065 m_usedMemoryPoolSize += size;
00066
00067
00068 size += 8;
00069
00070 MemoryBlock *mb;
00071
00072 if ( size > m_memoryBlockSize )
00073 {
00074
00075 mb = AllocateBlock(size);
00076 }
00077 else
00078 {
00079 mb = m_head.m_next;
00080 while ( NULL != mb )
00081 {
00082 if ( mb->m_size - mb->m_pos > size )
00083 {
00084 break;
00085 }
00086 mb = mb->m_next;
00087 }
00088 if ( NULL == mb )
00089 {
00090 mb = AllocateBlock(m_memoryBlockSize);
00091 }
00092 }
00093 void *data = &mb->m_data[mb->m_pos];
00094 *((int32 *)data) = mb->m_blockId;
00095 data = &((byte *)data)[4];
00096 *((int32 *)data) = size;
00097 data = &((byte *)data)[4];
00098
00099 mb->m_pos += size;
00100 ASSERT( mb->m_pos <= mb->m_size );
00101 return data;
00102 }
00103
00104 void MemoryPool::Free(void *ptr)
00105 {
00106 ASSERT(m_head.m_checkBits == MP_MAJIC);
00107
00108 int blockId = *((int32 *)(((byte *)ptr) - 8));
00109 int size = *((int32 *)(((byte *)ptr) - 4));
00110
00111 MemoryBlock *mb = m_head.m_next;
00112 while ( NULL != mb )
00113 {
00114 if ( mb->m_blockId == blockId )
00115 {
00116 ASSERT( size <= mb->m_size );
00117 mb->m_freeSize += size;
00118 ASSERT( mb->m_freeSize <= mb->m_size );
00119 if ( mb->m_freeSize == mb->m_size )
00120 {
00121 mb->m_freeSize = 0;
00122 mb->m_pos = 0;
00123 }
00124 return;
00125 }
00126 mb = mb->m_next;
00127 }
00128 throw new Exception("MemoryPool::Free: pointer not found");
00129 }
00130
00131 bool MemoryPool::WriteMemoryDumpToFile(const char *fileName) const
00132 {
00133 spl::IStreamPtr writer = File::OpenWrite(fileName);
00134
00135 MemoryBlock *mb = m_head.m_next;
00136 while ( NULL != mb )
00137 {
00138 Array<byte> data(mb->m_data, mb->m_size);
00139 writer->Write(data);
00140 mb = mb->m_next;
00141 }
00142 writer->Close();
00143
00144 return true;
00145 }
00146
00147 bool MemoryPool::IsValidPointer(const void *ptr) const
00148 {
00149 ASSERT(m_head.m_checkBits == MP_MAJIC);
00150
00151 int blockId = *((int32 *)(((byte *)ptr) - 8));
00152 int size = *((int32 *)(((byte *)ptr) - 4));
00153
00154 MemoryBlock *mb = m_head.m_next;
00155 while ( NULL != mb )
00156 {
00157 if ( mb->m_blockId == blockId )
00158 {
00159 ASSERT( size <= mb->m_size );
00160 return true;;
00161 }
00162 mb = mb->m_next;
00163 }
00164 return false;
00165 }
00166
00167 MemoryBlock *MemoryPool::AllocateBlock(int size)
00168 {
00169 MemoryBlock *mb = (MemoryBlock *)malloc(sizeof(MemoryBlock));
00170 if ( NULL == mb )
00171 {
00172 throw OutOfMemoryException();
00173 }
00174 memset(mb, 0, sizeof(MemoryBlock));
00175 mb->m_checkBits = MP_MAJIC;
00176 if (NULL == (mb->m_data = (byte *)malloc(size)))
00177 {
00178 throw OutOfMemoryException();
00179 }
00180
00181 if ( m_setMemoryData )
00182 {
00183 memset(mb->m_data, NEW_ALLOCATED_MEMORY_CONTENT, size);
00184 }
00185
00186 mb->m_blockId = m_memoryBlockCount++;
00187 mb->m_size = size;
00188 mb->m_next = m_head.m_next;
00189 m_head.m_next = mb;
00190
00191 m_totalMemoryPoolSize += size;
00192 m_freeMemoryPoolSize += size;
00193
00194 return mb;
00195 }
00196
00197 #ifdef DEBUG
00198 void MemoryPool::ValidateMem () const
00199 {
00200 ASSERT(m_head.m_checkBits == MP_MAJIC);
00201
00202 MemoryBlock *mb = m_head.m_next;
00203 while ( NULL != mb )
00204 {
00205 ASSERT(mb->m_checkBits == MP_MAJIC);
00206 ASSERT_MEM(mb, sizeof(MemoryBlock));
00207 ASSERT_MEM(mb->m_data, mb->m_size);
00208 mb = mb->m_next;
00209 }
00210 }
00211
00212 void MemoryPool::CheckMem () const
00213 {
00214 ASSERT(m_head.m_checkBits == MP_MAJIC);
00215
00216 MemoryBlock *mb = m_head.m_next;
00217 while ( NULL != mb )
00218 {
00219 ASSERT(mb->m_checkBits == MP_MAJIC);
00220 DEBUG_NOTE_MEM(mb);
00221 DEBUG_NOTE_MEM(mb->m_data);
00222
00223 mb = mb->m_next;
00224 }
00225 }
00226 #endif
00227
00228 void *operator new (size_t size, MemoryPool& pool)
00229 {
00230 return pool.Malloc((int)size);
00231 }
00232
00233 void operator delete (void *ptr, MemoryPool& pool)
00234 {
00235 pool.Free(ptr);
00236 }