Chinaunix首页 | 论坛 | 博客
  • 博客访问: 494512
  • 博文数量: 133
  • 博客积分: 1235
  • 博客等级: 少尉
  • 技术积分: 1201
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-08 19:59
文章分类

全部博文(133)

文章存档

2023年(12)

2022年(3)

2018年(2)

2017年(4)

2016年(4)

2015年(42)

2014年(1)

2013年(12)

2012年(16)

2011年(36)

2010年(1)

分类: 其他平台

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& 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

 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& 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*   m_datas;

 77 

 78         char*   m_usedbits;   // 标识特定内存块是否已使用

 79 };

 80 

 81 

 82 template

 83 MemoryPool::MemoryPool()

 84 {

 85     m_ishmKey = -1;

 86     m_datas = NULL;

 87     m_usedbits = NULL;

 88 }

 89 

 90 template

 91 MemoryPool::~MemoryPool()

 92 {

 93 

 94 }

 95 

 96 template

 97 int MemoryPool::Init(int ishmKey, const MemPoolHead& 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) + (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), 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*)sShm;   

127     m_ishmKey = ishmKey;

128 

129     m_usedbits = sShm + sizeof(MemPoolHead) + (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

154 int MemoryPool::Init(int ishmKey)

155 {

156     MemPoolHead stHead;

157     char* sShm = NULL;

158     if (!(sShm = UTIL::GetShm(ishmKey, sizeof(MemPoolHead), 0666&(~IPC_CREAT)))) {

159         return -1;

160     }

161 

162     memcpy(&stHead, sShm, sizeof(MemPoolHead));

163 

164     return Init(ishmKey, stHead);

165 }

166 

167 template

168 T* MemoryPool::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

204 void MemoryPool::DelPos(T* pdata)

205 {

206     if( (char*)pdata >= (char*)m_datas + sizeof(MemPoolHead) && (char*)pdata < m_usedbits) 

207     {

208         if( ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead))) % sizeof(T) == 0){

209             size_t index = ((char*)pdata - ((char*)m_datas + sizeof(MemPoolHead))) / 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

225 void MemoryPool::PrintHead() const

226 {   

227     if( NULL == m_datas ) return;

228 

229     PrintMemPoolHead(*m_datas);

230 }

231 

232 template

233 int MemoryPool::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

243 int MemoryPool::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), 0, size);

250     m_datas->iCurSize = 0;

251     m_datas->iNextPos = 0;

252 

253     return 0;

254 }

255         

256 template

257 T* MemoryPool::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

277 size_t MemoryPool::Total() const

278 {

279     if( NULL == m_datas ) return 0;

280 

281     return m_datas->iTotalSize;

282 }

283 

284 template

285 size_t MemoryPool::Size() const

286 {

287     if( NULL == m_datas ) return 0;

288 

289     return m_datas->iCurSize;

290 }

291 

292 template

293 bool   MemoryPool::Empty() const

294 {

295     if( NULL == m_datas ) return false;

296 

297     return ( 0 == m_datas->iCurSize);

298 }

299 

300 template

301 bool   MemoryPool::IsFull() const

302 {

303     if( NULL == m_datas ) return true;

304 

305     return (m_datas->iTotalSize == m_datas->iCurSize);

306 }

307 

308 #endif

阅读(1363) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~