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 }
原文地址:https://www.cnblogs.com/invisible/p/2438474.html