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