1 // Copyright (C) 2000, 2001 Stephen Cleary
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org for updates, documentation, and revision history.
8 
9 #ifndef BOOST_POOL_ALLOC_HPP
10 #define BOOST_POOL_ALLOC_HPP
11 
12 // std::numeric_limits
13 #include <boost/limits.hpp>
14 // new, std::bad_alloc
15 #include <new>
16 
17 #include <boost/pool/poolfwd.hpp>
18 
19 // boost::singleton_pool
20 #include <boost/pool/singleton_pool.hpp>
21 
22 // The following code will be put into Boost.Config in a later revision
23 #if defined(_RWSTD_VER) || defined(__SGI_STL_PORT)
24  // Needed, as of bcc 5.5 and STLPort 4.5b8
25  #define BOOST_NO_PROPER_STL_DEALLOCATE
26 #endif
27 
28 namespace boost {
29 
30 struct pool_allocator_tag { };
31 
32 template <typename T,
33     typename UserAllocator,
34     typename Mutex,
35     unsigned NextSize>
36 class pool_allocator
37 {
38   public:
39     typedef T value_type;
40     typedef UserAllocator user_allocator;
41     typedef Mutex mutex;
42     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
43 
44     typedef value_type * pointer;
45     typedef const value_type * const_pointer;
46     typedef value_type & reference;
47     typedef const value_type & const_reference;
48     typedef typename pool<UserAllocator>::size_type size_type;
49     typedef typename pool<UserAllocator>::difference_type difference_type;
50 
51     template <typename U>
52     struct rebind
53     {
54       typedef pool_allocator<U, UserAllocator, Mutex, NextSize> other;
55     };
56 
57   public:
pool_allocator()58     pool_allocator() { }
59 
60     // default copy constructor
61 
62     // default assignment operator
63 
64     // not explicit, mimicking std::allocator [20.4.1]
65     template <typename U>
pool_allocator(const pool_allocator<U,UserAllocator,Mutex,NextSize> &)66     pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize> &)
67     { }
68 
69     // default destructor
70 
address(reference r)71     static pointer address(reference r)
72     { return &r; }
address(const_reference s)73     static const_pointer address(const_reference s)
74     { return &s; }
max_size()75     static size_type max_size()
76     { return (std::numeric_limits<size_type>::max)(); }
construct(const pointer ptr,const value_type & t)77     static void construct(const pointer ptr, const value_type & t)
78     { new (ptr) T(t); }
destroy(const pointer ptr)79     static void destroy(const pointer ptr)
80     {
81       ptr->~T();
82       (void) ptr; // avoid unused variable warning
83     }
84 
operator ==(const pool_allocator &) const85     bool operator==(const pool_allocator &) const
86     { return true; }
operator !=(const pool_allocator &) const87     bool operator!=(const pool_allocator &) const
88     { return false; }
89 
allocate(const size_type n)90     static pointer allocate(const size_type n)
91     {
92       const pointer ret = static_cast<pointer>(
93           singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
94               NextSize>::ordered_malloc(n) );
95       if (ret == 0)
96         throw std::bad_alloc();
97       return ret;
98     }
allocate(const size_type n,const void * const)99     static pointer allocate(const size_type n, const void * const)
100     { return allocate(n); }
deallocate(const pointer ptr,const size_type n)101     static void deallocate(const pointer ptr, const size_type n)
102     {
103 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
104       if (ptr == 0 || n == 0)
105         return;
106 #endif
107       singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
108           NextSize>::ordered_free(ptr, n);
109     }
110 };
111 
112 struct fast_pool_allocator_tag { };
113 
114 template <typename T,
115     typename UserAllocator,
116     typename Mutex,
117     unsigned NextSize>
118 class fast_pool_allocator
119 {
120   public:
121     typedef T value_type;
122     typedef UserAllocator user_allocator;
123     typedef Mutex mutex;
124     BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
125 
126     typedef value_type * pointer;
127     typedef const value_type * const_pointer;
128     typedef value_type & reference;
129     typedef const value_type & const_reference;
130     typedef typename pool<UserAllocator>::size_type size_type;
131     typedef typename pool<UserAllocator>::difference_type difference_type;
132 
133     template <typename U>
134     struct rebind
135     {
136       typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize> other;
137     };
138 
139   public:
fast_pool_allocator()140     fast_pool_allocator() { }
141 
142     // default copy constructor
143 
144     // default assignment operator
145 
146     // not explicit, mimicking std::allocator [20.4.1]
147     template <typename U>
fast_pool_allocator(const fast_pool_allocator<U,UserAllocator,Mutex,NextSize> &)148     fast_pool_allocator(
149         const fast_pool_allocator<U, UserAllocator, Mutex, NextSize> &)
150     { }
151 
152     // default destructor
153 
address(reference r)154     static pointer address(reference r)
155     { return &r; }
address(const_reference s)156     static const_pointer address(const_reference s)
157     { return &s; }
max_size()158     static size_type max_size()
159     { return (std::numeric_limits<size_type>::max)(); }
construct(const pointer ptr,const value_type & t)160     void construct(const pointer ptr, const value_type & t)
161     { new (ptr) T(t); }
destroy(const pointer ptr)162     void destroy(const pointer ptr)
163     {
164       ptr->~T();
165       (void) ptr; // avoid unused variable warning
166     }
167 
operator ==(const fast_pool_allocator &) const168     bool operator==(const fast_pool_allocator &) const
169     { return true; }
operator !=(const fast_pool_allocator &) const170     bool operator!=(const fast_pool_allocator &) const
171     { return false; }
172 
allocate(const size_type n)173     static pointer allocate(const size_type n)
174     {
175       const pointer ret = (n == 1) ?
176           static_cast<pointer>(
177               singleton_pool<fast_pool_allocator_tag, sizeof(T),
178                   UserAllocator, Mutex, NextSize>::malloc() ) :
179           static_cast<pointer>(
180               singleton_pool<fast_pool_allocator_tag, sizeof(T),
181                   UserAllocator, Mutex, NextSize>::ordered_malloc(n) );
182       if (ret == 0)
183         throw std::bad_alloc();
184       return ret;
185     }
allocate(const size_type n,const void * const)186     static pointer allocate(const size_type n, const void * const)
187     { return allocate(n); }
allocate()188     static pointer allocate()
189     {
190       const pointer ret = static_cast<pointer>(
191           singleton_pool<fast_pool_allocator_tag, sizeof(T),
192               UserAllocator, Mutex, NextSize>::malloc() );
193       if (ret == 0)
194         throw std::bad_alloc();
195       return ret;
196     }
deallocate(const pointer ptr,const size_type n)197     static void deallocate(const pointer ptr, const size_type n)
198     {
199 #ifdef BOOST_NO_PROPER_STL_DEALLOCATE
200       if (ptr == 0 || n == 0)
201         return;
202 #endif
203       if (n == 1)
204         singleton_pool<fast_pool_allocator_tag, sizeof(T),
205             UserAllocator, Mutex, NextSize>::free(ptr);
206       else
207         singleton_pool<fast_pool_allocator_tag, sizeof(T),
208             UserAllocator, Mutex, NextSize>::free(ptr, n);
209     }
deallocate(const pointer ptr)210     static void deallocate(const pointer ptr)
211     {
212       singleton_pool<fast_pool_allocator_tag, sizeof(T),
213           UserAllocator, Mutex, NextSize>::free(ptr);
214     }
215 };
216 
217 } // namespace boost
218 
219 #endif
220