通用高效的c++内存池(特定类型)
2012-06-03 15:35 zhenjing 阅读(4468) 评论(3) 编辑 收藏 举报通用高效内存池的设计要点:
1)快速分配;
2)快速回收;
3)空间利用率高。
4)类型独立(最好)。
不打算对比各种内存分配器的优劣,主要是介绍一最近实现的特定类型的通用高效C++内存池。
特点:
1)基于共享内存; -- 不会因为进程挂掉而丢失数据。
2)快速分配; -- 在内存池接近满时,效率不高。
3)快速回收;-- 常数。
4)空间利用率高 -- 利用bit标识内存块使用与否 (《C++设计新思维》的小对象分配器不占用额外空间!!)
已知缺点:
1)在内存池接近满时,分配效率不高。
2)非类型独立。每一种类型需要一特定内存池。
3)非线程安全,需要使用者自行保证。
1 #ifndef __Memory_POOL__H__ 2 #define __Memory_POOL__H__ 3 4 #include <string> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <time.h> 8 #include <sys/time.h> 9 #include <sys/shm.h> 10 11 #include <bitstring.h> 12 #include "utilfunc.h" 13 14 15 template<class T> 16 struct MemPoolHead 17 { 18 size_t iTotalSize; // 19 size_t iCurSize; // 剩余空间数 20 size_t iNextPos; // 下一个可用位置,用于快速分配(循环分配) 21 size_t iRecordLen; 22 23 T arrDatas[0]; // 作为占位符,初始化后有效 24 25 MemPoolHead() 26 { 27 memset(this, 0, sizeof(MemPoolHead)); 28 } 29 }; 30 31 template<class T> 32 void PrintMemPoolHead(const MemPoolHead<T>& stHead) 33 { 34 printf("iTotalSize=%zu, iCurSize=%zu, iNextPos=%zu, iRecordLen=%zu\n", 35 stHead.iTotalSize, stHead.iCurSize, stHead.iNextPos, stHead.iRecordLen); 36 } 37 38 template<class T> 39 class MemoryPool 40 { 41 public: 42 MemoryPool(); 43 44 ~MemoryPool(); 45 46 int Init(int ishmKey); // for read exist data 47 48 int Init(int ishmKey, const MemPoolHead<T>& stHeadInfo); // for creating 49 50 T* GetPos(); 51 52 void DelPos(T* pdata); 53 54 void PrintHead() const; 55 56 int DeleteShm(); 57 58 int Reset(); 59 60 T* NextElem(size_t* pIndex) const; 61 62 63 size_t Total() const; 64 65 size_t Size() const; 66 67 bool Empty() const; 68 69 bool IsFull() const; 70 71 private: 72 MemoryPool(const MemoryPool&); 73 MemoryPool& operator=(const MemoryPool&); 74 75 int m_ishmKey; 76 MemPoolHead<T>* m_datas; 77 78 char* m_usedbits; // 标识特定内存块是否已使用 79 }; 80 81 82 template<class T> 83 MemoryPool<T>::MemoryPool() 84 { 85 m_ishmKey = -1; 86 m_datas = NULL; 87 m_usedbits = NULL; 88 } 89 90 template<class T> 91 MemoryPool<T>::~MemoryPool() 92 { 93 94 } 95 96 template<class T> 97 int MemoryPool<T>::Init(int ishmKey, const MemPoolHead<T>& stHeadInfo) 98 { 99 if( stHeadInfo.iCurSize > stHeadInfo.iTotalSize || stHeadInfo.iRecordLen != sizeof(T)){ 100 printf("Invalid parameters\n"); 101 return -1; 102 } 103 104 size_t size = sizeof(MemPoolHead<T>) + (stHeadInfo.iTotalSize) * sizeof(T) + (stHeadInfo.iTotalSize / 8 + 1); 105 106 PrintMemPoolHead(stHeadInfo); 107 printf("Head len=%lu, Recode Len=%lu, shm Size=%lu\n", sizeof(MemPoolHead<T>), sizeof(T), size); 108 109 int iCreate = false; 110 char* sShm = NULL; 111 if (!(sShm = UTIL::GetShm(ishmKey,size,0666&(~IPC_CREAT)))) 112 { 113 if (!(sShm = UTIL::GetShm(ishmKey,size,0666|IPC_CREAT))) 114 { 115 printf("get shm error!\n"); 116 return -2; 117 } 118 else 119 { 120 iCreate = true; 121 122 memset(sShm, 0, size); 123 } 124 } 125 126 m_datas = (MemPoolHead<T>*)sShm; 127 m_ishmKey = ishmKey; 128 129 m_usedbits = sShm + sizeof(MemPoolHead<T>) + (stHeadInfo.iTotalSize) * sizeof(T); 130 131 132 if( iCreate ){ 133 memcpy(m_datas, &stHeadInfo, sizeof(stHeadInfo)); 134 135 m_datas->iCurSize = 0; 136 m_datas->iNextPos = 0; 137 } 138 else { 139 if( stHeadInfo.iTotalSize != m_datas->iTotalSize || stHeadInfo.iRecordLen != m_datas->iRecordLen ) 140 { 141 printf("Memory head info is not matched!\n"); 142 PrintHead(); 143 144 m_datas = NULL; 145 m_ishmKey = -1; 146 return -1; 147 } 148 } 149 150 return 0; 151 } 152 153 template<class T> 154 int MemoryPool<T>::Init(int ishmKey) 155 { 156 MemPoolHead<T> stHead; 157 char* sShm = NULL; 158 if (!(sShm = UTIL::GetShm(ishmKey, sizeof(MemPoolHead<T>), 0666&(~IPC_CREAT)))) { 159 return -1; 160 } 161 162 memcpy(&stHead, sShm, sizeof(MemPoolHead<T>)); 163 164 return Init(ishmKey, stHead); 165 } 166 167 template<class T> 168 T* MemoryPool<T>::GetPos() 169 { 170 if( NULL == m_datas || m_datas->iNextPos > m_datas->iTotalSize ){ 171 printf("Something wrong in memory pool!\n"); 172 return NULL; 173 } 174 175 if( m_datas->iCurSize >= m_datas->iTotalSize ){ 176 printf("Memory pool is full\n"); 177 return NULL; 178 } 179 180 T *pdata = NULL; 181 182 while(1){ 183 184 if( m_datas->iNextPos >= m_datas->iTotalSize ){ 185 m_datas->iNextPos = 0; 186 } 187 188 if( bit_test(m_usedbits, m_datas->iNextPos) ){ // pos is used 189 m_datas->iNextPos++; 190 continue; 191 } 192 else{ 193 bit_set(m_usedbits, m_datas->iNextPos); 194 195 pdata = &m_datas->arrDatas[m_datas->iNextPos++]; 196 m_datas->iCurSize ++; 197 break; 198 } 199 } 200 return pdata; 201 } 202 203 template<class T> 204 void MemoryPool<T>::DelPos(T* pdata) 205 { 206 if( (char*)pdata >= (char*)m_datas + sizeof(MemPoolHead<T>) && (char*)pdata < m_usedbits) 207 { 208 if( ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead<T>))) % sizeof(T) == 0){ 209 size_t index = ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead<T>))) / sizeof(T); 210 211 if( bit_test(m_usedbits, index) ){ 212 printf("delete pos: %p(%zu)\n", pdata, index); 213 214 memset(pdata, 0, sizeof(T)); 215 216 m_datas->iCurSize --; 217 218 bit_clear(m_usedbits, index); 219 } 220 } 221 } 222 } 223 224 template<class T> 225 void MemoryPool<T>::PrintHead() const 226 { 227 if( NULL == m_datas ) return; 228 229 PrintMemPoolHead(*m_datas); 230 } 231 232 template<class T> 233 int MemoryPool<T>::DeleteShm() 234 { 235 if( NULL == m_datas ) return 0; 236 237 shmdt(m_datas); 238 239 return UTIL::DeleteShm(m_ishmKey); 240 } 241 242 template<class T> 243 int MemoryPool<T>::Reset() 244 { 245 if( NULL == m_datas ) return 0; 246 247 size_t size = (m_datas->iTotalSize) * sizeof(T) + (m_datas->iTotalSize / 8 + 1); 248 249 memset((char*)m_datas + sizeof(MemPoolHead<T>), 0, size); 250 m_datas->iCurSize = 0; 251 m_datas->iNextPos = 0; 252 253 return 0; 254 } 255 256 template<class T> 257 T* MemoryPool<T>::NextElem(size_t* pIndex) const 258 { 259 if( NULL == m_datas || NULL == pIndex ) return NULL; 260 261 while( *pIndex < m_datas->iTotalSize ) 262 { 263 size_t index = *pIndex; 264 if( bit_test(m_usedbits, index) ) 265 { 266 *pIndex = index + 1; 267 268 return &m_datas->arrDatas[index]; 269 } 270 *pIndex = index + 1; 271 } 272 273 return NULL; 274 } 275 276 template<class T> 277 size_t MemoryPool<T>::Total() const 278 { 279 if( NULL == m_datas ) return 0; 280 281 return m_datas->iTotalSize; 282 } 283 284 template<class T> 285 size_t MemoryPool<T>::Size() const 286 { 287 if( NULL == m_datas ) return 0; 288 289 return m_datas->iCurSize; 290 } 291 292 template<class T> 293 bool MemoryPool<T>::Empty() const 294 { 295 if( NULL == m_datas ) return false; 296 297 return ( 0 == m_datas->iCurSize); 298 } 299 300 template<class T> 301 bool MemoryPool<T>::IsFull() const 302 { 303 if( NULL == m_datas ) return true; 304 305 return (m_datas->iTotalSize == m_datas->iCurSize); 306 } 307 308 #endif
作者:zhenjing.chen
出处:http://www.cnblogs.com/zhenjing/
未注明转载的文章,版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。