通用高效内存池的设计要点:
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
原文链接: https://www.cnblogs.com/zhenjing/archive/2012/06/03/memory_pool.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/51781
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!