• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          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.
open_impl(void * addr,size_type)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.
close_impl()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.
destroy_impl()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    //!
grow(size_type extra_bytes)217    void grow(size_type extra_bytes)
218    {  mp_header->grow(extra_bytes); }
219 
shrink_to_fit()220    void shrink_to_fit()
221    {  mp_header->shrink_to_fit(); }
222 
223    public:
224 
225    //!Returns segment manager. Never throws.
get_segment_manager() const226    segment_manager *get_segment_manager() const
227    {   return mp_header; }
228 
229    //!Returns the base address of the memory in this process. Never throws.
get_address() const230    void *   get_address   () const
231    {   return reinterpret_cast<char*>(mp_header) - Offset; }
232 
233    //!Returns the size of memory segment. Never throws.
get_size() const234    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
get_free_memory() const239    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
all_memory_deallocated()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
check_sanity()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
zero_free_memory()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.
get_handle_from_address(const void * ptr) const259    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
belongs_to_segment(const void * ptr) const266    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.*/
get_address_from_handle(handle_t offset) const274    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
allocate(size_type nbytes)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.
allocate(size_type nbytes,const std::nothrow_t & tag)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.
allocate_aligned(size_type nbytes,size_type alignment,const std::nothrow_t & tag)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>
allocation_command(boost::interprocess::allocation_type command,size_type limit_size,size_type & prefer_in_recvd_out_size,T * & reuse)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
allocate_aligned(size_type nbytes,size_type alignment)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.
allocate_many(size_type elem_bytes,size_type n_elements,multiallocation_chain & chain)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.
allocate_many(const size_type * element_lengths,size_type n_elements,size_type sizeof_element,multiallocation_chain & chain)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.
allocate_many(const std::nothrow_t & tag,size_type elem_bytes,size_type n_elements,multiallocation_chain & chain)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.
allocate_many(const std::nothrow_t & tag,const size_type * elem_sizes,size_type n_elements,size_type sizeof_element,multiallocation_chain & chain)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.
deallocate_many(multiallocation_chain & chain)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.
deallocate(void * addr)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>
find(char_ptr_holder_t name)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
construct(char_ptr_holder_t name)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
find_or_construct(char_ptr_holder_t name)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
construct(char_ptr_holder_t name,const std::nothrow_t & tag)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
find_or_construct(char_ptr_holder_t name,const std::nothrow_t & tag)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
construct_it(char_ptr_holder_t name)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
find_or_construct_it(char_ptr_holder_t name)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
construct_it(char_ptr_holder_t name,const std::nothrow_t & tag)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
find_or_construct_it(char_ptr_holder_t name,const std::nothrow_t & tag)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>
atomic_func(Func & f)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>
try_atomic_func(Func & f)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>
destroy(const CharType * name)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>
destroy(const unique_instance_t * const)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>
destroy_ptr(const T * ptr)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>
get_instance_name(const T * ptr)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>
get_instance_type(const T * ptr)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>
get_instance_length(const T * ptr)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.
reserve_named_objects(size_type num)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.
reserve_unique_objects(size_type num)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.
shrink_to_fit_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.
get_num_named_objects()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.
get_num_unique_objects()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.
named_begin() const658    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.
named_end() const663    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.
unique_begin() const668    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.
unique_end() const673    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
get_allocator()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
get_deleter()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>
find_no_lock(char_ptr_holder_t name)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.
swap(basic_managed_memory_impl & other)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 
create_open_func(BasicManagedMemoryImpl * const frontend,create_enum_t type)732    create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
733       : m_frontend(frontend), m_type(type){}
734 
operator ()(void * addr,std::size_t size,bool created) const735    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 
get_min_size()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 
777