首页 > 代码库 > STL源码剖析:空间配置器

STL源码剖析:空间配置器

看完自己重写了一下,不知道的又看了一遍,里面没有考虑多线程的问题,主要是想实现以下内存池。

Mempool.h


#ifndef MEMPOOL_H_
#define MEMPOOL_H_

#include <cstddef>
#include <new>
#include <cstdlib>

namespace flysnow {

enum {STEP_ = 8};
enum {MAX_BYTES_ = 128};
enum {FREELIST_NUM_ = MAX_BYTES_/STEP_};

class Mempool{

private:
    union pool_bucket {
        union pool_bucket* next_node;
        char bucket_addr[1];
    };
    static size_t up_to_nearest(size_t n) {
        return STEP_*((n>>3) + (n%8 ? 1:0));
    }

    static size_t freelist_index(size_t n) {
        return ((n>>3) + (n%8 ? 0:-1));
    }

    static void* refill(size_t n);
    static char* alloc_memory(size_t size,int &pool_node_num);

    static pool_bucket* free_list_[FREELIST_NUM_];
    static char* start_pool;
    static char* end_pool;
    static size_t heap_size;


public:
    static void* allocate(size_t n);
    static void deallocate(void *p,size_t n);
    static size_t get_heap_size() {return heap_size;}
};

}
#endif


Mempool.cpp

#include "mempool.h"

namespace flysnow{

char* Mempool::start_pool = 0;
char* Mempool::end_pool = 0;
size_t Mempool::heap_size = 0;
Mempool::pool_bucket* Mempool::free_list_[FREELIST_NUM_] =
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void* Mempool::allocate(size_t n) {
    if(n > MAX_BYTES_){
        return malloc(n);
    }
    pool_bucket *p;
    pool_bucket **free_list_index = free_list_ + freelist_index(n);
    p = *free_list_index;
    if(0 == p) {
        void *q = refill(up_to_nearest(n));
        return q;
    }
    *free_list_index = p->next_node;
    return p;
}

void Mempool::deallocate(void *p,size_t n) {
    pool_bucket *q = (pool_bucket*)p;
    if(n > MAX_BYTES_) {
        free(p);
        return ;
    }
    pool_bucket **free_list_index = free_list_ + freelist_index(n);

    q->next_node = *free_list_index;
    *free_list_index = q;
}

void* Mempool::refill(size_t n) {
    int pool_node_num = 20;
    int i;
    pool_bucket **free_list_index = free_list_ + freelist_index(n);
    char *pool = alloc_memory(n,pool_node_num);
    if(1 == pool_node_num) {
        return pool;
    }

    pool_bucket *result = (pool_bucket*)pool;
    pool_bucket *current,*next;
    pool += n;
    *free_list_index = next = (pool_bucket*)pool;
    next = (pool_bucket*)pool;
    for(i=1; ;++i){
        current = next;
        next = (pool_bucket*)((char*)next + n);
        if(pool_node_num - 1 == i){
            current->next_node = NULL;
            break;
        } else {
            current->next_node = next;
        }
    }
    return result;
}


char* Mempool::alloc_memory(size_t size,int &pool_node_num) {
    size_t total_size = size*pool_node_num;
    size_t remain_size = end_pool - start_pool;
    if(total_size <= remain_size) {
        char* result = start_pool;
        start_pool += total_size;
        return result;
    } else if(remain_size >= size) {
        pool_node_num = remain_size/size;
        size_t return_size = pool_node_num*size;
        char *result = start_pool;
        start_pool += return_size;
        return result;
    } else {
        size_t get_size = 2*total_size + up_to_nearest(heap_size>>4);
        if(remain_size > 0) {
            //如果剩余7byte,此处会放在8byte的自由链表中,然而,最后allocate 8byte的
            //时候,岂不会出错?
            //原来之前get_size分配的内存总是8的倍数,因此不会出现以上情况。。。。
            pool_bucket **free_list_index = free_list_ + freelist_index(remain_size);
            ((pool_bucket*)start_pool)->next_node = *free_list_index;
            *free_list_index = (pool_bucket*)start_pool;
        }

        start_pool = (char*)malloc(get_size);
        if(0 == start_pool) {
            pool_bucket **free_list_index;
            pool_bucket *p;
            for(int i=size;i<=MAX_BYTES_;i+=STEP_) {
                free_list_index = free_list_ + freelist_index(i);
                p = *free_list_index;
                if(0 != p) {
                    *free_list_index = p->next_node;
                    start_pool = (char*)p;
                    end_pool = start_pool + i;
                    return (alloc_memory(size,pool_node_num));
                }
            }
            end_pool = 0;
            start_pool = (char*)malloc(get_size);
        }

        heap_size += get_size;
        end_pool = start_pool + get_size;
        //return (alloc_memory(size,pool_node_num));
        char *result = start_pool;
        start_pool += total_size;
        return result;
    }


}

}


main.cpp

#include <iostream>
#include "mempool.h"

using namespace std;

int main()
{
    char *p;
    for(size_t i=0;i<100000;++i){
       p = (char*)flysnow::Mempool::allocate(i%1029+1);
       cout<<flysnow::Mempool::get_heap_size()<<' ';
    }
    cout << endl;
    system("PAUSE");
    return 0;
}



STL源码剖析:空间配置器