1169691Skan// Bitmap Allocator. Out of line function definitions. -*- C++ -*-
2169691Skan
3169691Skan// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4169691Skan//
5169691Skan// This file is part of the GNU ISO C++ Library.  This library is free
6169691Skan// software; you can redistribute it and/or modify it under the
7169691Skan// terms of the GNU General Public License as published by the
8169691Skan// Free Software Foundation; either version 2, or (at your option)
9169691Skan// any later version.
10169691Skan
11169691Skan// This library is distributed in the hope that it will be useful,
12169691Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169691Skan// GNU General Public License for more details.
15169691Skan
16169691Skan// You should have received a copy of the GNU General Public License along
17169691Skan// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19169691Skan// USA.
20169691Skan
21169691Skan// As a special exception, you may use this file as part of a free software
22169691Skan// library without restriction.  Specifically, if other files instantiate
23169691Skan// templates or use macros or inline functions from this file, or you compile
24169691Skan// this file and link it with other files to produce an executable, this
25169691Skan// file does not by itself cause the resulting executable to be covered by
26169691Skan// the GNU General Public License.  This exception does not however
27169691Skan// invalidate any other reasons why the executable file might be covered by
28169691Skan// the GNU General Public License.
29169691Skan
30169691Skan#include <ext/bitmap_allocator.h>
31169691Skan
32169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
33169691Skan
34169691Skan  namespace __detail
35169691Skan  {
36169691Skan    template class __mini_vector<
37169691Skan      std::pair<bitmap_allocator<char>::_Alloc_block*,
38169691Skan		bitmap_allocator<char>::_Alloc_block*> >;
39169691Skan
40169691Skan    template class __mini_vector<
41169691Skan      std::pair<bitmap_allocator<wchar_t>::_Alloc_block*,
42169691Skan		bitmap_allocator<wchar_t>::_Alloc_block*> >;
43169691Skan
44169691Skan    template class __mini_vector<size_t*>;
45169691Skan
46169691Skan    template size_t** __lower_bound(size_t**, size_t**, size_t const&,
47169691Skan				    free_list::_LT_pointer_compare);
48169691Skan  }
49169691Skan
50169691Skan  size_t*
51169691Skan  free_list::
52169691Skan  _M_get(size_t __sz) throw(std::bad_alloc)
53169691Skan  {
54169691Skan#if defined __GTHREADS
55169691Skan    __mutex_type& __bfl_mutex = _M_get_mutex();
56169691Skan#endif
57169691Skan    const vector_type& __free_list = _M_get_free_list();
58169691Skan    using __gnu_cxx::__detail::__lower_bound;
59169691Skan    iterator __tmp = __lower_bound(__free_list.begin(), __free_list.end(),
60169691Skan				   __sz, _LT_pointer_compare());
61169691Skan
62169691Skan    if (__tmp == __free_list.end() || !_M_should_i_give(**__tmp, __sz))
63169691Skan      {
64169691Skan	// We release the lock here, because operator new is
65169691Skan	// guaranteed to be thread-safe by the underlying
66169691Skan	// implementation.
67169691Skan#if defined __GTHREADS
68169691Skan	__bfl_mutex.unlock();
69169691Skan#endif
70169691Skan	// Try twice to get the memory: once directly, and the 2nd
71169691Skan	// time after clearing the free list. If both fail, then throw
72169691Skan	// std::bad_alloc().
73169691Skan	int __ctr = 2;
74169691Skan	while (__ctr)
75169691Skan	  {
76169691Skan	    size_t* __ret = 0;
77169691Skan	    --__ctr;
78169691Skan	    try
79169691Skan	      {
80169691Skan		__ret = reinterpret_cast<size_t*>
81169691Skan		  (::operator new(__sz + sizeof(size_t)));
82169691Skan	      }
83169691Skan	    catch(...)
84169691Skan	      {
85169691Skan		this->_M_clear();
86169691Skan	      }
87169691Skan	    if (!__ret)
88169691Skan	      continue;
89169691Skan	    *__ret = __sz;
90169691Skan	    return __ret + 1;
91169691Skan	  }
92169691Skan	std::__throw_bad_alloc();
93169691Skan      }
94169691Skan    else
95169691Skan      {
96169691Skan	size_t* __ret = *__tmp;
97169691Skan	_M_get_free_list().erase(__tmp);
98169691Skan#if defined __GTHREADS
99169691Skan	__bfl_mutex.unlock();
100169691Skan#endif
101169691Skan	return __ret + 1;
102169691Skan      }
103169691Skan  }
104169691Skan
105169691Skan  void
106169691Skan  free_list::
107169691Skan  _M_clear()
108169691Skan  {
109169691Skan#if defined __GTHREADS
110169691Skan    __gnu_cxx::__scoped_lock __bfl_lock(_M_get_mutex());
111169691Skan#endif
112169691Skan    vector_type& __free_list = _M_get_free_list();
113169691Skan    iterator __iter = __free_list.begin();
114169691Skan    while (__iter != __free_list.end())
115169691Skan      {
116169691Skan	::operator delete((void*)*__iter);
117169691Skan	++__iter;
118169691Skan      }
119169691Skan    __free_list.clear();
120169691Skan  }
121169691Skan
122169691Skan  // Instantiations.
123169691Skan  template class bitmap_allocator<char>;
124169691Skan  template class bitmap_allocator<wchar_t>;
125169691Skan
126169691Skan_GLIBCXX_END_NAMESPACE
127