C++实现简单内存池

内存池是什么?

内存池(Memory Pool)是一种内存分配方式,又被称为固定大小区块规划(fixed-size-blocks allocation)。通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。

内存池如何实现?

1.内存结构

typedef struct {
  struct list_head list;
  int fd;  // Unix系映射文件句柄
  int tid;
} Heap;

typedef struct {
  unsigned int unMem_flg; // 块标志
  unsigned int unMem_size; // 块大小
} Heapinf;

#define ALLOCATE_MEM_ALL_BLOCK 0xFFFFFFFF //不可分区的块
#define ALLOCATE_MEM_SEP_BLOCK 0x11111111 //可分区的块
#define ALLOCATE_MEM_STATUS_USED 0x22222222 //已使用的块
#define ALLOCATE_MEM_STATUS_FREE 0x33333333 //未使用的块

在这里插入图片描述

2.接口

class HeapManage {
 public:
  // 从内存池分配指定内存
  static void *_allocate(unsigned int size, unsigned int tid);
  // 将内存返回内存池
  static int _release(void *ptr);
  
 private:
  struct list_head head;
  HeapManage();
  virtual ~HeapManage(){};
  // 获取堆内存/虚拟内存
  static void *_allocate_p(int mode, unsigned int unMemSize, int mapfd);
  // 释放堆内存/虚拟内存
  static void _release_p(list_head *head);
  // 单例模式
  static HeapManage &getInstance(); 
  static HeapManage *sInstance;
  class HeapFree {
   public:
    HeapFree() {}
    virtual ~HeapFree();
  };
  friend class HeapManage::HeapFree;
  static HeapFree mHeapFree;
};

#define allocate(size) HeapManage::_allocate(size, 0)
#define release(ptr) HeapManage::_release(ptr)

3.分配

void *HeapManage::_allocate(unsigned int ulAreaSize, unsigned int tid) {
  void *pReturn_code = NULL;
  ......

  unMemAct_size = length_align(ulAreaSize);
  head = &getInstance().head;
  pHeap = list_entry(head->next, Heap, list);
  iMem_fd = pHeap->fd;

  if (unMemAct_size > 64 * 1024) {
    pHeap = (Heap *)_allocate_p(
        0, unMemAct_size + sizeof(Heap) + sizeof(Heapinf) * 2, iMem_fd);
    if (pHeap != NULL) {
      list_add_tail(&pHeap->list, head);
      pHeap->tid = tid;
      pReturn_code = (char *)pHeap + sizeof(Heap) + sizeof(Heapinf);
    } else {
      ;
    }
    goto EXIT;
  }

  pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
  do {
    pHeapInf = (Heapinf *)((char *)pHeap + sizeof(Heap));
    if (pHeapInf->unMem_flg == ALLOCATE_MEM_ALL_BLOCK) {
      if (pHeap->list.next != head) {
        pHeap = list_entry(pHeap->list.next, Heap, list);
        pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
      } else {
        pHeap = (Heap *)_allocate_p(1, 0, iMem_fd);
        if (pHeap != NULL) {
          list_add_tail(&pHeap->list, head);
          pWorkInf =
              (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
        } else {
          ;
        }
      }
    } else if (pHeap->tid != tid) {
      if (pHeap->list.next != head) {
        ... ...
      } else {
        ... ...
      }
    } else if (pWorkInf->unMem_flg == ALLOCATE_MEM_STATUS_FREE) {
      if (pWorkInf->unMem_size >= unMemAct_size + sizeof(Heapinf) * 2) {
        /*** 从空闲区取出期待大小的块 ***/
        /*** 重新计算空闲区 ***/
        ......
        iMem_flg = 1;
        ...... 
      } else {
        pWorkInf = (Heapinf *)((char *)pWorkInf + sizeof(Heapinf) * 2 +
                               pWorkInf->unMem_size);
      }
    } else if (pWorkInf->unMem_flg == ALLOCATE_MEM_STATUS_USED) {
      pWorkInf = (Heapinf *)((char *)pWorkInf + sizeof(Heapinf) * 2 +
                             pWorkInf->unMem_size);
    } else if (pWorkInf->unMem_flg == ALLOCATE_MEM_SEP_BLOCK) {
      if (pHeap->list.next != head) {
        pHeap = list_entry(pHeap->list.next, Heap, list);
        pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
      } else {
        ... ...
      }
    } else {
      goto EXIT;
    }
  } while (iMem_flg != 1);

EXIT:
  return pReturn_code;
}

4.释放

int HeapManage::_release(void *ptr) {
  int iReturn_code;
  ......

  iReturn_code = 0;
  if (ptr == 0) goto EXIT;

  head = &getInstance().head;

  inf = (Heapinf *)((char *)ptr - sizeof(Heapinf));
  switch (inf->unMem_flg) {
    case ALLOCATE_MEM_STATUS_USED:
      pwk_inf = inf;
      do {
        pwk_inf = (Heapinf *)((char *)pwk_inf + pwk_inf->unMem_size +
                              sizeof(Heapinf) * 2);
        if (pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_FREE &&
            pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_USED &&
            pwk_inf->unMem_flg != ALLOCATE_MEM_SEP_BLOCK) {
          iReturn_code = -1;
          goto EXIT;
        }
      } while (pwk_inf->unMem_flg != ALLOCATE_MEM_SEP_BLOCK);

      pHeap = (Heap *)((char *)pwk_inf -
                       (sizeof(Heap) + sizeof(Heapinf) + pwk_inf->unMem_size));

      unMemFree_size = inf->unMem_size;

      pwk_inf = (Heapinf *)((char *)inf + inf->unMem_size + sizeof(Heapinf));
      if (pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_USED ||
          pwk_inf->unMem_size != unMemFree_size) {
        iReturn_code = -1;
        goto EXIT;
      }

      unMemNext_free_flg = 0;
      pwk_inf = (Heapinf *)((char *)pwk_inf + sizeof(Heapinf));
      // 根据释放区域前后区域是否需要合并,重新计算空闲区大小
      ... ...
      ... ...
      
      if (pHeap->list.prev == pHeap->list.next) {
        goto EXIT;
      } else {
        inf = (Heapinf *)((char *)pHeap + sizeof(Heap));
        if (inf->unMem_size == (inf + 1)->unMem_size + sizeof(Heapinf) * 2) {
          ;
        } else {
          goto EXIT;
        }
      }
      break;
    case ALLOCATE_MEM_ALL_BLOCK:
      pHeap = (Heap *)((char *)inf - sizeof(Heap));
      break;
    default:
      iReturn_code = -1;
      goto EXIT;
  }
  
  // 释放空内存池
  unMemFree_size = ((Heapinf *)(pHeap + 1))->unMem_size;
  unMemFree_size += sizeof(Heap) + sizeof(Heapinf) * 2;
  list_del(&pHeap->list);
#if defined(WIN32)
  hGlobal = GlobalHandle(pHeap);
  GlobalUnlock(hGlobal);
  GlobalFree(hGlobal);
#else
  munmap(pHeap, unMemFree_size);
#endif
EXIT:
  return iReturn_code;
}

5.C语言版本实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值