分类: 其他平台
2015-04-29 15:56:44
通用高效内存池的设计要点:
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
5 #include
6 #include
7 #include
8 #include
9 #include
10
11 #include
12 #include "utilfunc.h"
13
14
15 template
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
32 void PrintMemPoolHead(const MemPoolHead
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
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
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
77
78 char* m_usedbits; // 标识特定内存块是否已使用
79 };
80
81
82 template
83 MemoryPool
84 {
85 m_ishmKey = -1;
86 m_datas = NULL;
87 m_usedbits = NULL;
88 }
89
90 template
91 MemoryPool
92 {
93
94 }
95
96 template
97 int MemoryPool
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
105
106 PrintMemPoolHead(stHeadInfo);
107 printf("Head len=%lu, Recode Len=%lu, shm Size=%lu\n", sizeof(MemPoolHead
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
127 m_ishmKey = ishmKey;
128
129 m_usedbits = sShm + sizeof(MemPoolHead
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
154 int MemoryPool
155 {
156 MemPoolHead
157 char* sShm = NULL;
158 if (!(sShm = UTIL::GetShm(ishmKey, sizeof(MemPoolHead
159 return -1;
160 }
161
162 memcpy(&stHead, sShm, sizeof(MemPoolHead
163
164 return Init(ishmKey, stHead);
165 }
166
167 template
168 T* MemoryPool
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
204 void MemoryPool
205 {
206 if( (char*)pdata >= (char*)m_datas + sizeof(MemPoolHead
207 {
208 if( ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead
209 size_t index = ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead
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
225 void MemoryPool
226 {
227 if( NULL == m_datas ) return;
228
229 PrintMemPoolHead(*m_datas);
230 }
231
232 template
233 int MemoryPool
234 {
235 if( NULL == m_datas ) return 0;
236
237 shmdt(m_datas);
238
239 return UTIL::DeleteShm(m_ishmKey);
240 }
241
242 template
243 int MemoryPool
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
250 m_datas->iCurSize = 0;
251 m_datas->iNextPos = 0;
252
253 return 0;
254 }
255
256 template
257 T* MemoryPool
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
277 size_t MemoryPool
278 {
279 if( NULL == m_datas ) return 0;
280
281 return m_datas->iTotalSize;
282 }
283
284 template
285 size_t MemoryPool
286 {
287 if( NULL == m_datas ) return 0;
288
289 return m_datas->iCurSize;
290 }
291
292 template
293 bool MemoryPool
294 {
295 if( NULL == m_datas ) return false;
296
297 return ( 0 == m_datas->iCurSize);
298 }
299
300 template
301 bool MemoryPool
302 {
303 if( NULL == m_datas ) return true;
304
305 return (m_datas->iTotalSize == m_datas->iCurSize);
306 }
307
308 #endif