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>
grow(const char * filename,size_type extra_bytes)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>
shrink_to_fit(const char * filename)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.
basic_managed_memory_impl()160    basic_managed_memory_impl()
161       : mp_header(0){}
162 
163    //!Destructor. Calls close. Never throws.
~basic_managed_memory_impl()164    ~basic_managed_memory_impl()
165    {  this->close_impl(); }
166 
167    //!Places segment manager in the reserved space. This can throw.
create_impl(void * addr,size_type size)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          mp_header       = ::new(addr, boost_container_new_t()) segment_manager(size);
181       }
182       BOOST_CATCH(...){
183          return false;
184       }
185       BOOST_CATCH_END
186       return true;
187    }
188 
189    //!Connects to a segment manager in the reserved buffer. Never throws.
open_impl(void * addr,size_type)190    bool  open_impl     (void *addr, size_type)
191    {
192       if(mp_header)  return false;
193       mp_header = static_cast<segment_manager*>(addr);
194       return true;
195    }
196 
197    //!Frees resources. Never throws.
close_impl()198    bool close_impl()
199    {
200       bool ret = mp_header != 0;
201       mp_header = 0;
202       return ret;
203    }
204 
205    //!Frees resources and destroys common resources. Never throws.
destroy_impl()206    bool destroy_impl()
207    {
208       if(mp_header == 0)
209          return false;
210       mp_header->~segment_manager();
211       this->close_impl();
212          return true;
213    }
214 
215    //!
grow(size_type extra_bytes)216    void grow(size_type extra_bytes)
217    {  mp_header->grow(extra_bytes); }
218 
shrink_to_fit()219    void shrink_to_fit()
220    {  mp_header->shrink_to_fit(); }
221 
222    public:
223 
224    //!Returns segment manager. Never throws.
get_segment_manager() const225    segment_manager *get_segment_manager() const
226    {   return mp_header; }
227 
228    //!Returns the base address of the memory in this process. Never throws.
get_address() const229    void *   get_address   () const
230    {   return reinterpret_cast<char*>(mp_header) - Offset; }
231 
232    //!Returns the size of memory segment. Never throws.
get_size() const233    size_type   get_size   () const
234    {   return mp_header->get_size() + Offset;  }
235 
236    //!Returns the number of free bytes of the memory
237    //!segment
get_free_memory() const238    size_type get_free_memory() const
239    {  return mp_header->get_free_memory();  }
240 
241    //!Returns the result of "all_memory_deallocated()" function
242    //!of the used memory algorithm
all_memory_deallocated()243    bool all_memory_deallocated()
244    {   return mp_header->all_memory_deallocated(); }
245 
246    //!Returns the result of "check_sanity()" function
247    //!of the used memory algorithm
check_sanity()248    bool check_sanity()
249    {   return mp_header->check_sanity(); }
250 
251    //!Writes to zero free memory (memory not yet allocated) of
252    //!the memory algorithm
zero_free_memory()253    void zero_free_memory()
254    {   mp_header->zero_free_memory(); }
255 
256    //!Transforms an absolute address into an offset from base address.
257    //!The address must belong to the memory segment. Never throws.
get_handle_from_address(const void * ptr) const258    handle_t get_handle_from_address   (const void *ptr) const
259    {
260       return (handle_t)(reinterpret_cast<const char*>(ptr) -
261              reinterpret_cast<const char*>(this->get_address()));
262    }
263 
264    //!Returns true if the address belongs to the managed memory segment
belongs_to_segment(const void * ptr) const265    bool belongs_to_segment (const void *ptr) const
266    {
267       return ptr >= this->get_address() &&
268              ptr <  (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
269    }
270 
271    //!Transforms previously obtained offset into an absolute address in the
272    //!process space of the current process. Never throws.*/
get_address_from_handle(handle_t offset) const273    void *    get_address_from_handle (handle_t offset) const
274    {  return reinterpret_cast<char*>(this->get_address()) + offset; }
275 
276    //!Searches for nbytes of free memory in the segment, marks the
277    //!memory as used and return the pointer to the memory. If no
278    //!memory is available throws a boost::interprocess::bad_alloc exception
allocate(size_type nbytes)279    void* allocate             (size_type nbytes)
280    {   return mp_header->allocate(nbytes);   }
281 
282    //!Searches for nbytes of free memory in the segment, marks the
283    //!memory as used and return the pointer to the memory. If no memory
284    //!is available returns 0. Never throws.
allocate(size_type nbytes,const std::nothrow_t & tag)285    void* allocate             (size_type nbytes, const std::nothrow_t &tag)
286    {   return mp_header->allocate(nbytes, tag);  }
287 
288    //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
289    //!must be power of two. If no memory
290    //!is available returns 0. Never throws.
allocate_aligned(size_type nbytes,size_type alignment,const std::nothrow_t & tag)291    void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag)
292    {   return mp_header->allocate_aligned(nbytes, alignment, tag);  }
293 
294    template<class T>
allocation_command(boost::interprocess::allocation_type command,size_type limit_size,size_type & prefer_in_recvd_out_size,T * & reuse)295    T * allocation_command  (boost::interprocess::allocation_type command,   size_type limit_size,
296                            size_type &prefer_in_recvd_out_size, T *&reuse)
297    {  return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);  }
298 
299    //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
300    //!must be power of two. If no
301    //!memory is available throws a boost::interprocess::bad_alloc exception
allocate_aligned(size_type nbytes,size_type alignment)302    void * allocate_aligned(size_type nbytes, size_type alignment)
303    {   return mp_header->allocate_aligned(nbytes, alignment);  }
304 
305    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
306 
307    //Experimental. Don't use.
308 
309    //!Allocates n_elements of elem_bytes bytes.
310    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
allocate_many(size_type elem_bytes,size_type n_elements,multiallocation_chain & chain)311    void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
312    {  mp_header->allocate_many(elem_bytes, n_elements, chain); }
313 
314    //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
315    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
allocate_many(const size_type * element_lengths,size_type n_elements,size_type sizeof_element,multiallocation_chain & chain)316    void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
317    {  mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
318 
319    //!Allocates n_elements of elem_bytes bytes.
320    //!Non-throwing version. chain.size() is not increased on failure.
allocate_many(const std::nothrow_t & tag,size_type elem_bytes,size_type n_elements,multiallocation_chain & chain)321    void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
322    {  mp_header->allocate_many(tag, elem_bytes, n_elements, chain); }
323 
324    //!Allocates n_elements, each one of
325    //!element_lengths[i]*sizeof_element bytes.
326    //!Non-throwing version. chain.size() is not increased on failure.
allocate_many(const std::nothrow_t & tag,const size_type * elem_sizes,size_type n_elements,size_type sizeof_element,multiallocation_chain & chain)327    void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
328    {  mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); }
329 
330    //!Deallocates all elements contained in chain.
331    //!Never throws.
deallocate_many(multiallocation_chain & chain)332    void deallocate_many(multiallocation_chain &chain)
333    {  mp_header->deallocate_many(chain); }
334 
335    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
336 
337    //!Marks previously allocated memory as free. Never throws.
deallocate(void * addr)338    void  deallocate           (void *addr)
339    {   if (mp_header) mp_header->deallocate(addr);  }
340 
341    //!Tries to find a previous named allocation address. Returns a memory
342    //!buffer and the object count. If not found returned pointer is 0.
343    //!Never throws.
344    template <class T>
find(char_ptr_holder_t name)345    std::pair<T*, size_type> find  (char_ptr_holder_t name)
346    {   return mp_header->template find<T>(name); }
347 
348    //!Creates a named object or array in memory
349    //!
350    //!Allocates and constructs a T object or an array of T in memory,
351    //!associates this with the given name and returns a pointer to the
352    //!created object. If an array is being constructed all objects are
353    //!created using the same parameters given to this function.
354    //!
355    //!-> If the name was previously used, returns 0.
356    //!
357    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
358    //!
359    //!-> If T's constructor throws, the function throws that exception.
360    //!
361    //!Memory is freed automatically if T's constructor throws and if an
362    //!array was being constructed, destructors of created objects are called
363    //!before freeing the memory.
364    template <class T>
365    typename segment_manager::template construct_proxy<T>::type
construct(char_ptr_holder_t name)366       construct(char_ptr_holder_t name)
367    {   return mp_header->template construct<T>(name);  }
368 
369    //!Finds or creates a named object or array in memory
370    //!
371    //!Tries to find an object with the given name in memory. If
372    //!found, returns the pointer to this pointer. If the object is not found,
373    //!allocates and constructs a T object or an array of T in memory,
374    //!associates this with the given name and returns a pointer to the
375    //!created object. If an array is being constructed all objects are
376    //!created using the same parameters given to this function.
377    //!
378    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
379    //!
380    //!-> If T's constructor throws, the function throws that exception.
381    //!
382    //!Memory is freed automatically if T's constructor throws and if an
383    //!array was being constructed, destructors of created objects are called
384    //!before freeing the memory.
385    template <class T>
386    typename segment_manager::template construct_proxy<T>::type
find_or_construct(char_ptr_holder_t name)387       find_or_construct(char_ptr_holder_t name)
388    {   return mp_header->template find_or_construct<T>(name);  }
389 
390    //!Creates a named object or array in memory
391    //!
392    //!Allocates and constructs a T object or an array of T in memory,
393    //!associates this with the given name and returns a pointer to the
394    //!created object. If an array is being constructed all objects are
395    //!created using the same parameters given to this function.
396    //!
397    //!-> If the name was previously used, returns 0.
398    //!
399    //!-> Returns 0 if there is no available memory
400    //!
401    //!-> If T's constructor throws, the function throws that exception.
402    //!
403    //!Memory is freed automatically if T's constructor throws and if an
404    //!array was being constructed, destructors of created objects are called
405    //!before freeing the memory.
406    template <class T>
407    typename segment_manager::template construct_proxy<T>::type
construct(char_ptr_holder_t name,const std::nothrow_t & tag)408       construct(char_ptr_holder_t name, const std::nothrow_t &tag)
409    {   return mp_header->template construct<T>(name, tag);  }
410 
411    //!Finds or creates a named object or array in memory
412    //!
413    //!Tries to find an object with the given name in memory. If
414    //!found, returns the pointer to this pointer. If the object is not found,
415    //!allocates and constructs a T object or an array of T in memory,
416    //!associates this with the given name and returns a pointer to the
417    //!created object. If an array is being constructed all objects are
418    //!created using the same parameters given to this function.
419    //!
420    //!-> Returns 0 if there is no available memory
421    //!
422    //!-> If T's constructor throws, the function throws that exception.
423    //!
424    //!Memory is freed automatically if T's constructor throws and if an
425    //!array was being constructed, destructors of created objects are called
426    //!before freeing the memory.
427    template <class T>
428    typename segment_manager::template construct_proxy<T>::type
find_or_construct(char_ptr_holder_t name,const std::nothrow_t & tag)429       find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag)
430    {   return mp_header->template find_or_construct<T>(name, tag);  }
431 
432    //!Creates a named array from iterators in memory
433    //!
434    //!Allocates and constructs an array of T in memory,
435    //!associates this with the given name and returns a pointer to the
436    //!created object. Each element in the array is created using the
437    //!objects returned when dereferencing iterators as parameters
438    //!and incrementing all iterators for each element.
439    //!
440    //!-> If the name was previously used, returns 0.
441    //!
442    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
443    //!
444    //!-> If T's constructor throws, the function throws that exception.
445    //!
446    //!Memory is freed automatically if T's constructor throws and
447    //!destructors of created objects are called before freeing the memory.
448    template <class T>
449    typename segment_manager::template construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name)450       construct_it(char_ptr_holder_t name)
451    {   return mp_header->template construct_it<T>(name);  }
452 
453    //!Finds or creates a named array from iterators in memory
454    //!
455    //!Tries to find an object with the given name in memory. If
456    //!found, returns the pointer to this pointer. If the object is not found,
457    //!allocates and constructs an array of T in memory,
458    //!associates this with the given name and returns a pointer to the
459    //!created object. Each element in the array is created using the
460    //!objects returned when dereferencing iterators as parameters
461    //!and incrementing all iterators for each element.
462    //!
463    //!-> If the name was previously used, returns 0.
464    //!
465    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
466    //!
467    //!-> If T's constructor throws, the function throws that exception.
468    //!
469    //!Memory is freed automatically if T's constructor throws and
470    //!destructors of created objects are called before freeing the memory.
471    template <class T>
472    typename segment_manager::template construct_iter_proxy<T>::type
find_or_construct_it(char_ptr_holder_t name)473       find_or_construct_it(char_ptr_holder_t name)
474    {   return mp_header->template find_or_construct_it<T>(name);  }
475 
476    //!Creates a named array from iterators in memory
477    //!
478    //!Allocates and constructs an array of T in memory,
479    //!associates this with the given name and returns a pointer to the
480    //!created object. Each element in the array is created using the
481    //!objects returned when dereferencing iterators as parameters
482    //!and incrementing all iterators for each element.
483    //!
484    //!-> If the name was previously used, returns 0.
485    //!
486    //!-> If there is no available memory, returns 0.
487    //!
488    //!-> If T's constructor throws, the function throws that exception.
489    //!
490    //!Memory is freed automatically if T's constructor throws and
491    //!destructors of created objects are called before freeing the memory.*/
492    template <class T>
493    typename segment_manager::template construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name,const std::nothrow_t & tag)494       construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
495    {   return mp_header->template construct_it<T>(name, tag);  }
496 
497    //!Finds or creates a named array from iterators in memory
498    //!
499    //!Tries to find an object with the given name in memory. If
500    //!found, returns the pointer to this pointer. If the object is not found,
501    //!allocates and constructs an array of T in memory,
502    //!associates this with the given name and returns a pointer to the
503    //!created object. Each element in the array is created using the
504    //!objects returned when dereferencing iterators as parameters
505    //!and incrementing all iterators for each element.
506    //!
507    //!-> If the name was previously used, returns 0.
508    //!
509    //!-> If there is no available memory, returns 0.
510    //!
511    //!-> If T's constructor throws, the function throws that exception.
512    //!
513    //!Memory is freed automatically if T's constructor throws and
514    //!destructors of created objects are called before freeing the memory.*/
515    template <class T>
516    typename segment_manager::template construct_iter_proxy<T>::type
find_or_construct_it(char_ptr_holder_t name,const std::nothrow_t & tag)517       find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
518    {   return mp_header->template find_or_construct_it<T>(name, tag);  }
519 
520    //!Calls a functor and guarantees that no new construction, search or
521    //!destruction will be executed by any process while executing the object
522    //!function call. If the functor throws, this function throws.
523    template <class Func>
atomic_func(Func & f)524    void atomic_func(Func &f)
525    {   mp_header->atomic_func(f);  }
526 
527    //!Tries to call a functor guaranteeing that no new construction, search or
528    //!destruction will be executed by any process while executing the object
529    //!function call. If the atomic function can't be immediatelly executed
530    //!because the internal mutex is already locked, returns false.
531    //!If the functor throws, this function throws.
532    template <class Func>
try_atomic_func(Func & f)533    bool try_atomic_func(Func &f)
534    {   return mp_header->try_atomic_func(f); }
535 
536    //!Destroys a named memory object or array.
537    //!
538    //!Finds the object with the given name, calls its destructors,
539    //!frees used memory and returns true.
540    //!
541    //!-> If the object is not found, it returns false.
542    //!
543    //!Exception Handling:
544    //!
545    //!When deleting a dynamically object or array, the Standard
546    //!does not guarantee that dynamically allocated memory, will be released.
547    //!Also, when deleting arrays, the Standard doesn't require calling
548    //!destructors for the rest of the objects if for one of them the destructor
549    //!terminated with an exception.
550    //!
551    //!Destroying an object:
552    //!
553    //!If the destructor throws, the memory will be freed and that exception
554    //!will be thrown.
555    //!
556    //!Destroying an array:
557    //!
558    //!When destroying an array, if a destructor throws, the rest of
559    //!destructors are called. If any of these throws, the exceptions are
560    //!ignored. The name association will be erased, memory will be freed and
561    //!the first exception will be thrown. This guarantees the unlocking of
562    //!mutexes and other resources.
563    //!
564    //!For all theses reasons, classes with throwing destructors are not
565    //!recommended.
566    template <class T>
destroy(const CharType * name)567    bool destroy(const CharType *name)
568    {   return mp_header->template destroy<T>(name); }
569 
570    //!Destroys the unique instance of type T
571    //!
572    //!Calls the destructor, frees used memory and returns true.
573    //!
574    //!Exception Handling:
575    //!
576    //!When deleting a dynamically object, the Standard does not
577    //!guarantee that dynamically allocated memory will be released.
578    //!
579    //!Destroying an object:
580    //!
581    //!If the destructor throws, the memory will be freed and that exception
582    //!will be thrown.
583    //!
584    //!For all theses reasons, classes with throwing destructors are not
585    //!recommended for  memory.
586    template <class T>
destroy(const unique_instance_t * const)587    bool destroy(const unique_instance_t *const )
588    {   return mp_header->template destroy<T>(unique_instance);  }
589 
590    //!Destroys the object (named, unique, or anonymous)
591    //!
592    //!Calls the destructor, frees used memory and returns true.
593    //!
594    //!Exception Handling:
595    //!
596    //!When deleting a dynamically object, the Standard does not
597    //!guarantee that dynamically allocated memory will be released.
598    //!
599    //!Destroying an object:
600    //!
601    //!If the destructor throws, the memory will be freed and that exception
602    //!will be thrown.
603    //!
604    //!For all theses reasons, classes with throwing destructors are not
605    //!recommended for  memory.
606    template <class T>
destroy_ptr(const T * ptr)607    void destroy_ptr(const T *ptr)
608    {  mp_header->template destroy_ptr<T>(ptr); }
609 
610    //!Returns the name of an object created with construct/find_or_construct
611    //!functions. If ptr points to an unique instance typeid(T).name() is returned.
612    template<class T>
get_instance_name(const T * ptr)613    static const char_type *get_instance_name(const T *ptr)
614    {  return segment_manager::get_instance_name(ptr);   }
615 
616    //!Returns is the type an object created with construct/find_or_construct
617    //!functions. Does not throw.
618    template<class T>
get_instance_type(const T * ptr)619    static instance_type get_instance_type(const T *ptr)
620    {  return segment_manager::get_instance_type(ptr); }
621 
622    //!Returns the length of an object created with construct/find_or_construct
623    //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
624    template<class T>
get_instance_length(const T * ptr)625    static size_type get_instance_length(const T *ptr)
626    {  return segment_manager::get_instance_length(ptr); }
627 
628    //!Preallocates needed index resources to optimize the
629    //!creation of "num" named objects in the  memory segment.
630    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
reserve_named_objects(size_type num)631    void reserve_named_objects(size_type num)
632    {  mp_header->reserve_named_objects(num);  }
633 
634    //!Preallocates needed index resources to optimize the
635    //!creation of "num" unique objects in the  memory segment.
636    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
reserve_unique_objects(size_type num)637    void reserve_unique_objects(size_type num)
638    {  mp_header->reserve_unique_objects(num);  }
639 
640    //!Calls shrink_to_fit in both named and unique object indexes
641    //to try to free unused memory from those indexes.
shrink_to_fit_indexes()642    void shrink_to_fit_indexes()
643    {  mp_header->shrink_to_fit_indexes();  }
644 
645    //!Returns the number of named objects stored
646    //!in the managed segment.
get_num_named_objects()647    size_type get_num_named_objects()
648    {  return mp_header->get_num_named_objects();  }
649 
650    //!Returns the number of unique objects stored
651    //!in the managed segment.
get_num_unique_objects()652    size_type get_num_unique_objects()
653    {  return mp_header->get_num_unique_objects();  }
654 
655    //!Returns a constant iterator to the index storing the
656    //!named allocations. NOT thread-safe. Never throws.
named_begin() const657    const_named_iterator named_begin() const
658    {  return mp_header->named_begin(); }
659 
660    //!Returns a constant iterator to the end of the index
661    //!storing the named allocations. NOT thread-safe. Never throws.
named_end() const662    const_named_iterator named_end() const
663    {  return mp_header->named_end(); }
664 
665    //!Returns a constant iterator to the index storing the
666    //!unique allocations. NOT thread-safe. Never throws.
unique_begin() const667    const_unique_iterator unique_begin() const
668    {  return mp_header->unique_begin(); }
669 
670    //!Returns a constant iterator to the end of the index
671    //!storing the unique allocations. NOT thread-safe. Never throws.
unique_end() const672    const_unique_iterator unique_end() const
673    {  return mp_header->unique_end(); }
674 
675    //!This is the default allocator to allocate types T
676    //!from this managed segment
677    template<class T>
678    struct allocator
679    {
680       typedef typename segment_manager::template allocator<T>::type type;
681    };
682 
683    //!Returns an instance of the default allocator for type T
684    //!initialized that allocates memory from this segment manager.
685    template<class T>
686    typename allocator<T>::type
get_allocator()687       get_allocator()
688    {   return mp_header->template get_allocator<T>(); }
689 
690    //!This is the default deleter to delete types T
691    //!from this managed segment.
692    template<class T>
693    struct deleter
694    {
695       typedef typename segment_manager::template deleter<T>::type type;
696    };
697 
698    //!Returns an instance of the default allocator for type T
699    //!initialized that allocates memory from this segment manager.
700    template<class T>
701    typename deleter<T>::type
get_deleter()702       get_deleter()
703    {   return mp_header->template get_deleter<T>(); }
704 
705    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
706    //!Tries to find a previous named allocation address. Returns a memory
707    //!buffer and the object count. If not found returned pointer is 0.
708    //!Never throws.
709    template <class T>
find_no_lock(char_ptr_holder_t name)710    std::pair<T*, size_type> find_no_lock  (char_ptr_holder_t name)
711    {   return mp_header->template find_no_lock<T>(name); }
712    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
713 
714    protected:
715    //!Swaps the segment manager's managed by this managed memory segment.
716    //!NOT thread-safe. Never throws.
swap(basic_managed_memory_impl & other)717    void swap(basic_managed_memory_impl &other)
718    {  (simple_swap)(mp_header, other.mp_header); }
719 
720    private:
721    segment_manager *mp_header;
722 };
723 
724 template<class BasicManagedMemoryImpl>
725 class create_open_func
726 {
727    typedef typename BasicManagedMemoryImpl::size_type size_type;
728 
729    public:
730 
create_open_func(BasicManagedMemoryImpl * const frontend,create_enum_t type)731    create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
732       : m_frontend(frontend), m_type(type){}
733 
operator ()(void * addr,std::size_t size,bool created) const734    bool operator()(void *addr, std::size_t size, bool created) const
735    {
736       if( ((m_type == DoOpen)   &&  created) ||
737           ((m_type == DoCreate) && !created) ||
738           //Check for overflow
739           size_type(-1) < size ){
740          return false;
741       }
742       else if(created){
743          return m_frontend->create_impl(addr, static_cast<size_type>(size));
744       }
745       else{
746          return m_frontend->open_impl  (addr, static_cast<size_type>(size));
747       }
748    }
749 
get_min_size()750    static std::size_t get_min_size()
751    {
752       const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size();
753       if(sz > std::size_t(-1)){
754          //The minimum size is not representable by std::size_t
755          BOOST_ASSERT(false);
756          return std::size_t(-1);
757       }
758       else{
759          return static_cast<std::size_t>(sz);
760       }
761    }
762 
763    private:
764    BasicManagedMemoryImpl *m_frontend;
765    create_enum_t           m_type;
766 };
767 
768 }  //namespace ipcdetail {
769 }  //namespace interprocess {
770 }  //namespace boost {
771 
772 #include <boost/interprocess/detail/config_end.hpp>
773 
774 #endif   //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
775 
776