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