zoukankan      html  css  js  c++  java
  • sgistl2.91.57 之内存池

      代码还是比较简单的,加个main函数多调试几次,自然就知道是什么意思了。

      重点在于chunk_alloc这个函数里面的递归调用。

    C++语言: Codee#25985
    001 /*
    002 简言之,一个链表数组加一个内存池
    003 先在数组中找,找不到就向内存池要,如果池子空了,再向系统申请
    004 */
    005
    006 #include <cstdlib>
    007 #include <iostream>
    008 using namespace std;
    009
    010 enum
    011 {
    012     __ALIGN = 8
    013 };
    014
    015 enum
    016 {
    017     __MAX_BYTES = 128
    018 };
    019
    020 enum
    021 {
    022     __NFREELISTS = __MAX_BYTES / __ALIGN
    023 };
    024
    025 template <bool threads, int inst>
    026 class __default_alloc_template
    027 {
    028 private:
    029     static size_t ROUND_UP(size_t bytes)
    030     {
    031         return (((bytes) + __ALIGN - 1) & ~(__ALIGN - 1));
    032     }
    033
    034     union obj
    035     {
    036         union obj* free_list_link;
    037         char client_data[1];
    038     };
    039
    040     /*
    041        链表数组
    042        */
    043     static obj* volatile free_list[__NFREELISTS];
    044
    045     static size_t FREELIST_INDEX(size_t bytes)
    046     {
    047         return (((bytes) + __ALIGN - 1) / __ALIGN - 1);
    048     }
    049
    050     static void* refill(size_t n);
    051     static char* chunk_alloc(size_t size, int& nobjs);
    052
    053
    054     static char* start_free;    //内存池起始地址
    055     static char* end_free;        //内存池结束地址
    056     static size_t heap_size;    //堆大小(到目前为止总共向系统申请的内存)
    057
    058 public:
    059     void special_access(size_t sz, int n)
    060     {
    061         chunk_alloc(sz, n);
    062     }
    063
    064     static void* allocate(size_t n)
    065     {
    066         obj* volatile* my_free_list;
    067         obj* result;
    068
    069         if (n > (size_t) __MAX_BYTES)
    070     /*
    071             return malloc_alloc::allocate(n);
    072     */
    073             return malloc((size_t)n);
    074
    075         my_free_list = free_list + FREELIST_INDEX(n);
    076         result = *my_free_list;
    077         /*
    078            数组中对应项为空表
    079            */
    080         if (0 == result)
    081         {
    082             /*
    083                申请内存,并填充对应表项
    084                */
    085             void* r = refill(ROUND_UP(n));
    086             return r;
    087         }
    088
    089         /*
    090            修改表项值
    091            */
    092         *my_free_list = result->free_list_link;
    093         return result;
    094     }
    095
    096     static void deallocate(void* p, size_t n)
    097     {
    098         obj* q = (obj*)p;
    099         obj* volatile* my_free_list;
    100
    101         if (n > (size_t) __MAX_BYTES)
    102         {
    103     /*
    104             malloc_alloc::deallocate(p, n);
    105     */
    106             free(p);
    107             return ;
    108         }
    109
    110         /*
    111            归还内存,插入对应链表表头处
    112            */
    113
    114         my_free_list = free_list + FREELIST_INDEX(n);
    115         q->free_list_link = *my_free_list;
    116         *my_free_list = q;
    117     }
    118
    119     static void* reallocate(void* p, size_t old_sz, size_t new_sz);
    120 };
    121
    122 template <bool threads, int inst>
    123 char* __default_alloc_template<threads, inst>::start_free = 0;
    124
    125 template <bool threads, int inst>
    126 char* __default_alloc_template<threads, inst>::end_free = 0;
    127
    128 template <bool threads, int inst>
    129 size_t __default_alloc_template<threads, inst>::heap_size = 0;
    130
    131 /*
    132    sgi-stl-2.91.57中原来的代码,现无法通过编译
    133    注意此处的typename 具体解释见此处:
    134    http://stackoverflow.com/questions/610245/
    135    where-and-why-do-i-have-to-put-the-template-and-typename-keywords
    136    */
    137 template <bool threads, int inst>
    138 typename __default_alloc_template<threads,inst>::obj* volatile
    139 __default_alloc_template<threads, inst>::free_list[__NFREELISTS] =
    140 {
    141     0, 0, 0, 0,
    142     0, 0, 0, 0,
    143     0, 0, 0, 0,
    144     0, 0, 0, 0
    145 };
    146
    147 template <bool threads, int inst>
    148 void* __default_alloc_template<threads, inst>::refill(size_t n)
    149 {
    150     int nobjs = 20;
    151     /*
    152        申请内存块
    153        */
    154     char* chunk = chunk_alloc(n, nobjs);
    155     obj* volatile* my_free_list;
    156     obj* result;
    157     obj* current_obj, *next_obj;
    158     int i;
    159
    160     if (1 == nobjs)
    161         return chunk;
    162     my_free_list = free_list + FREELIST_INDEX(n);
    163     result = (obj*)chunk;                            //第一块拿来用
    164     *my_free_list = next_obj = (obj*)(chunk + n);    //剩下的插入到对应大小的链表中
    165
    166     /*
    167        建立链表,还是头插法
    168        */
    169     for (i = 1;; ++i)
    170     {
    171         current_obj = next_obj;
    172         next_obj = (obj*)((char*)next_obj + n);
    173         if (i == nobjs - 1)
    174         {
    175             current_obj->free_list_link = 0;
    176             break;
    177         }
    178         else
    179             current_obj->free_list_link = next_obj;
    180     }
    181     return result;
    182 }
    183
    184 /*
    185 */
    186 template<bool threads, int inst>
    187 char* __default_alloc_template<threads, inst>
    188 ::chunk_alloc(size_t size, int& nobjs)
    189 {
    190     /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    191     char*    result;
    192     size_t total_bytes = size * nobjs;
    193     size_t bytes_left = end_free - start_free;
    194     /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    195
    196     if (bytes_left >= total_bytes)
    197     {
    198         result = start_free;
    199         start_free += total_bytes;
    200         return(result);
    201     }
    202     else if (bytes_left >= size)
    203     {
    204         /*
    205            nobjs引用传参
    206            为的就是内存只够1块以上又不够20块分配,
    207            在此处修改为实际上分配到的块数
    208            */
    209
    210         nobjs = bytes_left / size;
    211         total_bytes = size * nobjs;
    212         result = start_free;
    213         start_free += total_bytes;
    214         return(result);
    215     }
    216     else
    217     {
    218         /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    219         size_t bytes_to_get = 2 * total_bytes + ROUND_UP (heap_size >> 4);
    220         /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    221
    222         /*
    223          * Try to make use of the
    224          * left-over piece.
    225          */
    226         if (bytes_left > 0)
    227         {
    228             obj* volatile* my_free_list = free_list + FREELIST_INDEX (bytes_left);
    229             ((obj*) start_free)->free_list_link = *my_free_list;
    230             *my_free_list = (obj*) start_free;
    231         }
    232
    233         start_free = (char*) malloc (bytes_to_get);
    234         if (0 == start_free)
    235         {
    236             /*~~*/
    237             int i;
    238             /*~~*/
    239
    240             obj* volatile* my_free_list, *p;
    241
    242             /*
    243              * Try to make do with
    244              * what we have. That
    245              * can't ;
    246              * hurt. We do not try
    247              * smaller requests,
    248              * since that tends ;
    249              * to result in disaster
    250              * on multi-process
    251              * machines.
    252              */
    253             /*
    254                申请不到内存,只好在原来的链表中找找看
    255                有一点就用一点
    256                */
    257             for (i = size; i <= __MAX_BYTES; i += __ALIGN)
    258             {
    259                 my_free_list = free_list + FREELIST_INDEX (i);
    260                 p = *my_free_list;
    261                 if (0 != p)
    262                 {
    263                     *my_free_list = p->free_list_link;
    264                     start_free = (char*) p;
    265                     end_free = start_free + i;
    266                     return(chunk_alloc (size, nobjs));
    267
    268                     /*
    269                      * Any leftover
    270                      * piece will
    271                      * eventually
    272                      * make it to the ;
    273                      * right free
    274                      * list.
    275                      */
    276                 }
    277             }
    278
    279             end_free = 0;    /* In case of exception. */
    280             start_free = (char*) malloc(bytes_to_get);
    281
    282             /*
    283              * This should either
    284              * throw an ;
    285              * exception or remedy
    286              * the situation. Thus we
    287              * assume it ;
    288              * succeeded.
    289              */
    290         }
    291
    292         heap_size += bytes_to_get;
    293         end_free = start_free + bytes_to_get;
    294         return(chunk_alloc (size, nobjs));
    295     }
    296 }
    297
    298 int main()
    299 {
    300     /*
    301     *    just test,debug to see how it works
    302     */
    303     __default_alloc_template<false, 1> my_alloc;
    304
    305     for (int i = 0; i < 1024; ++i)
    306     {
    307         int x = rand() % 128+1;
    308         my_alloc.allocate(x);
    309     }
    310
    311     return 0;
    312 }
  • 相关阅读:
    [WPF系列] window自定义
    [WPF系列]-Prism+EF
    C#基础-事件 继承类无法直接引发基类的事件
    [WPF系列] 高级 调试
    [WPF系列]-DynamicResource与StaticResource的区别
    [WPF系列]-DataBinding 绑定计算表达式
    [WPF系列]- Style
    [WPF系列]-基础 TextBlock
    [WPF系列]-ListBox
    [WPF系列]-DataBinding 枚举类型数据源
  • 原文地址:https://www.cnblogs.com/invisible/p/2438474.html
Copyright © 2011-2022 走看看