]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/allocators/private_adaptive_pool.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / interprocess / allocators / private_adaptive_pool.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. 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/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
12 #define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_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/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24
25 #include <boost/intrusive/pointer_traits.hpp>
26
27 #include <boost/interprocess/interprocess_fwd.hpp>
28 #include <boost/assert.hpp>
29 #include <boost/utility/addressof.hpp>
30 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
31 #include <boost/interprocess/containers/version_type.hpp>
32 #include <boost/container/detail/multiallocation_chain.hpp>
33 #include <boost/interprocess/exceptions.hpp>
34 #include <boost/interprocess/detail/utilities.hpp>
35 #include <boost/interprocess/detail/workaround.hpp>
36 #include <boost/move/adl_move_swap.hpp>
37 #include <cstddef>
38
39 //!\file
40 //!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator
41
42 namespace boost {
43 namespace interprocess {
44
45 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
46
47 namespace ipcdetail {
48
49 template < unsigned int Version
50 , class T
51 , class SegmentManager
52 , std::size_t NodesPerBlock
53 , std::size_t MaxFreeBlocks
54 , unsigned char OverheadPercent
55 >
56 class private_adaptive_pool_base
57 : public node_pool_allocation_impl
58 < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock
59 , MaxFreeBlocks, OverheadPercent>
60 , Version
61 , T
62 , SegmentManager
63 >
64 {
65 public:
66 //Segment manager
67 typedef SegmentManager segment_manager;
68 typedef typename SegmentManager::void_pointer void_pointer;
69
70 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
71 private:
72 typedef private_adaptive_pool_base
73 < Version, T, SegmentManager, NodesPerBlock
74 , MaxFreeBlocks, OverheadPercent> self_t;
75 typedef ipcdetail::private_adaptive_node_pool
76 <SegmentManager
77 , sizeof_value<T>::value
78 , NodesPerBlock
79 , MaxFreeBlocks
80 , OverheadPercent
81 > node_pool_t;
82
83 BOOST_STATIC_ASSERT((Version <=2));
84
85 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
86
87 public:
88 typedef typename boost::intrusive::
89 pointer_traits<void_pointer>::template
90 rebind_pointer<T>::type pointer;
91 typedef typename boost::intrusive::
92 pointer_traits<void_pointer>::template
93 rebind_pointer<const T>::type const_pointer;
94 typedef T value_type;
95 typedef typename ipcdetail::add_reference
96 <value_type>::type reference;
97 typedef typename ipcdetail::add_reference
98 <const value_type>::type const_reference;
99 typedef typename segment_manager::size_type size_type;
100 typedef typename segment_manager::size_type difference_type;
101 typedef boost::interprocess::version_type
102 <private_adaptive_pool_base, Version> version;
103 typedef boost::container::container_detail::transform_multiallocation_chain
104 <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
105
106 //!Obtains node_allocator from other node_allocator
107 template<class T2>
108 struct rebind
109 {
110 typedef private_adaptive_pool_base
111 <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
112 };
113
114 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
115
116 template <int dummy>
117 struct node_pool
118 {
119 typedef ipcdetail::private_adaptive_node_pool
120 <SegmentManager
121 , sizeof_value<T>::value
122 , NodesPerBlock
123 , MaxFreeBlocks
124 , OverheadPercent
125 > type;
126
127 static type *get(void *p)
128 { return static_cast<type*>(p); }
129 };
130
131 private:
132 //!Not assignable from related private_adaptive_pool_base
133 template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
134 private_adaptive_pool_base& operator=
135 (const private_adaptive_pool_base<Version2, T2, MemoryAlgorithm2, N2, F2, OP2>&);
136
137 //!Not assignable from other private_adaptive_pool_base
138 private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
139 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
140
141 public:
142 //!Constructor from a segment manager
143 private_adaptive_pool_base(segment_manager *segment_mngr)
144 : m_node_pool(segment_mngr)
145 {}
146
147 //!Copy constructor from other private_adaptive_pool_base. Never throws
148 private_adaptive_pool_base(const private_adaptive_pool_base &other)
149 : m_node_pool(other.get_segment_manager())
150 {}
151
152 //!Copy constructor from related private_adaptive_pool_base. Never throws.
153 template<class T2>
154 private_adaptive_pool_base
155 (const private_adaptive_pool_base
156 <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
157 : m_node_pool(other.get_segment_manager())
158 {}
159
160 //!Destructor, frees all used memory. Never throws
161 ~private_adaptive_pool_base()
162 {}
163
164 //!Returns the segment manager. Never throws
165 segment_manager* get_segment_manager()const
166 { return m_node_pool.get_segment_manager(); }
167
168 //!Returns the internal node pool. Never throws
169 node_pool_t* get_node_pool() const
170 { return const_cast<node_pool_t*>(&m_node_pool); }
171
172 //!Swaps allocators. Does not throw. If each allocator is placed in a
173 //!different shared memory segments, the result is undefined.
174 friend void swap(self_t &alloc1,self_t &alloc2)
175 { boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool); }
176
177 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
178 private:
179 node_pool_t m_node_pool;
180 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
181 };
182
183 //!Equality test for same type of private_adaptive_pool_base
184 template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
185 bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
186 const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
187 { return &alloc1 == &alloc2; }
188
189 //!Inequality test for same type of private_adaptive_pool_base
190 template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
191 bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
192 const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
193 { return &alloc1 != &alloc2; }
194
195 template < class T
196 , class SegmentManager
197 , std::size_t NodesPerBlock = 64
198 , std::size_t MaxFreeBlocks = 2
199 , unsigned char OverheadPercent = 5
200 >
201 class private_adaptive_pool_v1
202 : public private_adaptive_pool_base
203 < 1
204 , T
205 , SegmentManager
206 , NodesPerBlock
207 , MaxFreeBlocks
208 , OverheadPercent
209 >
210 {
211 public:
212 typedef ipcdetail::private_adaptive_pool_base
213 < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
214
215 template<class T2>
216 struct rebind
217 {
218 typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
219 };
220
221 private_adaptive_pool_v1(SegmentManager *segment_mngr)
222 : base_t(segment_mngr)
223 {}
224
225 template<class T2>
226 private_adaptive_pool_v1
227 (const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
228 : base_t(other)
229 {}
230 };
231
232 } //namespace ipcdetail {
233
234 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
235
236 //!An STL node allocator that uses a segment manager as memory
237 //!source. The internal pointer type will of the same type (raw, smart) as
238 //!"typename SegmentManager::void_pointer" type. This allows
239 //!placing the allocator in shared memory, memory mapped-files, etc...
240 //!This allocator has its own node pool.
241 //!
242 //!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
243 //!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
244 //!that the adaptive node pool will hold. The rest of the totally free blocks will be
245 //!deallocated with the segment manager.
246 //!
247 //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
248 //!(memory usable for nodes / total memory allocated from the segment manager)
249 template < class T
250 , class SegmentManager
251 , std::size_t NodesPerBlock
252 , std::size_t MaxFreeBlocks
253 , unsigned char OverheadPercent
254 >
255 class private_adaptive_pool
256 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
257 : public ipcdetail::private_adaptive_pool_base
258 < 2
259 , T
260 , SegmentManager
261 , NodesPerBlock
262 , MaxFreeBlocks
263 , OverheadPercent
264 >
265 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
266 {
267
268 #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
269 typedef ipcdetail::private_adaptive_pool_base
270 < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
271 public:
272 typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
273
274 template<class T2>
275 struct rebind
276 {
277 typedef private_adaptive_pool
278 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
279 };
280
281 private_adaptive_pool(SegmentManager *segment_mngr)
282 : base_t(segment_mngr)
283 {}
284
285 template<class T2>
286 private_adaptive_pool
287 (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
288 : base_t(other)
289 {}
290
291 #else
292 public:
293 typedef implementation_defined::segment_manager segment_manager;
294 typedef segment_manager::void_pointer void_pointer;
295 typedef implementation_defined::pointer pointer;
296 typedef implementation_defined::const_pointer const_pointer;
297 typedef T value_type;
298 typedef typename ipcdetail::add_reference
299 <value_type>::type reference;
300 typedef typename ipcdetail::add_reference
301 <const value_type>::type const_reference;
302 typedef typename segment_manager::size_type size_type;
303 typedef typename segment_manager::difference_type difference_type;
304
305 //!Obtains private_adaptive_pool from
306 //!private_adaptive_pool
307 template<class T2>
308 struct rebind
309 {
310 typedef private_adaptive_pool
311 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
312 };
313
314 private:
315 //!Not assignable from
316 //!related private_adaptive_pool
317 template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
318 private_adaptive_pool& operator=
319 (const private_adaptive_pool<T2, SegmentManager2, N2, F2>&);
320
321 //!Not assignable from
322 //!other private_adaptive_pool
323 private_adaptive_pool& operator=(const private_adaptive_pool&);
324
325 public:
326 //!Constructor from a segment manager. If not present, constructs a node
327 //!pool. Increments the reference count of the associated node pool.
328 //!Can throw boost::interprocess::bad_alloc
329 private_adaptive_pool(segment_manager *segment_mngr);
330
331 //!Copy constructor from other private_adaptive_pool. Increments the reference
332 //!count of the associated node pool. Never throws
333 private_adaptive_pool(const private_adaptive_pool &other);
334
335 //!Copy constructor from related private_adaptive_pool. If not present, constructs
336 //!a node pool. Increments the reference count of the associated node pool.
337 //!Can throw boost::interprocess::bad_alloc
338 template<class T2>
339 private_adaptive_pool
340 (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
341
342 //!Destructor, removes node_pool_t from memory
343 //!if its reference count reaches to zero. Never throws
344 ~private_adaptive_pool();
345
346 //!Returns a pointer to the node pool.
347 //!Never throws
348 node_pool_t* get_node_pool() const;
349
350 //!Returns the segment manager.
351 //!Never throws
352 segment_manager* get_segment_manager()const;
353
354 //!Returns the number of elements that could be allocated.
355 //!Never throws
356 size_type max_size() const;
357
358 //!Allocate memory for an array of count elements.
359 //!Throws boost::interprocess::bad_alloc if there is no enough memory
360 pointer allocate(size_type count, cvoid_pointer hint = 0);
361
362 //!Deallocate allocated memory.
363 //!Never throws
364 void deallocate(const pointer &ptr, size_type count);
365
366 //!Deallocates all free blocks
367 //!of the pool
368 void deallocate_free_blocks();
369
370 //!Swaps allocators. Does not throw. If each allocator is placed in a
371 //!different memory segment, the result is undefined.
372 friend void swap(self_t &alloc1, self_t &alloc2);
373
374 //!Returns address of mutable object.
375 //!Never throws
376 pointer address(reference value) const;
377
378 //!Returns address of non mutable object.
379 //!Never throws
380 const_pointer address(const_reference value) const;
381
382 //!Copy construct an object.
383 //!Throws if T's copy constructor throws
384 void construct(const pointer &ptr, const_reference v);
385
386 //!Destroys object. Throws if object's
387 //!destructor throws
388 void destroy(const pointer &ptr);
389
390 //!Returns maximum the number of objects the previously allocated memory
391 //!pointed by p can hold. This size only works for memory allocated with
392 //!allocate, allocation_command and allocate_many.
393 size_type size(const pointer &p) const;
394
395 pointer allocation_command(boost::interprocess::allocation_type command,
396 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse);
397
398 //!Allocates many elements of size elem_size in a contiguous block
399 //!of memory. The minimum number to be allocated is min_elements,
400 //!the preferred and maximum number is
401 //!preferred_elements. The number of actually allocated elements is
402 //!will be assigned to received_size. The elements must be deallocated
403 //!with deallocate(...)
404 void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
405
406 //!Allocates n_elements elements, each one of size elem_sizes[i]in a
407 //!contiguous block
408 //!of memory. The elements must be deallocated
409 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
410
411 //!Allocates many elements of size elem_size in a contiguous block
412 //!of memory. The minimum number to be allocated is min_elements,
413 //!the preferred and maximum number is
414 //!preferred_elements. The number of actually allocated elements is
415 //!will be assigned to received_size. The elements must be deallocated
416 //!with deallocate(...)
417 void deallocate_many(multiallocation_chain &chain);
418
419 //!Allocates just one object. Memory allocated with this function
420 //!must be deallocated only with deallocate_one().
421 //!Throws boost::interprocess::bad_alloc if there is no enough memory
422 pointer allocate_one();
423
424 //!Allocates many elements of size == 1 in a contiguous block
425 //!of memory. The minimum number to be allocated is min_elements,
426 //!the preferred and maximum number is
427 //!preferred_elements. The number of actually allocated elements is
428 //!will be assigned to received_size. Memory allocated with this function
429 //!must be deallocated only with deallocate_one().
430 void allocate_individual(size_type num_elements, multiallocation_chain &chain);
431
432 //!Deallocates memory previously allocated with allocate_one().
433 //!You should never use deallocate_one to deallocate memory allocated
434 //!with other functions different from allocate_one(). Never throws
435 void deallocate_one(const pointer &p);
436
437 //!Allocates many elements of size == 1 in a contiguous block
438 //!of memory. The minimum number to be allocated is min_elements,
439 //!the preferred and maximum number is
440 //!preferred_elements. The number of actually allocated elements is
441 //!will be assigned to received_size. Memory allocated with this function
442 //!must be deallocated only with deallocate_one().
443 void deallocate_individual(multiallocation_chain &chain);
444 #endif
445 };
446
447 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
448
449 //!Equality test for same type
450 //!of private_adaptive_pool
451 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
452 bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
453 const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
454
455 //!Inequality test for same type
456 //!of private_adaptive_pool
457 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
458 bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
459 const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
460
461 #endif
462
463 } //namespace interprocess {
464 } //namespace boost {
465
466 #include <boost/interprocess/detail/config_end.hpp>
467
468 #endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
469