comparison DEPENDENCIES/generic/include/boost/container/allocator.hpp @ 102:f46d142149f5

Whoops, finish that update
author Chris Cannam
date Mon, 07 Sep 2015 11:13:41 +0100
parents
children
comparison
equal deleted inserted replaced
101:c530137014c0 102:f46d142149f5
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_CONTAINER_ALLOCATOR_HPP
12 #define BOOST_CONTAINER_ALLOCATOR_HPP
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24 #include <boost/container/container_fwd.hpp>
25 #include <boost/container/detail/version_type.hpp>
26 #include <boost/container/throw_exception.hpp>
27 #include <boost/container/detail/alloc_lib_auto_link.hpp>
28 #include <boost/container/detail/multiallocation_chain.hpp>
29 #include <boost/static_assert.hpp>
30 #include <cstddef>
31 #include <cassert>
32
33 namespace boost {
34 namespace container {
35
36 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
37
38 template<unsigned Version, unsigned int AllocationDisableMask>
39 class allocator<void, Version, AllocationDisableMask>
40 {
41 typedef allocator<void, Version, AllocationDisableMask> self_t;
42 public:
43 typedef void value_type;
44 typedef void * pointer;
45 typedef const void* const_pointer;
46 typedef int & reference;
47 typedef const int & const_reference;
48 typedef std::size_t size_type;
49 typedef std::ptrdiff_t difference_type;
50 typedef boost::container::container_detail::
51 version_type<self_t, Version> version;
52
53 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
54 typedef boost::container::container_detail::
55 basic_multiallocation_chain<void*> multiallocation_chain;
56 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
57
58 //!Obtains an allocator that allocates
59 //!objects of type T2
60 template<class T2>
61 struct rebind
62 {
63 typedef allocator< T2
64 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
65 , Version, AllocationDisableMask
66 #endif
67 > other;
68 };
69
70 //!Default constructor
71 //!Never throws
72 allocator()
73 {}
74
75 //!Constructor from other allocator.
76 //!Never throws
77 allocator(const allocator &)
78 {}
79
80 //!Constructor from related allocator.
81 //!Never throws
82 template<class T2>
83 allocator(const allocator<T2, Version, AllocationDisableMask> &)
84 {}
85 };
86
87 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
88
89 //!\file
90 //! This class is an extended STL-compatible that offers advanced allocation mechanism
91 //!(in-place expansion, shrinking, burst-allocation...)
92 //!
93 //! This allocator is a wrapper around a modified DLmalloc.
94 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
95 template<class T>
96 #else
97 //! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
98 //! the allocator offers advanced expand in place and burst allocation capabilities.
99 //
100 //! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
101 //! of allocation types the user wants to disable.
102 template<class T, unsigned Version, unsigned int AllocationDisableMask>
103 #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
104 class allocator
105 {
106 typedef unsigned int allocation_type;
107 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
108 private:
109
110 //Self type
111 typedef allocator<T, Version, AllocationDisableMask> self_t;
112
113 //Not assignable from related allocator
114 template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
115 allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
116
117 //Not assignable from other allocator
118 allocator& operator=(const allocator&);
119
120 static const unsigned int ForbiddenMask =
121 BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
122
123 //The mask can't disable all the allocation types
124 BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
125
126 //The mask is only valid for version 2 allocators
127 BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
128
129 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
130
131 public:
132 typedef T value_type;
133 typedef T * pointer;
134 typedef const T * const_pointer;
135 typedef T & reference;
136 typedef const T & const_reference;
137 typedef std::size_t size_type;
138 typedef std::ptrdiff_t difference_type;
139
140 typedef boost::container::container_detail::
141 version_type<self_t, Version> version;
142
143 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
144 typedef boost::container::container_detail::
145 basic_multiallocation_chain<void*> void_multiallocation_chain;
146
147 typedef boost::container::container_detail::
148 transform_multiallocation_chain
149 <void_multiallocation_chain, T> multiallocation_chain;
150 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
151
152 //!Obtains an allocator that allocates
153 //!objects of type T2
154 template<class T2>
155 struct rebind
156 {
157 typedef allocator<T2, Version, AllocationDisableMask> other;
158 };
159
160 //!Default constructor
161 //!Never throws
162 allocator() BOOST_NOEXCEPT_OR_NOTHROW
163 {}
164
165 //!Constructor from other allocator.
166 //!Never throws
167 allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
168 {}
169
170 //!Constructor from related allocator.
171 //!Never throws
172 template<class T2>
173 allocator(const allocator<T2
174 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
175 , Version, AllocationDisableMask
176 #endif
177 > &) BOOST_NOEXCEPT_OR_NOTHROW
178 {}
179
180 //!Allocates memory for an array of count elements.
181 //!Throws std::bad_alloc if there is no enough memory
182 //!If Version is 2, this allocated memory can only be deallocated
183 //!with deallocate() or (for Version == 2) deallocate_many()
184 pointer allocate(size_type count, const void * hint= 0)
185 {
186 (void)hint;
187 if(count > this->max_size())
188 boost::container::throw_bad_alloc();
189 void *ret = boost_cont_malloc(count*sizeof(T));
190 if(!ret)
191 boost::container::throw_bad_alloc();
192 return static_cast<pointer>(ret);
193 }
194
195 //!Deallocates previously allocated memory.
196 //!Never throws
197 void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
198 { boost_cont_free(ptr); }
199
200 //!Returns the maximum number of elements that could be allocated.
201 //!Never throws
202 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
203 { return size_type(-1)/sizeof(T); }
204
205 //!Swaps two allocators, does nothing
206 //!because this allocator is stateless
207 friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW
208 {}
209
210 //!An allocator always compares to true, as memory allocated with one
211 //!instance can be deallocated by another instance
212 friend bool operator==(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
213 { return true; }
214
215 //!An allocator always compares to false, as memory allocated with one
216 //!instance can be deallocated by another instance
217 friend bool operator!=(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
218 { return false; }
219
220 //!An advanced function that offers in-place expansion shrink to fit and new allocation
221 //!capabilities. Memory allocated with this function can only be deallocated with deallocate()
222 //!or deallocate_many().
223 //!This function is available only with Version == 2
224 pointer allocation_command(allocation_type command,
225 size_type limit_size,
226 size_type &prefer_in_recvd_out_size,
227 pointer &reuse)
228 {
229 BOOST_STATIC_ASSERT(( Version > 1 ));
230 const allocation_type mask(AllocationDisableMask);
231 command &= ~mask;
232 pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
233 if(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
234 boost::container::throw_bad_alloc();
235 return ret;
236 }
237
238 //!Returns maximum the number of objects the previously allocated memory
239 //!pointed by p can hold.
240 //!Memory must not have been allocated with
241 //!allocate_one or allocate_individual.
242 //!This function is available only with Version == 2
243 size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
244 {
245 BOOST_STATIC_ASSERT(( Version > 1 ));
246 return boost_cont_size(p);
247 }
248
249 //!Allocates just one object. Memory allocated with this function
250 //!must be deallocated only with deallocate_one().
251 //!Throws bad_alloc if there is no enough memory
252 //!This function is available only with Version == 2
253 pointer allocate_one()
254 {
255 BOOST_STATIC_ASSERT(( Version > 1 ));
256 return this->allocate(1);
257 }
258
259 //!Allocates many elements of size == 1.
260 //!Elements must be individually deallocated with deallocate_one()
261 //!This function is available only with Version == 2
262 void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
263 {
264 BOOST_STATIC_ASSERT(( Version > 1 ));
265 this->allocate_many(1, num_elements, chain);
266 }
267
268 //!Deallocates memory previously allocated with allocate_one().
269 //!You should never use deallocate_one to deallocate memory allocated
270 //!with other functions different from allocate_one() or allocate_individual.
271 //Never throws
272 void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
273 {
274 BOOST_STATIC_ASSERT(( Version > 1 ));
275 return this->deallocate(p, 1);
276 }
277
278 //!Deallocates memory allocated with allocate_one() or allocate_individual().
279 //!This function is available only with Version == 2
280 void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
281 {
282 BOOST_STATIC_ASSERT(( Version > 1 ));
283 return this->deallocate_many(chain);
284 }
285
286 //!Allocates many elements of size elem_size.
287 //!Elements must be individually deallocated with deallocate()
288 //!This function is available only with Version == 2
289 void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
290 {
291 BOOST_STATIC_ASSERT(( Version > 1 ));/*
292 boost_cont_memchain ch;
293 BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
294 if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
295 boost::container::throw_bad_alloc();
296 }
297 chain.incorporate_after(chain.before_begin()
298 ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
299 ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
300 ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
301 if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
302 boost::container::throw_bad_alloc();
303 }
304 }
305
306 //!Allocates n_elements elements, each one of size elem_sizes[i]
307 //!Elements must be individually deallocated with deallocate()
308 //!This function is available only with Version == 2
309 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
310 {
311 BOOST_STATIC_ASSERT(( Version > 1 ));
312 boost_cont_memchain ch;
313 BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
314 if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
315 boost::container::throw_bad_alloc();
316 }
317 chain.incorporate_after(chain.before_begin()
318 ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
319 ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
320 ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
321 /*
322 if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
323 boost::container::throw_bad_alloc();
324 }*/
325 }
326
327 //!Deallocates several elements allocated by
328 //!allocate_many(), allocate(), or allocation_command().
329 //!This function is available only with Version == 2
330 void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
331 {
332 BOOST_STATIC_ASSERT(( Version > 1 ));
333 boost_cont_memchain ch;
334 void *beg(&*chain.begin()), *last(&*chain.last());
335 size_t size(chain.size());
336 BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
337 boost_cont_multidealloc(&ch);
338 //boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
339 }
340
341 private:
342
343 pointer priv_allocation_command
344 (allocation_type command, std::size_t limit_size
345 ,size_type &prefer_in_recvd_out_size
346 ,pointer &reuse_ptr)
347 {
348 std::size_t const preferred_size = prefer_in_recvd_out_size;
349 boost_cont_command_ret_t ret = {0 , 0};
350 if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
351 return pointer();
352 }
353 std::size_t l_size = limit_size*sizeof(T);
354 std::size_t p_size = preferred_size*sizeof(T);
355 std::size_t r_size;
356 {
357 void* reuse_ptr_void = reuse_ptr;
358 ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
359 reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
360 }
361 prefer_in_recvd_out_size = r_size/sizeof(T);
362 return (pointer)ret.first;
363 }
364 };
365
366 } //namespace container {
367 } //namespace boost {
368
369 #include <boost/container/detail/config_end.hpp>
370
371 #endif //BOOST_CONTAINER_ALLOCATOR_HPP
372