allocator.cc

00001 // Allocator details. 00002 00003 // Copyright (C) 2004 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License along 00017 // with this library; see the file COPYING. If not, write to the Free 00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00019 // USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 // 00031 // ISO C++ 14882: 00032 // 00033 00034 #include <bits/c++config.h> 00035 #include <memory> 00036 #include <ext/mt_allocator.h> 00037 #include <ext/pool_allocator.h> 00038 00039 namespace __gnu_internal 00040 { 00041 __glibcxx_mutex_define_initialized(palloc_init_mutex); 00042 } 00043 00044 namespace __gnu_cxx 00045 { 00046 // Definitions for __pool_alloc_base. 00047 __pool_alloc_base::_Obj* volatile* 00048 __pool_alloc_base::_M_get_free_list(size_t __bytes) 00049 { 00050 size_t __i = ((__bytes + (size_t)_S_align - 1) / (size_t)_S_align - 1); 00051 return _S_free_list + __i; 00052 } 00053 00054 mutex_type& 00055 __pool_alloc_base::_M_get_mutex() 00056 { return __gnu_internal::palloc_init_mutex; } 00057 00058 // Allocate memory in large chunks in order to avoid fragmenting the 00059 // heap too much. Assume that __n is properly aligned. We hold the 00060 // allocation lock. 00061 char* 00062 __pool_alloc_base::_M_allocate_chunk(size_t __n, int& __nobjs) 00063 { 00064 char* __result; 00065 size_t __total_bytes = __n * __nobjs; 00066 size_t __bytes_left = _S_end_free - _S_start_free; 00067 00068 if (__bytes_left >= __total_bytes) 00069 { 00070 __result = _S_start_free; 00071 _S_start_free += __total_bytes; 00072 return __result ; 00073 } 00074 else if (__bytes_left >= __n) 00075 { 00076 __nobjs = (int)(__bytes_left / __n); 00077 __total_bytes = __n * __nobjs; 00078 __result = _S_start_free; 00079 _S_start_free += __total_bytes; 00080 return __result; 00081 } 00082 else 00083 { 00084 // Try to make use of the left-over piece. 00085 if (__bytes_left > 0) 00086 { 00087 _Obj* volatile* __free_list = _M_get_free_list(__bytes_left); 00088 ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list; 00089 *__free_list = (_Obj*)(void*)_S_start_free; 00090 } 00091 00092 size_t __bytes_to_get = (2 * __total_bytes 00093 + _M_round_up(_S_heap_size >> 4)); 00094 _S_start_free = static_cast<char*>(::operator new(__bytes_to_get)); 00095 if (_S_start_free == 0) 00096 { 00097 // Try to make do with what we have. That can't hurt. We 00098 // do not try smaller requests, since that tends to result 00099 // in disaster on multi-process machines. 00100 size_t __i = __n; 00101 for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) 00102 { 00103 _Obj* volatile* __free_list = _M_get_free_list(__i); 00104 _Obj* __p = *__free_list; 00105 if (__p != 0) 00106 { 00107 *__free_list = __p->_M_free_list_link; 00108 _S_start_free = (char*)__p; 00109 _S_end_free = _S_start_free + __i; 00110 return _M_allocate_chunk(__n, __nobjs); 00111 // Any leftover piece will eventually make it to the 00112 // right free list. 00113 } 00114 } 00115 _S_end_free = 0; // In case of exception. 00116 00117 // This should either throw an exception or remedy the situation. 00118 // Thus we assume it succeeded. 00119 _S_start_free = static_cast<char*>(::operator new(__bytes_to_get)); 00120 } 00121 _S_heap_size += __bytes_to_get; 00122 _S_end_free = _S_start_free + __bytes_to_get; 00123 return _M_allocate_chunk(__n, __nobjs); 00124 } 00125 } 00126 00127 // Returns an object of size __n, and optionally adds to "size 00128 // __n"'s free list. We assume that __n is properly aligned. We 00129 // hold the allocation lock. 00130 void* 00131 __pool_alloc_base::_M_refill(size_t __n) 00132 { 00133 int __nobjs = 20; 00134 char* __chunk = _M_allocate_chunk(__n, __nobjs); 00135 _Obj* volatile* __free_list; 00136 _Obj* __result; 00137 _Obj* __current_obj; 00138 _Obj* __next_obj; 00139 00140 if (__nobjs == 1) 00141 return __chunk; 00142 __free_list = _M_get_free_list(__n); 00143 00144 // Build free list in chunk. 00145 __result = (_Obj*)(void*)__chunk; 00146 *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); 00147 for (int __i = 1; ; __i++) 00148 { 00149 __current_obj = __next_obj; 00150 __next_obj = (_Obj*)(void*)((char*)__next_obj + __n); 00151 if (__nobjs - 1 == __i) 00152 { 00153 __current_obj->_M_free_list_link = 0; 00154 break; 00155 } 00156 else 00157 __current_obj->_M_free_list_link = __next_obj; 00158 } 00159 return __result; 00160 } 00161 00162 __pool_alloc_base::_Obj* volatile __pool_alloc_base::_S_free_list[_S_free_list_size]; 00163 00164 char* __pool_alloc_base::_S_start_free = 0; 00165 00166 char* __pool_alloc_base::_S_end_free = 0; 00167 00168 size_t __pool_alloc_base::_S_heap_size = 0; 00169 } // namespace __gnu_cxx

Generated on Tue Sep 7 10:05:00 2004 for libstdc++-v3 Source by doxygen 1.3.8