]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/detail/managed_memory_impl.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / interprocess / detail / managed_memory_impl.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_DETAIL_MANAGED_MEMORY_IMPL_HPP
12 #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_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/interprocess/interprocess_fwd.hpp>
26 #include <boost/interprocess/detail/utilities.hpp>
27 #include <boost/interprocess/detail/os_file_functions.hpp>
28 #include <boost/interprocess/creation_tags.hpp>
29 #include <boost/interprocess/exceptions.hpp>
30 #include <boost/interprocess/segment_manager.hpp>
31 #include <boost/interprocess/sync/scoped_lock.hpp>
32 #include <boost/interprocess/detail/nothrow.hpp>
33 #include <boost/interprocess/detail/simple_swap.hpp>
34 //
35 #include <boost/core/no_exceptions_support.hpp>
36 //
37 #include <boost/intrusive/detail/minimal_pair_header.hpp>
38 #include <boost/assert.hpp>
39
40 //!\file
41 //!Describes a named shared memory allocation user class.
42 //!
43
44 namespace boost {
45 namespace interprocess {
46 namespace ipcdetail {
47
48 template<class BasicManagedMemoryImpl>
49 class create_open_func;
50
51 template<
52 class CharType,
53 class MemoryAlgorithm,
54 template<class IndexConfig> class IndexType
55 >
56 struct segment_manager_type
57 {
58 typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
59 };
60
61 //!This class is designed to be a base class to classes that manage
62 //!creation of objects in a fixed size memory buffer. Apart
63 //!from allocating raw memory, the user can construct named objects. To
64 //!achieve this, this class uses the reserved space provided by the allocation
65 //!algorithm to place a named_allocator_algo, who takes care of name mappings.
66 //!The class can be customized with the char type used for object names
67 //!and the memory allocation algorithm to be used.*/
68 template < class CharType
69 , class MemoryAlgorithm
70 , template<class IndexConfig> class IndexType
71 , std::size_t Offset = 0
72 >
73 class basic_managed_memory_impl
74 {
75 //Non-copyable
76 basic_managed_memory_impl(const basic_managed_memory_impl &);
77 basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
78
79 template<class BasicManagedMemoryImpl>
80 friend class create_open_func;
81
82 public:
83 typedef typename segment_manager_type
84 <CharType, MemoryAlgorithm, IndexType>::type segment_manager;
85 typedef CharType char_type;
86 typedef MemoryAlgorithm memory_algorithm;
87 typedef typename MemoryAlgorithm::mutex_family mutex_family;
88 typedef CharType char_t;
89 typedef typename MemoryAlgorithm::size_type size_type;
90 typedef typename MemoryAlgorithm::difference_type difference_type;
91 typedef difference_type handle_t;
92 typedef typename segment_manager::
93 const_named_iterator const_named_iterator;
94 typedef typename segment_manager::
95 const_unique_iterator const_unique_iterator;
96
97 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
98
99 typedef typename
100 segment_manager::char_ptr_holder_t char_ptr_holder_t;
101 //Experimental. Don't use.
102
103 typedef typename segment_manager::multiallocation_chain multiallocation_chain;
104
105 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
106
107 static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
108
109 private:
110 typedef basic_managed_memory_impl
111 <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
112 protected:
113 template<class ManagedMemory>
114 static bool grow(const char *filename, size_type extra_bytes)
115 {
116 typedef typename ManagedMemory::device_type device_type;
117 //Increase file size
118 try{
119 offset_t old_size;
120 {
121 device_type f(open_or_create, filename, read_write);
122 if(!f.get_size(old_size))
123 return false;
124 f.truncate(old_size + extra_bytes);
125 }
126 ManagedMemory managed_memory(open_only, filename);
127 //Grow always works
128 managed_memory.self_t::grow(extra_bytes);
129 }
130 catch(...){
131 return false;
132 }
133 return true;
134 }
135
136 template<class ManagedMemory>
137 static bool shrink_to_fit(const char *filename)
138 {
139 typedef typename ManagedMemory::device_type device_type;
140 size_type new_size;
141 try{
142 ManagedMemory managed_memory(open_only, filename);
143 managed_memory.get_size();
144 managed_memory.self_t::shrink_to_fit();
145 new_size = managed_memory.get_size();
146 }
147 catch(...){
148 return false;
149 }
150
151 //Decrease file size
152 {
153 device_type f(open_or_create, filename, read_write);
154 f.truncate(new_size);
155 }
156 return true;
157 }
158
159 //!Constructor. Allocates basic resources. Never throws.
160 basic_managed_memory_impl()
161 : mp_header(0){}
162
163 //!Destructor. Calls close. Never throws.
164 ~basic_managed_memory_impl()
165 { this->close_impl(); }
166
167 //!Places segment manager in the reserved space. This can throw.
168 bool create_impl (void *addr, size_type size)
169 {
170 if(mp_header) return false;
171
172 //Check if there is enough space
173 if(size < segment_manager::get_min_size())
174 return false;
175
176 //This function should not throw. The index construction can
177 //throw if constructor allocates memory. So we must catch it.
178 BOOST_TRY{
179 //Let's construct the allocator in memory
180 BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of<segment_manager>::value));
181 mp_header = ::new(addr, boost_container_new_t()) segment_manager(size);
182 }
183 BOOST_CATCH(...){
184 return false;
185 }
186 BOOST_CATCH_END
187 return true;
188 }
189
190 //!Connects to a segment manager in the reserved buffer. Never throws.
191 bool open_impl (void *addr, size_type)
192 {
193 if(mp_header) return false;
194 mp_header = static_cast<segment_manager*>(addr);
195 return true;
196 }
197
198 //!Frees resources. Never throws.
199 bool close_impl()
200 {
201 bool ret = mp_header != 0;
202 mp_header = 0;
203 return ret;
204 }
205
206 //!Frees resources and destroys common resources. Never throws.
207 bool destroy_impl()
208 {
209 if(mp_header == 0)
210 return false;
211 mp_header->~segment_manager();
212 this->close_impl();
213 return true;
214 }
215
216 //!
217 void grow(size_type extra_bytes)
218 { mp_header->grow(extra_bytes); }
219
220 void shrink_to_fit()
221 { mp_header->shrink_to_fit(); }
222
223 public:
224
225 //!Returns segment manager. Never throws.
226 segment_manager *get_segment_manager() const
227 { return mp_header; }
228
229 //!Returns the base address of the memory in this process. Never throws.
230 void * get_address () const
231 { return reinterpret_cast<char*>(mp_header) - Offset; }
232
233 //!Returns the size of memory segment. Never throws.
234 size_type get_size () const
235 { return mp_header->get_size() + Offset; }
236
237 //!Returns the number of free bytes of the memory
238 //!segment
239 size_type get_free_memory() const
240 { return mp_header->get_free_memory(); }
241
242 //!Returns the result of "all_memory_deallocated()" function
243 //!of the used memory algorithm
244 bool all_memory_deallocated()
245 { return mp_header->all_memory_deallocated(); }
246
247 //!Returns the result of "check_sanity()" function
248 //!of the used memory algorithm
249 bool check_sanity()
250 { return mp_header->check_sanity(); }
251
252 //!Writes to zero free memory (memory not yet allocated) of
253 //!the memory algorithm
254 void zero_free_memory()
255 { mp_header->zero_free_memory(); }
256
257 //!Transforms an absolute address into an offset from base address.
258 //!The address must belong to the memory segment. Never throws.
259 handle_t get_handle_from_address (const void *ptr) const
260 {
261 return (handle_t)(reinterpret_cast<const char*>(ptr) -
262 reinterpret_cast<const char*>(this->get_address()));
263 }
264
265 //!Returns true if the address belongs to the managed memory segment
266 bool belongs_to_segment (const void *ptr) const
267 {
268 return ptr >= this->get_address() &&
269 ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
270 }
271
272 //!Transforms previously obtained offset into an absolute address in the
273 //!process space of the current process. Never throws.*/
274 void * get_address_from_handle (handle_t offset) const
275 { return reinterpret_cast<char*>(this->get_address()) + offset; }
276
277 //!Searches for nbytes of free memory in the segment, marks the
278 //!memory as used and return the pointer to the memory. If no
279 //!memory is available throws a boost::interprocess::bad_alloc exception
280 void* allocate (size_type nbytes)
281 { return mp_header->allocate(nbytes); }
282
283 //!Searches for nbytes of free memory in the segment, marks the
284 //!memory as used and return the pointer to the memory. If no memory
285 //!is available returns 0. Never throws.
286 void* allocate (size_type nbytes, const std::nothrow_t &tag)
287 { return mp_header->allocate(nbytes, tag); }
288
289 //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
290 //!must be power of two. If no memory
291 //!is available returns 0. Never throws.
292 void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag)
293 { return mp_header->allocate_aligned(nbytes, alignment, tag); }
294
295 template<class T>
296 T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
297 size_type &prefer_in_recvd_out_size, T *&reuse)
298 { return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
299
300 //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
301 //!must be power of two. If no
302 //!memory is available throws a boost::interprocess::bad_alloc exception
303 void * allocate_aligned(size_type nbytes, size_type alignment)
304 { return mp_header->allocate_aligned(nbytes, alignment); }
305
306 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
307
308 //Experimental. Don't use.
309
310 //!Allocates n_elements of elem_bytes bytes.
311 //!Throws bad_alloc on failure. chain.size() is not increased on failure.
312 void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
313 { mp_header->allocate_many(elem_bytes, n_elements, chain); }
314
315 //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
316 //!Throws bad_alloc on failure. chain.size() is not increased on failure.
317 void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
318 { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
319
320 //!Allocates n_elements of elem_bytes bytes.
321 //!Non-throwing version. chain.size() is not increased on failure.
322 void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
323 { mp_header->allocate_many(tag, elem_bytes, n_elements, chain); }
324
325 //!Allocates n_elements, each one of
326 //!element_lengths[i]*sizeof_element bytes.
327 //!Non-throwing version. chain.size() is not increased on failure.
328 void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
329 { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); }
330
331 //!Deallocates all elements contained in chain.
332 //!Never throws.
333 void deallocate_many(multiallocation_chain &chain)
334 { mp_header->deallocate_many(chain); }
335
336 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
337
338 //!Marks previously allocated memory as free. Never throws.
339 void deallocate (void *addr)
340 { if (mp_header) mp_header->deallocate(addr); }
341
342 //!Tries to find a previous named allocation address. Returns a memory
343 //!buffer and the object count. If not found returned pointer is 0.
344 //!Never throws.
345 template <class T>
346 std::pair<T*, size_type> find (char_ptr_holder_t name)
347 { return mp_header->template find<T>(name); }
348
349 //!Creates a named object or array in memory
350 //!
351 //!Allocates and constructs a T object or an array of T in memory,
352 //!associates this with the given name and returns a pointer to the
353 //!created object. If an array is being constructed all objects are
354 //!created using the same parameters given to this function.
355 //!
356 //!-> If the name was previously used, returns 0.
357 //!
358 //!-> Throws boost::interprocess::bad_alloc if there is no available memory
359 //!
360 //!-> If T's constructor throws, the function throws that exception.
361 //!
362 //!Memory is freed automatically if T's constructor throws and if an
363 //!array was being constructed, destructors of created objects are called
364 //!before freeing the memory.
365 template <class T>
366 typename segment_manager::template construct_proxy<T>::type
367 construct(char_ptr_holder_t name)
368 { return mp_header->template construct<T>(name); }
369
370 //!Finds or creates a named object or array in memory
371 //!
372 //!Tries to find an object with the given name in memory. If
373 //!found, returns the pointer to this pointer. If the object is not found,
374 //!allocates and constructs a T object or an array of T in memory,
375 //!associates this with the given name and returns a pointer to the
376 //!created object. If an array is being constructed all objects are
377 //!created using the same parameters given to this function.
378 //!
379 //!-> Throws boost::interprocess::bad_alloc if there is no available memory
380 //!
381 //!-> If T's constructor throws, the function throws that exception.
382 //!
383 //!Memory is freed automatically if T's constructor throws and if an
384 //!array was being constructed, destructors of created objects are called
385 //!before freeing the memory.
386 template <class T>
387 typename segment_manager::template construct_proxy<T>::type
388 find_or_construct(char_ptr_holder_t name)
389 { return mp_header->template find_or_construct<T>(name); }
390
391 //!Creates a named object or array in memory
392 //!
393 //!Allocates and constructs a T object or an array of T in memory,
394 //!associates this with the given name and returns a pointer to the
395 //!created object. If an array is being constructed all objects are
396 //!created using the same parameters given to this function.
397 //!
398 //!-> If the name was previously used, returns 0.
399 //!
400 //!-> Returns 0 if there is no available memory
401 //!
402 //!-> If T's constructor throws, the function throws that exception.
403 //!
404 //!Memory is freed automatically if T's constructor throws and if an
405 //!array was being constructed, destructors of created objects are called
406 //!before freeing the memory.
407 template <class T>
408 typename segment_manager::template construct_proxy<T>::type
409 construct(char_ptr_holder_t name, const std::nothrow_t &tag)
410 { return mp_header->template construct<T>(name, tag); }
411
412 //!Finds or creates a named object or array in memory
413 //!
414 //!Tries to find an object with the given name in memory. If
415 //!found, returns the pointer to this pointer. If the object is not found,
416 //!allocates and constructs a T object or an array of T in memory,
417 //!associates this with the given name and returns a pointer to the
418 //!created object. If an array is being constructed all objects are
419 //!created using the same parameters given to this function.
420 //!
421 //!-> Returns 0 if there is no available memory
422 //!
423 //!-> If T's constructor throws, the function throws that exception.
424 //!
425 //!Memory is freed automatically if T's constructor throws and if an
426 //!array was being constructed, destructors of created objects are called
427 //!before freeing the memory.
428 template <class T>
429 typename segment_manager::template construct_proxy<T>::type
430 find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag)
431 { return mp_header->template find_or_construct<T>(name, tag); }
432
433 //!Creates a named array from iterators in memory
434 //!
435 //!Allocates and constructs an array of T in memory,
436 //!associates this with the given name and returns a pointer to the
437 //!created object. Each element in the array is created using the
438 //!objects returned when dereferencing iterators as parameters
439 //!and incrementing all iterators for each element.
440 //!
441 //!-> If the name was previously used, returns 0.
442 //!
443 //!-> Throws boost::interprocess::bad_alloc if there is no available memory
444 //!
445 //!-> If T's constructor throws, the function throws that exception.
446 //!
447 //!Memory is freed automatically if T's constructor throws and
448 //!destructors of created objects are called before freeing the memory.
449 template <class T>
450 typename segment_manager::template construct_iter_proxy<T>::type
451 construct_it(char_ptr_holder_t name)
452 { return mp_header->template construct_it<T>(name); }
453
454 //!Finds or creates a named array from iterators in memory
455 //!
456 //!Tries to find an object with the given name in memory. If
457 //!found, returns the pointer to this pointer. If the object is not found,
458 //!allocates and constructs an array of T in memory,
459 //!associates this with the given name and returns a pointer to the
460 //!created object. Each element in the array is created using the
461 //!objects returned when dereferencing iterators as parameters
462 //!and incrementing all iterators for each element.
463 //!
464 //!-> If the name was previously used, returns 0.
465 //!
466 //!-> Throws boost::interprocess::bad_alloc if there is no available memory
467 //!
468 //!-> If T's constructor throws, the function throws that exception.
469 //!
470 //!Memory is freed automatically if T's constructor throws and
471 //!destructors of created objects are called before freeing the memory.
472 template <class T>
473 typename segment_manager::template construct_iter_proxy<T>::type
474 find_or_construct_it(char_ptr_holder_t name)
475 { return mp_header->template find_or_construct_it<T>(name); }
476
477 //!Creates a named array from iterators in memory
478 //!
479 //!Allocates and constructs an array of T in memory,
480 //!associates this with the given name and returns a pointer to the
481 //!created object. Each element in the array is created using the
482 //!objects returned when dereferencing iterators as parameters
483 //!and incrementing all iterators for each element.
484 //!
485 //!-> If the name was previously used, returns 0.
486 //!
487 //!-> If there is no available memory, returns 0.
488 //!
489 //!-> If T's constructor throws, the function throws that exception.
490 //!
491 //!Memory is freed automatically if T's constructor throws and
492 //!destructors of created objects are called before freeing the memory.*/
493 template <class T>
494 typename segment_manager::template construct_iter_proxy<T>::type
495 construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
496 { return mp_header->template construct_it<T>(name, tag); }
497
498 //!Finds or creates a named array from iterators in memory
499 //!
500 //!Tries to find an object with the given name in memory. If
501 //!found, returns the pointer to this pointer. If the object is not found,
502 //!allocates and constructs an array of T in memory,
503 //!associates this with the given name and returns a pointer to the
504 //!created object. Each element in the array is created using the
505 //!objects returned when dereferencing iterators as parameters
506 //!and incrementing all iterators for each element.
507 //!
508 //!-> If the name was previously used, returns 0.
509 //!
510 //!-> If there is no available memory, returns 0.
511 //!
512 //!-> If T's constructor throws, the function throws that exception.
513 //!
514 //!Memory is freed automatically if T's constructor throws and
515 //!destructors of created objects are called before freeing the memory.*/
516 template <class T>
517 typename segment_manager::template construct_iter_proxy<T>::type
518 find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
519 { return mp_header->template find_or_construct_it<T>(name, tag); }
520
521 //!Calls a functor and guarantees that no new construction, search or
522 //!destruction will be executed by any process while executing the object
523 //!function call. If the functor throws, this function throws.
524 template <class Func>
525 void atomic_func(Func &f)
526 { mp_header->atomic_func(f); }
527
528 //!Tries to call a functor guaranteeing that no new construction, search or
529 //!destruction will be executed by any process while executing the object
530 //!function call. If the atomic function can't be immediatelly executed
531 //!because the internal mutex is already locked, returns false.
532 //!If the functor throws, this function throws.
533 template <class Func>
534 bool try_atomic_func(Func &f)
535 { return mp_header->try_atomic_func(f); }
536
537 //!Destroys a named memory object or array.
538 //!
539 //!Finds the object with the given name, calls its destructors,
540 //!frees used memory and returns true.
541 //!
542 //!-> If the object is not found, it returns false.
543 //!
544 //!Exception Handling:
545 //!
546 //!When deleting a dynamically object or array, the Standard
547 //!does not guarantee that dynamically allocated memory, will be released.
548 //!Also, when deleting arrays, the Standard doesn't require calling
549 //!destructors for the rest of the objects if for one of them the destructor
550 //!terminated with an exception.
551 //!
552 //!Destroying an object:
553 //!
554 //!If the destructor throws, the memory will be freed and that exception
555 //!will be thrown.
556 //!
557 //!Destroying an array:
558 //!
559 //!When destroying an array, if a destructor throws, the rest of
560 //!destructors are called. If any of these throws, the exceptions are
561 //!ignored. The name association will be erased, memory will be freed and
562 //!the first exception will be thrown. This guarantees the unlocking of
563 //!mutexes and other resources.
564 //!
565 //!For all theses reasons, classes with throwing destructors are not
566 //!recommended.
567 template <class T>
568 bool destroy(const CharType *name)
569 { return mp_header->template destroy<T>(name); }
570
571 //!Destroys the unique instance of type T
572 //!
573 //!Calls the destructor, frees used memory and returns true.
574 //!
575 //!Exception Handling:
576 //!
577 //!When deleting a dynamically object, the Standard does not
578 //!guarantee that dynamically allocated memory will be released.
579 //!
580 //!Destroying an object:
581 //!
582 //!If the destructor throws, the memory will be freed and that exception
583 //!will be thrown.
584 //!
585 //!For all theses reasons, classes with throwing destructors are not
586 //!recommended for memory.
587 template <class T>
588 bool destroy(const unique_instance_t *const )
589 { return mp_header->template destroy<T>(unique_instance); }
590
591 //!Destroys the object (named, unique, or anonymous)
592 //!
593 //!Calls the destructor, frees used memory and returns true.
594 //!
595 //!Exception Handling:
596 //!
597 //!When deleting a dynamically object, the Standard does not
598 //!guarantee that dynamically allocated memory will be released.
599 //!
600 //!Destroying an object:
601 //!
602 //!If the destructor throws, the memory will be freed and that exception
603 //!will be thrown.
604 //!
605 //!For all theses reasons, classes with throwing destructors are not
606 //!recommended for memory.
607 template <class T>
608 void destroy_ptr(const T *ptr)
609 { mp_header->template destroy_ptr<T>(ptr); }
610
611 //!Returns the name of an object created with construct/find_or_construct
612 //!functions. If ptr points to an unique instance typeid(T).name() is returned.
613 template<class T>
614 static const char_type *get_instance_name(const T *ptr)
615 { return segment_manager::get_instance_name(ptr); }
616
617 //!Returns is the type an object created with construct/find_or_construct
618 //!functions. Does not throw.
619 template<class T>
620 static instance_type get_instance_type(const T *ptr)
621 { return segment_manager::get_instance_type(ptr); }
622
623 //!Returns the length of an object created with construct/find_or_construct
624 //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
625 template<class T>
626 static size_type get_instance_length(const T *ptr)
627 { return segment_manager::get_instance_length(ptr); }
628
629 //!Preallocates needed index resources to optimize the
630 //!creation of "num" named objects in the memory segment.
631 //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
632 void reserve_named_objects(size_type num)
633 { mp_header->reserve_named_objects(num); }
634
635 //!Preallocates needed index resources to optimize the
636 //!creation of "num" unique objects in the memory segment.
637 //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
638 void reserve_unique_objects(size_type num)
639 { mp_header->reserve_unique_objects(num); }
640
641 //!Calls shrink_to_fit in both named and unique object indexes
642 //to try to free unused memory from those indexes.
643 void shrink_to_fit_indexes()
644 { mp_header->shrink_to_fit_indexes(); }
645
646 //!Returns the number of named objects stored
647 //!in the managed segment.
648 size_type get_num_named_objects()
649 { return mp_header->get_num_named_objects(); }
650
651 //!Returns the number of unique objects stored
652 //!in the managed segment.
653 size_type get_num_unique_objects()
654 { return mp_header->get_num_unique_objects(); }
655
656 //!Returns a constant iterator to the index storing the
657 //!named allocations. NOT thread-safe. Never throws.
658 const_named_iterator named_begin() const
659 { return mp_header->named_begin(); }
660
661 //!Returns a constant iterator to the end of the index
662 //!storing the named allocations. NOT thread-safe. Never throws.
663 const_named_iterator named_end() const
664 { return mp_header->named_end(); }
665
666 //!Returns a constant iterator to the index storing the
667 //!unique allocations. NOT thread-safe. Never throws.
668 const_unique_iterator unique_begin() const
669 { return mp_header->unique_begin(); }
670
671 //!Returns a constant iterator to the end of the index
672 //!storing the unique allocations. NOT thread-safe. Never throws.
673 const_unique_iterator unique_end() const
674 { return mp_header->unique_end(); }
675
676 //!This is the default allocator to allocate types T
677 //!from this managed segment
678 template<class T>
679 struct allocator
680 {
681 typedef typename segment_manager::template allocator<T>::type type;
682 };
683
684 //!Returns an instance of the default allocator for type T
685 //!initialized that allocates memory from this segment manager.
686 template<class T>
687 typename allocator<T>::type
688 get_allocator()
689 { return mp_header->template get_allocator<T>(); }
690
691 //!This is the default deleter to delete types T
692 //!from this managed segment.
693 template<class T>
694 struct deleter
695 {
696 typedef typename segment_manager::template deleter<T>::type type;
697 };
698
699 //!Returns an instance of the default allocator for type T
700 //!initialized that allocates memory from this segment manager.
701 template<class T>
702 typename deleter<T>::type
703 get_deleter()
704 { return mp_header->template get_deleter<T>(); }
705
706 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
707 //!Tries to find a previous named allocation address. Returns a memory
708 //!buffer and the object count. If not found returned pointer is 0.
709 //!Never throws.
710 template <class T>
711 std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
712 { return mp_header->template find_no_lock<T>(name); }
713 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
714
715 protected:
716 //!Swaps the segment manager's managed by this managed memory segment.
717 //!NOT thread-safe. Never throws.
718 void swap(basic_managed_memory_impl &other)
719 { (simple_swap)(mp_header, other.mp_header); }
720
721 private:
722 segment_manager *mp_header;
723 };
724
725 template<class BasicManagedMemoryImpl>
726 class create_open_func
727 {
728 typedef typename BasicManagedMemoryImpl::size_type size_type;
729
730 public:
731
732 create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
733 : m_frontend(frontend), m_type(type){}
734
735 bool operator()(void *addr, std::size_t size, bool created) const
736 {
737 if( ((m_type == DoOpen) && created) ||
738 ((m_type == DoCreate) && !created) ||
739 //Check for overflow
740 size_type(-1) < size ){
741 return false;
742 }
743 else if(created){
744 return m_frontend->create_impl(addr, static_cast<size_type>(size));
745 }
746 else{
747 return m_frontend->open_impl (addr, static_cast<size_type>(size));
748 }
749 }
750
751 static std::size_t get_min_size()
752 {
753 const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size();
754 if(sz > std::size_t(-1)){
755 //The minimum size is not representable by std::size_t
756 BOOST_ASSERT(false);
757 return std::size_t(-1);
758 }
759 else{
760 return static_cast<std::size_t>(sz);
761 }
762 }
763
764 private:
765 BasicManagedMemoryImpl *m_frontend;
766 create_enum_t m_type;
767 };
768
769 } //namespace ipcdetail {
770 } //namespace interprocess {
771 } //namespace boost {
772
773 #include <boost/interprocess/detail/config_end.hpp>
774
775 #endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
776