内存池,参考sgi stl的实现,测试后感觉还不错

基本设计思路:

内存分配的最小单位为8字节,称为内存块,一次分配若干连续的内存块,称为内存池。

类似sgi stl的做法,取一个数组作为内存分配的入口,每个入口都只能分配大小为8的倍数的内存,而数组的下标就是用来确定这个倍数。

每个入口都维护一个链表,链表的节点

当申请内存时,根据申请的字节数确定入口后,看当前链表是否有节点可用,有就分配出去,没有就向内存池申请。

回收内存时,将内存块直接挂回链表的头部,而不是返回给内存池

最大优点是:内存碎片为0,分配回收效率较高

最大缺点是:运行时的内存占有量只增不减,但增长比较缓慢

/*

 * File:   Allocator.h

 * Author: Administrator

 *

 * Created on 2011年3月15日, 下午3:10

 */

 

#ifndef ALLOCATOR_H

#define ALLOCATOR_H

 

#include <iostream>

using namespace std;

 

const int ENTRY_COUNT = 16; //提供16个内存池分配入口

const int BLOCK_SIZE = 8; //内存块的大小

const int POOL_SIZE = 256; //内存池中的内存块个数

const int MAX_SIZE = ENTRY_COUNT*BLOCK_SIZE; //一次最大可分配的字节数,大于时将采用普通的new

 

 

namespace zlh {

 

    template<class T>

    class Allocator {

    private:

 

        //内存块,分配的最小单位

 

        union MemoryBlock {

 

            MemoryBlock() : next(0) {

            }

            MemoryBlock* next;

            unsigned char buf[BLOCK_SIZE];

        };

 

        //内存池,管理内存块

 

        struct MemoryPool {

 

            MemoryPool() : vernier(0), next(0) {

            }

 

            int remain() //获取剩余块数

            {

                return POOL_SIZE - vernier;

            }

 

            void alloc(int index) //给entry[index]分配空间

            {

                pool[vernier].next = entry[index];

                entry[index] = &pool[vernier];

                vernier = vernier + index + 1;

            }

 

            MemoryPool* next;

            int vernier; //游标,从该处开始分配

            MemoryBlock pool[POOL_SIZE];

        };

 

    private:

        static MemoryPool* firstPool; //从该指针指向的池分配空间

        static MemoryBlock** entry; //分配空间的入口

    public:

 

        Allocator() {

 

            ///初始化分配入口

            entry = new MemoryBlock*[ENTRY_COUNT];

            for (int i = 0; i < ENTRY_COUNT; i++)

                entry[i] = 0;

 

            ///必须保证firstPool不为0

            if (firstPool == 0) {

                firstPool = new MemoryPool();

            }

        }

 

        ~Allocator() {

 

            MemoryPool* temp;

            while (firstPool != 0) {

                temp = firstPool;

                firstPool = firstPool->next;

                delete[] temp;

            }

            delete[] entry;

        }

 

        //分配大小为cnt*sizeof(T)的空间

 

        T* allocate(int cnt) {

            int size = cnt * sizeof (T);

 

            if (size > MAX_SIZE) {//大于MAX_SIZE采用普通的new

                return new T[cnt];

            }

 

            int index = size / 8; //确定分配入口

            if (entry[index] != 0) {//该入口是否有可分配的内存

                MemoryBlock* temp = entry[index];

                entry[index] = entry[index]->next;

                return (T*) temp;

            } else {//没有就向pool申请

                innerAlloc(index);

                allocate(cnt);

            }

        }

 

        void deallocate(T* ptr, int cnt) {

            int size = cnt * sizeof (T);

 

            if (size > MAX_SIZE) {

                delete[] ptr;

                return;

            }

 

            int index = size / 8;

            MemoryBlock* temp = (MemoryBlock*) ptr;

            temp->next = entry[index]; //将回收的内存块挂接到入口链首

            entry[index] = temp;

        }

 

        //构造一个T对象

 

        template<class T1>

        T* construct(T1 value1) {

            T* ptr = allocate(1);

            new(ptr) T(value1);

            return ptr;

        }

 

        //构造一个T对象

 

        template<class T1, class T2>

        void construct(T1 value1, T2 value2) {

            T* ptr = allocate(1);

            new(ptr) T(value1, value2);

            return ptr;

        }

 

        //销毁该对象

 

        void destruct(T* ptr) {

            ptr->~T();

            deallocate(ptr, 1);

        }

 

    private:

 

        void innerAlloc(int index) {

            int remain = firstPool->remain(); //获取当前pool的剩余块数

 

            if (index + 1 > remain) {//当申请的块数大于剩余块数

                if (remain > 0)//将剩余的块一次性分配给合适的入口

                    firstPool->alloc(remain - 1);

                extend(); //然后申请新的pool

                innerAlloc(index);

            } else {//满足申请时直接分配

                firstPool->alloc(index);

            }

 

        }

 

        void extend() {

            MemoryPool* newPool = new MemoryPool();

            newPool->next = firstPool;

            firstPool = newPool;

        }

 

    };

 

    template<class T>

    class Allocator<T>::MemoryBlock** Allocator<T>::entry = 0;

 

    template<class T>

    class Allocator<T>::MemoryPool* Allocator<T>::firstPool = 0;

}

 

 

#endif /* ALLOCATOR_H */

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值