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