xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/src/c++98/pool_allocator.cc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // Allocator details.
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino // any later version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*e4b17023SJohn Marino // GNU General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino //
26*e4b17023SJohn Marino // ISO C++ 14882:
27*e4b17023SJohn Marino //
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino #include <bits/c++config.h>
30*e4b17023SJohn Marino #include <cstdlib>
31*e4b17023SJohn Marino #include <ext/pool_allocator.h>
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino namespace
34*e4b17023SJohn Marino {
35*e4b17023SJohn Marino   __gnu_cxx::__mutex&
get_palloc_mutex()36*e4b17023SJohn Marino   get_palloc_mutex()
37*e4b17023SJohn Marino   {
38*e4b17023SJohn Marino     static __gnu_cxx::__mutex palloc_mutex;
39*e4b17023SJohn Marino     return palloc_mutex;
40*e4b17023SJohn Marino   }
41*e4b17023SJohn Marino } // anonymous namespace
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
44*e4b17023SJohn Marino {
45*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino   // Definitions for __pool_alloc_base.
48*e4b17023SJohn Marino   __pool_alloc_base::_Obj* volatile*
_M_get_free_list(size_t __bytes)49*e4b17023SJohn Marino   __pool_alloc_base::_M_get_free_list(size_t __bytes) throw ()
50*e4b17023SJohn Marino   {
51*e4b17023SJohn Marino     size_t __i = ((__bytes + (size_t)_S_align - 1) / (size_t)_S_align - 1);
52*e4b17023SJohn Marino     return _S_free_list + __i;
53*e4b17023SJohn Marino   }
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino   __mutex&
_M_get_mutex()56*e4b17023SJohn Marino   __pool_alloc_base::_M_get_mutex() throw ()
57*e4b17023SJohn Marino   { return get_palloc_mutex(); }
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino   // Allocate memory in large chunks in order to avoid fragmenting the
60*e4b17023SJohn Marino   // heap too much.  Assume that __n is properly aligned.  We hold the
61*e4b17023SJohn Marino   // allocation lock.
62*e4b17023SJohn Marino   char*
_M_allocate_chunk(size_t __n,int & __nobjs)63*e4b17023SJohn Marino   __pool_alloc_base::_M_allocate_chunk(size_t __n, int& __nobjs)
64*e4b17023SJohn Marino   {
65*e4b17023SJohn Marino     char* __result;
66*e4b17023SJohn Marino     size_t __total_bytes = __n * __nobjs;
67*e4b17023SJohn Marino     size_t __bytes_left = _S_end_free - _S_start_free;
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino     if (__bytes_left >= __total_bytes)
70*e4b17023SJohn Marino       {
71*e4b17023SJohn Marino 	__result = _S_start_free;
72*e4b17023SJohn Marino 	_S_start_free += __total_bytes;
73*e4b17023SJohn Marino 	return __result ;
74*e4b17023SJohn Marino       }
75*e4b17023SJohn Marino     else if (__bytes_left >= __n)
76*e4b17023SJohn Marino       {
77*e4b17023SJohn Marino 	__nobjs = (int)(__bytes_left / __n);
78*e4b17023SJohn Marino 	__total_bytes = __n * __nobjs;
79*e4b17023SJohn Marino 	__result = _S_start_free;
80*e4b17023SJohn Marino 	_S_start_free += __total_bytes;
81*e4b17023SJohn Marino 	return __result;
82*e4b17023SJohn Marino       }
83*e4b17023SJohn Marino     else
84*e4b17023SJohn Marino       {
85*e4b17023SJohn Marino 	// Try to make use of the left-over piece.
86*e4b17023SJohn Marino 	if (__bytes_left > 0)
87*e4b17023SJohn Marino 	  {
88*e4b17023SJohn Marino 	    _Obj* volatile* __free_list = _M_get_free_list(__bytes_left);
89*e4b17023SJohn Marino 	    ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list;
90*e4b17023SJohn Marino 	    *__free_list = (_Obj*)(void*)_S_start_free;
91*e4b17023SJohn Marino 	  }
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino 	size_t __bytes_to_get = (2 * __total_bytes
94*e4b17023SJohn Marino 				 + _M_round_up(_S_heap_size >> 4));
95*e4b17023SJohn Marino 	__try
96*e4b17023SJohn Marino 	  {
97*e4b17023SJohn Marino 	    _S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
98*e4b17023SJohn Marino 	  }
99*e4b17023SJohn Marino 	__catch(const std::bad_alloc&)
100*e4b17023SJohn Marino 	  {
101*e4b17023SJohn Marino 	    // Try to make do with what we have.  That can't hurt.  We
102*e4b17023SJohn Marino 	    // do not try smaller requests, since that tends to result
103*e4b17023SJohn Marino 	    // in disaster on multi-process machines.
104*e4b17023SJohn Marino 	    size_t __i = __n;
105*e4b17023SJohn Marino 	    for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align)
106*e4b17023SJohn Marino 	      {
107*e4b17023SJohn Marino 		_Obj* volatile* __free_list = _M_get_free_list(__i);
108*e4b17023SJohn Marino 		_Obj* __p = *__free_list;
109*e4b17023SJohn Marino 		if (__p != 0)
110*e4b17023SJohn Marino 		  {
111*e4b17023SJohn Marino 		    *__free_list = __p->_M_free_list_link;
112*e4b17023SJohn Marino 		    _S_start_free = (char*)__p;
113*e4b17023SJohn Marino 		    _S_end_free = _S_start_free + __i;
114*e4b17023SJohn Marino 		    return _M_allocate_chunk(__n, __nobjs);
115*e4b17023SJohn Marino 		    // Any leftover piece will eventually make it to the
116*e4b17023SJohn Marino 		    // right free list.
117*e4b17023SJohn Marino 		  }
118*e4b17023SJohn Marino 	      }
119*e4b17023SJohn Marino 	    // What we have wasn't enough.  Rethrow.
120*e4b17023SJohn Marino 	    _S_start_free = _S_end_free = 0;   // We have no chunk.
121*e4b17023SJohn Marino 	    __throw_exception_again;
122*e4b17023SJohn Marino 	  }
123*e4b17023SJohn Marino 	_S_heap_size += __bytes_to_get;
124*e4b17023SJohn Marino 	_S_end_free = _S_start_free + __bytes_to_get;
125*e4b17023SJohn Marino 	return _M_allocate_chunk(__n, __nobjs);
126*e4b17023SJohn Marino       }
127*e4b17023SJohn Marino   }
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino   // Returns an object of size __n, and optionally adds to "size
130*e4b17023SJohn Marino   // __n"'s free list.  We assume that __n is properly aligned.  We
131*e4b17023SJohn Marino   // hold the allocation lock.
132*e4b17023SJohn Marino   void*
_M_refill(size_t __n)133*e4b17023SJohn Marino   __pool_alloc_base::_M_refill(size_t __n)
134*e4b17023SJohn Marino   {
135*e4b17023SJohn Marino     int __nobjs = 20;
136*e4b17023SJohn Marino     char* __chunk = _M_allocate_chunk(__n, __nobjs);
137*e4b17023SJohn Marino     _Obj* volatile* __free_list;
138*e4b17023SJohn Marino     _Obj* __result;
139*e4b17023SJohn Marino     _Obj* __current_obj;
140*e4b17023SJohn Marino     _Obj* __next_obj;
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino     if (__nobjs == 1)
143*e4b17023SJohn Marino       return __chunk;
144*e4b17023SJohn Marino     __free_list = _M_get_free_list(__n);
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino     // Build free list in chunk.
147*e4b17023SJohn Marino     __result = (_Obj*)(void*)__chunk;
148*e4b17023SJohn Marino     *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n);
149*e4b17023SJohn Marino     for (int __i = 1; ; __i++)
150*e4b17023SJohn Marino       {
151*e4b17023SJohn Marino 	__current_obj = __next_obj;
152*e4b17023SJohn Marino 	__next_obj = (_Obj*)(void*)((char*)__next_obj + __n);
153*e4b17023SJohn Marino 	if (__nobjs - 1 == __i)
154*e4b17023SJohn Marino 	  {
155*e4b17023SJohn Marino 	    __current_obj->_M_free_list_link = 0;
156*e4b17023SJohn Marino 	    break;
157*e4b17023SJohn Marino 	  }
158*e4b17023SJohn Marino 	else
159*e4b17023SJohn Marino 	  __current_obj->_M_free_list_link = __next_obj;
160*e4b17023SJohn Marino       }
161*e4b17023SJohn Marino     return __result;
162*e4b17023SJohn Marino   }
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   __pool_alloc_base::_Obj* volatile __pool_alloc_base::_S_free_list[_S_free_list_size];
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino   char* __pool_alloc_base::_S_start_free = 0;
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino   char* __pool_alloc_base::_S_end_free = 0;
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino   size_t __pool_alloc_base::_S_heap_size = 0;
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino   // Instantiations.
173*e4b17023SJohn Marino   template class __pool_alloc<char>;
174*e4b17023SJohn Marino   template class __pool_alloc<wchar_t>;
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
177*e4b17023SJohn Marino } // namespace
178