Sgistl default use of the two-level space Configurator, when the need to configure the chunk is greater than bytes when SGI STL calls the first-level space Configurator, the allocate function of the first-level space Configurator allocates memory directly using malloc, and the DEALLOCATE function frees memory directly using free. SGI STL calls a level two space Configurator when the chunk that needs to be configured is less than bytes.
The two-level space Configurator has a much finer memory use than a simple, rough memory usage of the first-level space Configurator.
The specific usage of the second-level space Configurator Please read a book, I will not transcription, only to the two-level space Configurator easily confused place to write my understanding.
What does the memory pool and free_list really matter?
The second-level space Configurator maintains a pool of memory, and an array named Free_list is responsible for managing the pool of memory. Each element of the Free_list constitutes a linked list, the same amount of memory that each element of the same list points to, and the memory size <= the memory pool to which all the linked list nodes of Free_list point.
I guess there are two reasons to use an array instead of a linked list: 1. The second-level space configurator divides the memory pool into fixed 16 size classes, i.e. the length of the Free_list (16) is fixed, and 2. Since the length of the free_list is fixed then the use of arrays is undoubtedly a more efficient method of time (O (1)), if the list is used, free_ The query efficiency of list is O (n).
Yes, I understand. Two-level Space Configurator execution process, time relationship, not drawing program flowchart.
1. The two-level space Configurator calls the ALLOCATE function when requesting memory, and if the requested memory is greater than 128 bytes, call the first-level space Configurator, otherwise allocate the free_list array, and then returns after taking a chunk of memory from the linked list to which an element in Free_list is pointing.
2. Call the refill function when Free_list does not have a suitable memory chunk.
3. Refill calls _s_chunk_alloc,_s_chunk_alloc to allocate a memory pool for memory, and to free_list the remaining space in the memory pool.
4. _s_chunk_alloc call finished, back to Refill,refill free_list array, from the free_list of an element point to the list of the link to take a piece of memory back to the allocate,allocate and return to the client.
Source code for the _s_chunk_alloc function:
Template <bool __threads, int __inst>char*__default_alloc_template<__threads,__inst>::_s_chunk_alloc ( size_t __size, Int&__nobjs) {char* __result; size_t __total_bytes = __size * __NOBJS; size_t __bytes_left = _s_end_free-_s_start_free; Memory Pool remaining space if (__bytes_left >= __total_bytes) {///memory pool remaining space fully satisfies the demand __result= _s_start_free; _s_start_free+= __total_bytes; return (__result); The else if (__bytes_left >= __size) {///memory pool remaining space does not fully meet the requirements but is sufficient to supply one (inclusive) chunk __nobjs= (int) (__bytes_left/__size); __total_bytes= __size * __NOBJS; __result= _s_start_free; _s_start_free+= __total_bytes; return (__result); } else {//memory pool remaining space cannot be supplied with a chunk size size_t __bytes_to_get = 2 *__total_bytes + _s_round_up (_s_heap_size >> 4); Try to make use of the left-over piece. Take advantage of some of the remaining small remnants of the current memory pool. if (__bytes_left > 0) {_obj*__stl_volatile* __my_free_list = _s_free_list+ _s_freelist_index (__bytes_left); Is this right? If __bytes_left = 15, then _s_freelist_index (15) = 1,//1 6B position, and actually only 15B left? ((_obj*) _s_start_free), _m_free_list_link = *__my_free_list; *__my_free_list= (_obj*) _s_start_free; } _s_start_free= (char*) malloc (__bytes_to_get); if (0 = = _s_start_free) {size_t __i; _obj*__stl_volatile* __my_free_list; _obj*__p; Try to make does with the. That can ' t//hurt. We do not try smaller requests, since this tends//to result in disaster on multi-process machines. for (__i = __size; __i<= (size_t) _max_bytes; __i+= (size_t) _align) {__my_free_list= _s_free_list + _s_freelist_index (__i); __p= *__my_free_list; if (0! = __p) {*__my_free_list= __p-_m_free_list_link; _s_start_free= (char*) __p; _s_end_free= _s_start_free + __i; Does this make sure that each piece of memory is __i? Return (_s_chunk_alloc (__SIZE,__NOBJS)); Any leftover piece would eventually make it to the//right free list. }} _s_end_free= 0; In case of exception. _s_start_free= (char*) malloc_alloc::allocate (__bytes_to_get); This should either throw a//exception or remedy the situation. Thus we assume it//succeeded. } _s_heap_size+= __bytes_to_get; _s_end_free= _s_start_free + __bytes_to_get; Return (_s_chunk_alloc (__SIZE,__NOBJS)); }}
You can see that there are two inputs for the CHUNK_ALLOC function: 1. INT&__NOBJS, number of elements to be allocated; 2. size_t __size, the size of each element.
The program flowchart of the Chunk_alloc function (for easy observation, the drawing is not a standard program flowchart) as follows:
The Chunk_alloc function of the 2.SGI STL second-level space Configurator __default_alloc_template