• 通用高效的c++内存池(特定类型)


    通用高效内存池的设计要点:

    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/
    未注明转载的文章,版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Mysql数据库--自学笔记--2
    Mysql数据库--自学笔记--1
    Python--作业3--模拟ATM程序的流程
    Python--数据存储:json模块的使用讲解
    如果我能成功,你也能
    有意注意到底有多重要
    没有人喜欢听废话——讲重点
    回顾你的一天是多么的重要
    思考的力量
    多问为什么,肯定不会错
  • 原文地址:https://www.cnblogs.com/zhenjing/p/memory_pool.html
Copyright © 2020-2023  润新知