内存池模型设计探讨二

链表方式的内存管理特点是可以管理足够多的对象(对象的数量依赖指针的范围),不足的地方是无法精确的满足小内存块的申请,例如1字节、2字节大小的对象,因为链表节点指针是4字节(32位平台)。

我们可以通过简单的算法避免这种情况,例如宏:

#define ALLOC_ROUNDUP(X, Y) ((X)+((Y)-1)&~((Y)-1)),我们可以采用这个宏调整block_size,使用户的对象大小保持在某个值的倍数,前面的构造函数可以修改为:

DataBlock::DataBlock(size_type block_size)

{

       block_size_ = ALLOC_ROUNDUP(block_size_, 4);

       base_addr_  = new unsigned char[block_size_ * MAX_BLOCKS];

       /*初始化,生成链表*/

       NodePtr node = head_node_ = (NodePtr)base_addr_;

       head_node_->next_ = end_node();

       for (size_type n = 1; n < MAX_BLOCKS; n++) {

              node->next_ = (NodePtr)(base_addr_ + n*block_size_);

              node = node->next_;

              node->next_ = end_node();

       }

}

红字部分是增加的代码,它使block_size_调整为4的倍数,这个算法也能避免字节边界的问题。

虽然通过调整block_size_使我们的内存管理器看上去适应性更强,但是如果用户对内存的需求小内存块比较多,那么我们链表方式的内存管理器会浪费更多的内存。下面的小对象内存分配方式是采用《C++设计新思维》里面的方式,在这本书里面作者采用对对象前一个字节进行添加计数的方式进行管理,一个字节最大值255,那么采用这种方式用户对象申请数量最大上限为255,下面代码摘录于《C++设计新思维》供大家参考:

struct Chunk

{

void Init(std::size_t blockSize, unsigned char blocks);

void* Allocate(std::size_t blockSize);

void Deallocate(void* p, std::size_t blockSize);

void Reset(std::size_t blockSize, unsigned char blocks);

void Release();

unsigned char* pData_;

unsigned char

firstAvailableBlock_,

blocksAvailable_;

};

Chunk::Init(std::size_t blockSize, unsigned char blocks)

{

    pData_ = new unsigned char[blockSize * blocks];

    Reset(blockSize, blocks);

}

Chunk::Reset(std::size_t blockSize, unsigned char blocks)

{

    firstAvailableBlock_ = 0;

    blocksAvailable_ = blocks;

 

    unsigned char i = 0;

    unsigned char* p = pData_;

    for (; i != blocks; p += blockSize)

    {

        *p = ++i;

    }

}

Reset方法里面作者对申请的代码进行分段计数,它的内存分配和回收方法分别为:

Void *Chunk::Allocate(std::size_t blockSize)

{

    if (!blocksAvailable_) return 0;

   

    assert((firstAvailableBlock_ * blockSize) / blockSize ==

        firstAvailableBlock_);

 

    unsigned char* pResult =

        pData_ + (firstAvailableBlock_ * blockSize);

    firstAvailableBlock_ = *pResult;

    --blocksAvailable_;

   

    return pResult;

}

Void Chunk::Deallocate(void* p, std::size_t blockSize)

{

    assert(p >= pData_);

 

    unsigned char* toRelease = static_cast<unsigned char*>(p);

    // Alignment check

    assert((toRelease - pData_) % blockSize == 0);

 

    *toRelease = firstAvailableBlock_;

    firstAvailableBlock_ = static_cast<unsigned char>(

        (toRelease - pData_) / blockSize);

    // Truncation check

    assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);

 

    ++blocksAvailable_;

}

《未完待续......》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值