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     try
00095       {
00096         _S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
00097       }
00098     catch (...)
00099       {
00100         // Try to make do with what we have.  That can't hurt.  We
00101         // do not try smaller requests, since that tends to result
00102         // in disaster on multi-process machines.
00103         size_t __i = __n;
00104         for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align)
00105           {
00106         _Obj* volatile* __free_list = _M_get_free_list(__i);
00107         _Obj* __p = *__free_list;
00108         if (__p != 0)
00109           {
00110             *__free_list = __p->_M_free_list_link;
00111             _S_start_free = (char*)__p;
00112             _S_end_free = _S_start_free + __i;
00113             return _M_allocate_chunk(__n, __nobjs);
00114             // Any leftover piece will eventually make it to the
00115             // right free list.
00116           }
00117           }
00118         // What we have wasn't enough.  Rethrow.
00119         _S_start_free = _S_end_free = 0;   // We have no chunk.
00120         __throw_exception_again;
00121       }
00122     _S_heap_size += __bytes_to_get;
00123     _S_end_free = _S_start_free + __bytes_to_get;
00124     return _M_allocate_chunk(__n, __nobjs);
00125       }
00126   }
00127   
00128   // Returns an object of size __n, and optionally adds to "size
00129   // __n"'s free list.  We assume that __n is properly aligned.  We
00130   // hold the allocation lock.
00131   void*
00132   __pool_alloc_base::_M_refill(size_t __n)
00133   {
00134     int __nobjs = 20;
00135     char* __chunk = _M_allocate_chunk(__n, __nobjs);
00136     _Obj* volatile* __free_list;
00137     _Obj* __result;
00138     _Obj* __current_obj;
00139     _Obj* __next_obj;
00140     
00141     if (__nobjs == 1)
00142       return __chunk;
00143     __free_list = _M_get_free_list(__n);
00144     
00145     // Build free list in chunk.
00146     __result = (_Obj*)(void*)__chunk;
00147     *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n);
00148     for (int __i = 1; ; __i++)
00149       {
00150     __current_obj = __next_obj;
00151     __next_obj = (_Obj*)(void*)((char*)__next_obj + __n);
00152     if (__nobjs - 1 == __i)
00153       {
00154         __current_obj->_M_free_list_link = 0;
00155         break;
00156       }
00157     else
00158       __current_obj->_M_free_list_link = __next_obj;
00159       }
00160     return __result;
00161   }
00162 
00163   __pool_alloc_base::_Obj* volatile __pool_alloc_base::_S_free_list[_S_free_list_size];
00164   
00165   char* __pool_alloc_base::_S_start_free = 0;
00166   
00167   char* __pool_alloc_base::_S_end_free = 0;
00168   
00169   size_t __pool_alloc_base::_S_heap_size = 0;
00170 } // namespace __gnu_cxx

Generated on Fri May 6 01:08:51 2005 for libstdc++-v3 Source by  doxygen 1.4.2