设为首页 加入收藏

TOP

仿SGI STL的一个allocator
2014-03-10 12:50:44 来源: 作者: 【 】 浏览:86
Tags:SGI  STL 一个 allocator
    仿SGI STL的一个allocator
    1 #ifndef _STL_ALLOC_H_
    2 #define _STL_ALLOC_H_
    3
    4 #include <cstddef>//for size_t, nullptr_t
    5 #include <cstdlib>//for exit(), malloc(), free()
    6
    7 namespace zstd
    8 {
    9     /*
    10     **this is the _malloc_alloc class
    11     */
    12     class _malloc_alloc
    13     {
    14     public:
    15         //分配size字节的内存空间
    16         inline static void* allocate(size_t bytes);
    17         //回收ptr指向的内存空间
    18         inline static void deallocate(void *ptr, size_t);
    19     };
    20     void* _malloc_alloc::allocate(size_t bytes)
    21     {
    22         void *result = nullptr;
    23
    24         result = (void*)malloc(bytes);
    25         if (!result)
    26             exit(-1);
    27         else
    28             return result;
    29     }
    30     void _malloc_alloc::deallocate(void *ptr, size_t)
    31     {
    32         free(ptr);
    33     }
    34     /*
    35     **this is the _default_alloc class
    36     */
    37     class _default_alloc
    38     {
    39     private:
    40         //小型区块的上调边界
    41         static const int ALIGN = 8;
    42         //小型区块的上限
    43         static const int MAX_BYTES = 128;
    44         //free-lists个数
    45         static const int FREELIST_NUMS = MAX_BYTES / ALIGN;
    46         //free-lists的节点构造
    47         union node
    48         {
    49             union node *free_list_link;
    50             char client_data ;
    51         };
    52
    53         static node *free_list[FREELIST_NUMS];
    54         //内存池起始的位置
    55         static char *start_of_memorypool;
    56         //内存池结束的位置
    57         static char *end_of_memorypool;
    58         //每次向内存池中注水时的水量修正值
    59         static int heap_size;
    60     private:
    61         //将bytes上调至ALIGN的倍数
    62         static size_t ROUND_UP(size_t bytes)
    63         {
    64             return (bytes + (ALIGN - 1)) & ~(ALIGN - 1);
    65         }
    66         //根据bytes大小决定使用第几个free-list,从0开始算起
    67         static size_t FREELIST_INDEX(size_t bytes)
    68         {
    69             //return ROUND_UP(bytes) / ALIGN - 1;
    70             return ((bytes)+ALIGN - 1) / ALIGN - 1;
    71         }
    72         //返回一个大小为bytes的对象,并可能加入大小为n的其他区块到free list
    73         static void *refill(size_t bytes);
    74         //配置一大块空间,可容纳nobjs个大小为bytes的区块
    75         //如果配置nobjs个区块有所不便,nobjs可能降低
    76         static char *chunk_alloc(size_t bytes, int &nobjs);
    77     public:
    78         //分配size字节的内存空间
    79         static void* allocate(size_t bytes);
    80         //回收ptr指向的内存空间
    81         static void deallocate(void *ptr, size_t n);
    82     };
    83     _default_alloc::node *_default_alloc::free_list[FREELIST_NUMS] =
    84     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
    85     char *_default_alloc::start_of_memorypool = nullptr;
    86     char *_default_alloc::end_of_memorypool = nullptr;
    87     int _default_alloc::heap_size = 0;
    88
    89     void *_default_alloc::allocate(size_t bytes)
    90     {
    91         node *result = nullptr;
    92         node **my_free_list = nullptr;
    93
    94         if (bytes > (size_t)MAX_BYTES)
    95             return _malloc_alloc::allocate(bytes);
    96
    97         my_free_list = free_list + FREELIST_INDEX(bytes);
    98         if(!*my_free_list)
    99         {
    100             void *r = refill(ROUND_UP(bytes));
    101             return r;
    102         }
    103         else
    104             result = *my_free_list;
    105         *my_free_list = result->free_list_link;
    106         return result;
    107     }
    108     void _default_alloc::deallocate(void *ptr, size_t n)
    109     {
    110         node *q = (node*)ptr;
    111         node **my_free_list = nullptr;
    112
    113         if(n > (size_t)MAX_BYTES)
    114             return _malloc_alloc::deallocate(ptr, n);
    115
    116         my_free_list = free_list + FREELIST_INDEX(n);
    117         q->free_list_link = *my_free_list;
    118         *my_free_list = q;
    119     }
    120     void *_default_alloc::refill(size_t bytes)
    121     {
    122         int nobjs = 20;
    123
    124         char *chunk = chunk_alloc(bytes, nobjs);
    125         node **my_free_list = nullptr;
    126         node *result = nullptr;
    127         node *cur, *next;
    128
    129         if(1 == nobjs)
    130             return chunk;
    131         result = (node*)chunk;
    132         my_free_list = free_list + FREELIST_INDEX(bytes);
    133         next = *my_free_list = (node*)(chunk + bytes);
    134
    135         for(int i = 1; ;++i)
    136         {
    137             cur = next;
    138             next = (node*)((char*)next + bytes);
    139             if(nobjs - 1 == i)
    140             {
    141                 cur->free_list_link = nullptr;
    142                 break;
    143             }
    144             else
    145                 cur->free_list_link = next;
    146         }
    147         return result;
    148     }
    149     char *_default_alloc::chunk_alloc(size_t bytes, int &nobjs)
    150     {
    151         char *result = nullptr;
    152         size_t total_bytes = bytes * nobjs;
    153         size_t bytes_left = end_of_memorypool - start_of_memorypool;
    154
    155         if(bytes_left >= total_bytes)
    156         {
    157             result = start_of_memorypool;
    158             start_of_memorypool += total_bytes;
    159             return result;
    160         }
    161         else if (bytes_left >= bytes)
    162         {
    163             nobjs = bytes_left / bytes;
    164             total_bytes = bytes * nobjs;
    165             result = start_of_memorypool;
    166             start_of_memorypool += total_bytes;
    167             return result;
    168         }
    169         else
    170         {
    171             size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size 》 4);
    172             if(bytes_left > 0)
    173             {
    174                 node **my_free_list = free_list + FREELIST_INDEX(bytes_left);
    175                 ((node*)start_of_memorypool)->free_list_link = *my_free_list;
    176                 *my_free_list = (node*)start_of_memorypool;
    177             }
    178             start_of_memorypool = (char*)malloc(bytes_to_get);
    179             if(nullptr == start_of_memorypool)
    180             {
    181                 node **my_free_list, *p;
    182                 for (int i = bytes; i <= MAX_BYTES; i += ALIGN)
    183                 {
    184                     my_free_list = free_list + FREELIST_INDEX(i);
    185                     p = *my_free_list;
    186                     if(nullptr != p)
    187                     {
    188                         *my_free_list = p->free_list_link;
    189                         start_of_memorypool = (char*)p;
    190                         end_of_memorypool = start_of_memorypool + i;
    191                         return chunk_alloc(bytes, nobjs);
    192                     }
    193                 }
    194                 end_of_memorypool = nullptr;
    195                 start_of_memorypool = (char*)_malloc_alloc::allocate(bytes_to_get);
    196             }
    197             heap_size += bytes_to_get;
    198             end_of_memorypool = start_of_memorypool + bytes_to_get;
    199             return chunk_alloc(bytes, nobjs);
    200         }
    201     }
    202
    203     #ifdef _USE_MALLOC_ALLOC_
    204         typedef _malloc_alloc    malloc_alloc;
    205         typedef malloc_alloc    alloc;
    206     #else
    207         typedef _default_alloc    default_alloc;
    208         typedef default_alloc    alloc;
    209     #endif
    210
    211
    212     template<class T, class Alloc>
    213     class simple_alloc
    214     {
    215     public:
    216         //分配能容纳n个T对象的内存空间
    217         static T *allocate(size_t n)
    218         {
    219             return 0 == n 0 : (T*)Alloc::allocate(n * sizeof(T));
    220         }
    221         //分配能容纳1个T对象的内存空间
    222         static T *allocate()
    223         {
    224             return (T*)Alloc::allocate(sizeof(T));
    225         }
    226         static void deallocate(T *ptr, size_t n)
    227         {
    228             if (0 != n)
    229                 Alloc::deallocate(ptr, n * sizeof(T));
    230         }
    231         static void deallocate(T *ptr)
    232         {
    233             Alloc::deallocate(ptr, sizeof(T));
    234         }
    235     };
    236 }//end of namespace
    237
    238 #endif

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇typedef 及其与struct的结合.. 下一篇vs2010 调试快捷键

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Libevent C++ 高并发 (2025-12-26 00:49:30)
·C++ dll 设计接口时 (2025-12-26 00:49:28)
·透彻理解 C 语言指针 (2025-12-26 00:22:52)
·C语言指针详解 (经典 (2025-12-26 00:22:49)
·C 指针 | 菜鸟教程 (2025-12-26 00:22:46)