Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:37:02

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
0012 #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 #  pragma once
0020 #endif
0021 
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024 
0025 #include <boost/interprocess/interprocess_fwd.hpp>
0026 #include <boost/interprocess/detail/utilities.hpp>
0027 #include <boost/interprocess/detail/os_file_functions.hpp>
0028 #include <boost/interprocess/creation_tags.hpp>
0029 #include <boost/interprocess/exceptions.hpp>
0030 #include <boost/interprocess/segment_manager.hpp>
0031 #include <boost/interprocess/sync/scoped_lock.hpp>
0032 #include <boost/interprocess/detail/nothrow.hpp>
0033 #include <boost/interprocess/detail/simple_swap.hpp>
0034 //
0035 //
0036 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0037 #include <boost/assert.hpp>
0038 
0039 //!\file
0040 //!Describes a named shared memory allocation user class.
0041 //!
0042 
0043 namespace boost {
0044 namespace interprocess {
0045 namespace ipcdetail {
0046 
0047 template<class BasicManagedMemoryImpl>
0048 class create_open_func;
0049 
0050 template<
0051          class CharType,
0052          class MemoryAlgorithm,
0053          template<class IndexConfig> class IndexType
0054         >
0055 struct segment_manager_type
0056 {
0057    typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
0058 };
0059 
0060 //!This class is designed to be a base class to classes that manage
0061 //!creation of objects in a fixed size memory buffer. Apart
0062 //!from allocating raw memory, the user can construct named objects. To
0063 //!achieve this, this class uses the reserved space provided by the allocation
0064 //!algorithm to place a named_allocator_algo, who takes care of name mappings.
0065 //!The class can be customized with the char type used for object names
0066 //!and the memory allocation algorithm to be used.*/
0067 template <  class CharType
0068          ,  class MemoryAlgorithm
0069          ,  template<class IndexConfig> class IndexType
0070          ,  std::size_t Offset = 0
0071          >
0072 class basic_managed_memory_impl
0073 {
0074    //Non-copyable
0075    basic_managed_memory_impl(const basic_managed_memory_impl &);
0076    basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
0077 
0078    template<class BasicManagedMemoryImpl>
0079    friend class create_open_func;
0080 
0081    public:
0082    typedef typename segment_manager_type
0083       <CharType, MemoryAlgorithm, IndexType>::type    segment_manager;
0084    typedef CharType                                   char_type;
0085    typedef MemoryAlgorithm                            memory_algorithm;
0086    typedef typename MemoryAlgorithm::mutex_family     mutex_family;
0087    typedef CharType                                   char_t;
0088    typedef typename MemoryAlgorithm::size_type        size_type;
0089    typedef typename MemoryAlgorithm::difference_type  difference_type;
0090    typedef difference_type                            handle_t;
0091    typedef typename segment_manager::
0092       const_named_iterator                            const_named_iterator;
0093    typedef typename segment_manager::
0094       const_unique_iterator                           const_unique_iterator;
0095 
0096    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0097 
0098    typedef typename
0099            segment_manager::char_ptr_holder_t         char_ptr_holder_t;
0100    //Experimental. Don't use.
0101 
0102    typedef typename segment_manager::multiallocation_chain  multiallocation_chain;
0103 
0104    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0105 
0106    static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
0107 
0108    private:
0109    typedef basic_managed_memory_impl
0110                <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
0111    protected:
0112    template<class ManagedMemory, class CharT>
0113    static bool grow(const CharT *filename, size_type extra_bytes)
0114    {
0115       typedef typename ManagedMemory::device_type device_type;
0116       //Increase file size
0117       BOOST_INTERPROCESS_TRY{
0118          offset_t old_size;
0119          {
0120             device_type f(open_or_create, filename, read_write);
0121             if(!f.get_size(old_size))
0122                return false;
0123             f.truncate(old_size + static_cast<offset_t>(extra_bytes));
0124          }
0125          ManagedMemory managed_memory(open_only, filename);
0126          //Grow always works
0127          managed_memory.self_t::grow(extra_bytes);
0128       }
0129       BOOST_INTERPROCESS_CATCH(...){
0130          return false;
0131       } BOOST_INTERPROCESS_CATCH_END
0132       return true;
0133    }
0134 
0135    template<class ManagedMemory, class CharT>
0136    static bool shrink_to_fit(const CharT *filename)
0137    {
0138       typedef typename ManagedMemory::device_type device_type;
0139       size_type new_size;
0140       BOOST_INTERPROCESS_TRY{
0141          ManagedMemory managed_memory(open_only, filename);
0142          managed_memory.get_size();
0143          managed_memory.self_t::shrink_to_fit();
0144          new_size = managed_memory.get_size();
0145       }
0146       BOOST_INTERPROCESS_CATCH(...){
0147          return false;
0148       } BOOST_INTERPROCESS_CATCH_END
0149 
0150       //Decrease file size
0151       {
0152          device_type f(open_or_create, filename, read_write);
0153          f.truncate(static_cast<offset_t>(new_size));
0154       }
0155       return true;
0156    }
0157 
0158    //!Constructor. Allocates basic resources. Never throws.
0159    basic_managed_memory_impl()
0160       : mp_header(0){}
0161 
0162    //!Destructor. Calls close. Never throws.
0163    ~basic_managed_memory_impl()
0164    {  this->close_impl(); }
0165 
0166    //!Places segment manager in the reserved space. This can throw.
0167    bool  create_impl   (void *addr, size_type size)
0168    {
0169       if(mp_header)  return false;
0170 
0171       //Check if there is enough space
0172       if(size < segment_manager::get_min_size())
0173          return false;
0174 
0175       //This function should not throw. The index construction can
0176       //throw if constructor allocates memory. So we must catch it.
0177       BOOST_INTERPROCESS_TRY{
0178          //Let's construct the allocator in memory
0179          BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of<segment_manager>::value));
0180          mp_header       = ::new(addr, boost_container_new_t()) segment_manager(size);
0181       }
0182       BOOST_INTERPROCESS_CATCH(...){
0183          return false;
0184       } BOOST_INTERPROCESS_CATCH_END
0185       return true;
0186    }
0187 
0188    //!Connects to a segment manager in the reserved buffer. Never throws.
0189    bool  open_impl     (void *addr, size_type)
0190    {
0191       if(mp_header)  return false;
0192       mp_header = static_cast<segment_manager*>(addr);
0193       return true;
0194    }
0195 
0196    //!Frees resources. Never throws.
0197    bool close_impl()
0198    {
0199       bool ret = mp_header != 0;
0200       mp_header = 0;
0201       return ret;
0202    }
0203 
0204    //!Frees resources and destroys common resources. Never throws.
0205    bool destroy_impl()
0206    {
0207       if(mp_header == 0)
0208          return false;
0209       mp_header->~segment_manager();
0210       this->close_impl();
0211          return true;
0212    }
0213 
0214    //!
0215    void grow(size_type extra_bytes)
0216    {  mp_header->grow(extra_bytes); }
0217 
0218    void shrink_to_fit()
0219    {  mp_header->shrink_to_fit(); }
0220 
0221    public:
0222 
0223    //!Returns segment manager. Never throws.
0224    segment_manager *get_segment_manager() const
0225    {   return mp_header; }
0226 
0227    //!Returns the base address of the memory in this process. Never throws.
0228    void *   get_address   () const
0229    {   return reinterpret_cast<char*>(mp_header) - Offset; }
0230 
0231    //!Returns the size of memory segment. Never throws.
0232    size_type   get_size   () const
0233    {   return mp_header->get_size() + Offset;  }
0234 
0235    //!Returns the number of free bytes of the memory
0236    //!segment
0237    size_type get_free_memory() const
0238    {  return mp_header->get_free_memory();  }
0239 
0240    //!Returns the result of "all_memory_deallocated()" function
0241    //!of the used memory algorithm
0242    bool all_memory_deallocated()
0243    {   return mp_header->all_memory_deallocated(); }
0244 
0245    //!Returns the result of "check_sanity()" function
0246    //!of the used memory algorithm
0247    bool check_sanity()
0248    {   return mp_header->check_sanity(); }
0249 
0250    //!Writes to zero free memory (memory not yet allocated) of
0251    //!the memory algorithm
0252    void zero_free_memory()
0253    {   mp_header->zero_free_memory(); }
0254 
0255    //!Transforms an absolute address into an offset from base address.
0256    //!The address must belong to the memory segment. Never throws.
0257    handle_t get_handle_from_address   (const void *ptr) const
0258    {
0259       return (handle_t)(reinterpret_cast<const char*>(ptr) -
0260              reinterpret_cast<const char*>(this->get_address()));
0261    }
0262 
0263    //!Returns true if the address belongs to the managed memory segment
0264    bool belongs_to_segment (const void *ptr) const
0265    {
0266       return ptr >= this->get_address() &&
0267              ptr <  (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
0268    }
0269 
0270    //!Transforms previously obtained offset into an absolute address in the
0271    //!process space of the current process. Never throws.*/
0272    void *    get_address_from_handle (handle_t offset) const
0273    {  return reinterpret_cast<char*>(this->get_address()) + offset; }
0274 
0275    //!Searches for nbytes of free memory in the segment, marks the
0276    //!memory as used and return the pointer to the memory. If no
0277    //!memory is available throws a boost::interprocess::bad_alloc exception
0278    void* allocate             (size_type nbytes)
0279    {   return mp_header->allocate(nbytes);   }
0280 
0281    //!Searches for nbytes of free memory in the segment, marks the
0282    //!memory as used and return the pointer to the memory. If no memory
0283    //!is available returns 0. Never throws.
0284    void* allocate             (size_type nbytes, const std::nothrow_t &tag)
0285    {   return mp_header->allocate(nbytes, tag);  }
0286 
0287    //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
0288    //!must be power of two. If no memory
0289    //!is available returns 0. Never throws.
0290    void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag)
0291    {   return mp_header->allocate_aligned(nbytes, alignment, tag);  }
0292 
0293    template<class T>
0294    T * allocation_command  (boost::interprocess::allocation_type command,   size_type limit_size,
0295                            size_type &prefer_in_recvd_out_size, T *&reuse)
0296    {  return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);  }
0297 
0298    //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
0299    //!must be power of two. If no
0300    //!memory is available throws a boost::interprocess::bad_alloc exception
0301    void * allocate_aligned(size_type nbytes, size_type alignment)
0302    {   return mp_header->allocate_aligned(nbytes, alignment);  }
0303 
0304    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0305 
0306    //Experimental. Don't use.
0307 
0308    //!Allocates n_elements of elem_bytes bytes.
0309    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0310    void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0311    {  mp_header->allocate_many(elem_bytes, n_elements, chain); }
0312 
0313    //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
0314    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0315    void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0316    {  mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
0317 
0318    //!Allocates n_elements of elem_bytes bytes.
0319    //!Non-throwing version. chain.size() is not increased on failure.
0320    void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0321    {  mp_header->allocate_many(tag, elem_bytes, n_elements, chain); }
0322 
0323    //!Allocates n_elements, each one of
0324    //!element_lengths[i]*sizeof_element bytes.
0325    //!Non-throwing version. chain.size() is not increased on failure.
0326    void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0327    {  mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); }
0328 
0329    //!Deallocates all elements contained in chain.
0330    //!Never throws.
0331    void deallocate_many(multiallocation_chain &chain)
0332    {  mp_header->deallocate_many(chain); }
0333 
0334    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0335 
0336    //!Marks previously allocated memory as free. Never throws.
0337    void  deallocate           (void *addr)
0338    {   if (mp_header) mp_header->deallocate(addr);  }
0339 
0340    //!Tries to find a previous named allocation address. Returns a memory
0341    //!buffer and the object count. If not found returned pointer is 0.
0342    //!Never throws.
0343    template <class T>
0344    std::pair<T*, size_type> find  (char_ptr_holder_t name)
0345    {   return mp_header->template find<T>(name); }
0346 
0347    //!Creates a named object or array in memory
0348    //!
0349    //!Allocates and constructs a T object or an array of T in memory,
0350    //!associates this with the given name and returns a pointer to the
0351    //!created object. If an array is being constructed all objects are
0352    //!created using the same parameters given to this function.
0353    //!
0354    //!-> If the name was previously used, returns 0.
0355    //!
0356    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
0357    //!
0358    //!-> If T's constructor throws, the function throws that exception.
0359    //!
0360    //!Memory is freed automatically if T's constructor throws and if an
0361    //!array was being constructed, destructors of created objects are called
0362    //!before freeing the memory.
0363    template <class T>
0364    typename segment_manager::template construct_proxy<T>::type
0365       construct(char_ptr_holder_t name)
0366    {   return mp_header->template construct<T>(name);  }
0367 
0368    //!Finds or creates a named object or array in memory
0369    //!
0370    //!Tries to find an object with the given name in memory. If
0371    //!found, returns the pointer to this pointer. If the object is not found,
0372    //!allocates and constructs a T object or an array of T in memory,
0373    //!associates this with the given name and returns a pointer to the
0374    //!created object. If an array is being constructed all objects are
0375    //!created using the same parameters given to this function.
0376    //!
0377    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
0378    //!
0379    //!-> If T's constructor throws, the function throws that exception.
0380    //!
0381    //!Memory is freed automatically if T's constructor throws and if an
0382    //!array was being constructed, destructors of created objects are called
0383    //!before freeing the memory.
0384    template <class T>
0385    typename segment_manager::template construct_proxy<T>::type
0386       find_or_construct(char_ptr_holder_t name)
0387    {   return mp_header->template find_or_construct<T>(name);  }
0388 
0389    //!Creates a named object or array in memory
0390    //!
0391    //!Allocates and constructs a T object or an array of T in memory,
0392    //!associates this with the given name and returns a pointer to the
0393    //!created object. If an array is being constructed all objects are
0394    //!created using the same parameters given to this function.
0395    //!
0396    //!-> If the name was previously used, returns 0.
0397    //!
0398    //!-> Returns 0 if there is no available memory
0399    //!
0400    //!-> If T's constructor throws, the function throws that exception.
0401    //!
0402    //!Memory is freed automatically if T's constructor throws and if an
0403    //!array was being constructed, destructors of created objects are called
0404    //!before freeing the memory.
0405    template <class T>
0406    typename segment_manager::template construct_proxy<T>::type
0407       construct(char_ptr_holder_t name, const std::nothrow_t &tag)
0408    {   return mp_header->template construct<T>(name, tag);  }
0409 
0410    //!Finds or creates a named object or array in memory
0411    //!
0412    //!Tries to find an object with the given name in memory. If
0413    //!found, returns the pointer to this pointer. If the object is not found,
0414    //!allocates and constructs a T object or an array of T in memory,
0415    //!associates this with the given name and returns a pointer to the
0416    //!created object. If an array is being constructed all objects are
0417    //!created using the same parameters given to this function.
0418    //!
0419    //!-> Returns 0 if there is no available memory
0420    //!
0421    //!-> If T's constructor throws, the function throws that exception.
0422    //!
0423    //!Memory is freed automatically if T's constructor throws and if an
0424    //!array was being constructed, destructors of created objects are called
0425    //!before freeing the memory.
0426    template <class T>
0427    typename segment_manager::template construct_proxy<T>::type
0428       find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag)
0429    {   return mp_header->template find_or_construct<T>(name, tag);  }
0430 
0431    //!Creates a named array from iterators in memory
0432    //!
0433    //!Allocates and constructs an array of T in memory,
0434    //!associates this with the given name and returns a pointer to the
0435    //!created object. Each element in the array is created using the
0436    //!objects returned when dereferencing iterators as parameters
0437    //!and incrementing all iterators for each element.
0438    //!
0439    //!-> If the name was previously used, returns 0.
0440    //!
0441    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
0442    //!
0443    //!-> If T's constructor throws, the function throws that exception.
0444    //!
0445    //!Memory is freed automatically if T's constructor throws and
0446    //!destructors of created objects are called before freeing the memory.
0447    template <class T>
0448    typename segment_manager::template construct_iter_proxy<T>::type
0449       construct_it(char_ptr_holder_t name)
0450    {   return mp_header->template construct_it<T>(name);  }
0451 
0452    //!Finds or creates a named array from iterators in memory
0453    //!
0454    //!Tries to find an object with the given name in memory. If
0455    //!found, returns the pointer to this pointer. If the object is not found,
0456    //!allocates and constructs an array of T in memory,
0457    //!associates this with the given name and returns a pointer to the
0458    //!created object. Each element in the array is created using the
0459    //!objects returned when dereferencing iterators as parameters
0460    //!and incrementing all iterators for each element.
0461    //!
0462    //!-> If the name was previously used, returns 0.
0463    //!
0464    //!-> Throws boost::interprocess::bad_alloc if there is no available memory
0465    //!
0466    //!-> If T's constructor throws, the function throws that exception.
0467    //!
0468    //!Memory is freed automatically if T's constructor throws and
0469    //!destructors of created objects are called before freeing the memory.
0470    template <class T>
0471    typename segment_manager::template construct_iter_proxy<T>::type
0472       find_or_construct_it(char_ptr_holder_t name)
0473    {   return mp_header->template find_or_construct_it<T>(name);  }
0474 
0475    //!Creates a named array from iterators in memory
0476    //!
0477    //!Allocates and constructs an array of T in memory,
0478    //!associates this with the given name and returns a pointer to the
0479    //!created object. Each element in the array is created using the
0480    //!objects returned when dereferencing iterators as parameters
0481    //!and incrementing all iterators for each element.
0482    //!
0483    //!-> If the name was previously used, returns 0.
0484    //!
0485    //!-> If there is no available memory, returns 0.
0486    //!
0487    //!-> If T's constructor throws, the function throws that exception.
0488    //!
0489    //!Memory is freed automatically if T's constructor throws and
0490    //!destructors of created objects are called before freeing the memory.*/
0491    template <class T>
0492    typename segment_manager::template construct_iter_proxy<T>::type
0493       construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
0494    {   return mp_header->template construct_it<T>(name, tag);  }
0495 
0496    //!Finds or creates a named array from iterators in memory
0497    //!
0498    //!Tries to find an object with the given name in memory. If
0499    //!found, returns the pointer to this pointer. If the object is not found,
0500    //!allocates and constructs an array of T in memory,
0501    //!associates this with the given name and returns a pointer to the
0502    //!created object. Each element in the array is created using the
0503    //!objects returned when dereferencing iterators as parameters
0504    //!and incrementing all iterators for each element.
0505    //!
0506    //!-> If the name was previously used, returns 0.
0507    //!
0508    //!-> If there is no available memory, returns 0.
0509    //!
0510    //!-> If T's constructor throws, the function throws that exception.
0511    //!
0512    //!Memory is freed automatically if T's constructor throws and
0513    //!destructors of created objects are called before freeing the memory.*/
0514    template <class T>
0515    typename segment_manager::template construct_iter_proxy<T>::type
0516       find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
0517    {   return mp_header->template find_or_construct_it<T>(name, tag);  }
0518 
0519    //!Calls a functor and guarantees that no new construction, search or
0520    //!destruction will be executed by any process while executing the object
0521    //!function call. If the functor throws, this function throws.
0522    template <class Func>
0523    void atomic_func(Func &f)
0524    {   mp_header->atomic_func(f);  }
0525 
0526    //!Tries to call a functor guaranteeing that no new construction, search or
0527    //!destruction will be executed by any process while executing the object
0528    //!function call. If the atomic function can't be immediatelly executed
0529    //!because the internal mutex is already locked, returns false.
0530    //!If the functor throws, this function throws.
0531    template <class Func>
0532    bool try_atomic_func(Func &f)
0533    {   return mp_header->try_atomic_func(f); }
0534 
0535    //!Destroys a named memory object or array.
0536    //!
0537    //!Finds the object with the given name, calls its destructors,
0538    //!frees used memory and returns true.
0539    //!
0540    //!-> If the object is not found, it returns false.
0541    //!
0542    //!Exception Handling:
0543    //!
0544    //!When deleting a dynamically object or array, the Standard
0545    //!does not guarantee that dynamically allocated memory, will be released.
0546    //!Also, when deleting arrays, the Standard doesn't require calling
0547    //!destructors for the rest of the objects if for one of them the destructor
0548    //!terminated with an exception.
0549    //!
0550    //!Destroying an object:
0551    //!
0552    //!If the destructor throws, the memory will be freed and that exception
0553    //!will be thrown.
0554    //!
0555    //!Destroying an array:
0556    //!
0557    //!When destroying an array, if a destructor throws, the rest of
0558    //!destructors are called. If any of these throws, the exceptions are
0559    //!ignored. The name association will be erased, memory will be freed and
0560    //!the first exception will be thrown. This guarantees the unlocking of
0561    //!mutexes and other resources.
0562    //!
0563    //!For all theses reasons, classes with throwing destructors are not
0564    //!recommended.
0565    template <class T>
0566    bool destroy(const CharType *name)
0567    {   return mp_header->template destroy<T>(name); }
0568 
0569    //!Destroys the unique instance of type T
0570    //!
0571    //!Calls the destructor, frees used memory and returns true.
0572    //!
0573    //!Exception Handling:
0574    //!
0575    //!When deleting a dynamically object, the Standard does not
0576    //!guarantee that dynamically allocated memory will be released.
0577    //!
0578    //!Destroying an object:
0579    //!
0580    //!If the destructor throws, the memory will be freed and that exception
0581    //!will be thrown.
0582    //!
0583    //!For all theses reasons, classes with throwing destructors are not
0584    //!recommended for  memory.
0585    template <class T>
0586    bool destroy(const unique_instance_t *const )
0587    {   return mp_header->template destroy<T>(unique_instance);  }
0588 
0589    //!Destroys the object (named, unique, or anonymous)
0590    //!
0591    //!Calls the destructor, frees used memory and returns true.
0592    //!
0593    //!Exception Handling:
0594    //!
0595    //!When deleting a dynamically object, the Standard does not
0596    //!guarantee that dynamically allocated memory will be released.
0597    //!
0598    //!Destroying an object:
0599    //!
0600    //!If the destructor throws, the memory will be freed and that exception
0601    //!will be thrown.
0602    //!
0603    //!For all theses reasons, classes with throwing destructors are not
0604    //!recommended for  memory.
0605    template <class T>
0606    void destroy_ptr(const T *ptr)
0607    {  mp_header->template destroy_ptr<T>(ptr); }
0608 
0609    //!Returns the name of an object created with construct/find_or_construct
0610    //!functions. If ptr points to an unique instance typeid(T).name() is returned.
0611    template<class T>
0612    static const char_type *get_instance_name(const T *ptr)
0613    {  return segment_manager::get_instance_name(ptr);   }
0614 
0615    //!Returns is the type an object created with construct/find_or_construct
0616    //!functions. Does not throw.
0617    template<class T>
0618    static instance_type get_instance_type(const T *ptr)
0619    {  return segment_manager::get_instance_type(ptr); }
0620 
0621    //!Returns the length of an object created with construct/find_or_construct
0622    //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
0623    template<class T>
0624    static size_type get_instance_length(const T *ptr)
0625    {  return segment_manager::get_instance_length(ptr); }
0626 
0627    //!Preallocates needed index resources to optimize the
0628    //!creation of "num" named objects in the  memory segment.
0629    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0630    void reserve_named_objects(size_type num)
0631    {  mp_header->reserve_named_objects(num);  }
0632 
0633    //!Preallocates needed index resources to optimize the
0634    //!creation of "num" unique objects in the  memory segment.
0635    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0636    void reserve_unique_objects(size_type num)
0637    {  mp_header->reserve_unique_objects(num);  }
0638 
0639    //!Calls shrink_to_fit in both named and unique object indexes
0640    //to try to free unused memory from those indexes.
0641    void shrink_to_fit_indexes()
0642    {  mp_header->shrink_to_fit_indexes();  }
0643 
0644    //!Returns the number of named objects stored
0645    //!in the managed segment.
0646    size_type get_num_named_objects()
0647    {  return mp_header->get_num_named_objects();  }
0648 
0649    //!Returns the number of unique objects stored
0650    //!in the managed segment.
0651    size_type get_num_unique_objects()
0652    {  return mp_header->get_num_unique_objects();  }
0653 
0654    //!Returns a constant iterator to the index storing the
0655    //!named allocations. NOT thread-safe. Never throws.
0656    const_named_iterator named_begin() const
0657    {  return mp_header->named_begin(); }
0658 
0659    //!Returns a constant iterator to the end of the index
0660    //!storing the named allocations. NOT thread-safe. Never throws.
0661    const_named_iterator named_end() const
0662    {  return mp_header->named_end(); }
0663 
0664    //!Returns a constant iterator to the index storing the
0665    //!unique allocations. NOT thread-safe. Never throws.
0666    const_unique_iterator unique_begin() const
0667    {  return mp_header->unique_begin(); }
0668 
0669    //!Returns a constant iterator to the end of the index
0670    //!storing the unique allocations. NOT thread-safe. Never throws.
0671    const_unique_iterator unique_end() const
0672    {  return mp_header->unique_end(); }
0673 
0674    //!This is the default allocator to allocate types T
0675    //!from this managed segment
0676    template<class T>
0677    struct allocator
0678    {
0679       typedef typename segment_manager::template allocator<T>::type type;
0680    };
0681 
0682    //!Returns an instance of the default allocator for type T
0683    //!initialized that allocates memory from this segment manager.
0684    template<class T>
0685    typename allocator<T>::type
0686       get_allocator()
0687    {   return mp_header->template get_allocator<T>(); }
0688 
0689    //!This is the default deleter to delete types T
0690    //!from this managed segment.
0691    template<class T>
0692    struct deleter
0693    {
0694       typedef typename segment_manager::template deleter<T>::type type;
0695    };
0696 
0697    //!Returns an instance of the default allocator for type T
0698    //!initialized that allocates memory from this segment manager.
0699    template<class T>
0700    typename deleter<T>::type
0701       get_deleter()
0702    {   return mp_header->template get_deleter<T>(); }
0703 
0704    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0705    //!Tries to find a previous named allocation address. Returns a memory
0706    //!buffer and the object count. If not found returned pointer is 0.
0707    //!Never throws.
0708    template <class T>
0709    std::pair<T*, size_type> find_no_lock  (char_ptr_holder_t name)
0710    {   return mp_header->template find_no_lock<T>(name); }
0711    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0712 
0713    protected:
0714    //!Swaps the segment manager's managed by this managed memory segment.
0715    //!NOT thread-safe. Never throws.
0716    void swap(basic_managed_memory_impl &other)
0717    {  (simple_swap)(mp_header, other.mp_header); }
0718 
0719    private:
0720    segment_manager *mp_header;
0721 };
0722 
0723 template<class BasicManagedMemoryImpl>
0724 class create_open_func
0725 {
0726    typedef typename BasicManagedMemoryImpl::size_type size_type;
0727 
0728    public:
0729 
0730    create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
0731       : m_frontend(frontend), m_type(type){}
0732 
0733    bool operator()(void *addr, std::size_t size, bool created) const
0734    {
0735       if( ((m_type == DoOpen)   &&  created) ||
0736           ((m_type == DoCreate) && !created) ||
0737           //Check for overflow
0738           size_type(-1) < size ){
0739          return false;
0740       }
0741       else if(created){
0742          return m_frontend->create_impl(addr, static_cast<size_type>(size));
0743       }
0744       else{
0745          return m_frontend->open_impl  (addr, static_cast<size_type>(size));
0746       }
0747    }
0748 
0749    static std::size_t get_min_size()
0750    {
0751       const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size();
0752       if(sz > std::size_t(-1)){
0753          //The minimum size is not representable by std::size_t
0754          BOOST_ASSERT(false);
0755          return std::size_t(-1);
0756       }
0757       else{
0758          return static_cast<std::size_t>(sz);
0759       }
0760    }
0761 
0762    private:
0763    BasicManagedMemoryImpl *m_frontend;
0764    create_enum_t           m_type;
0765 };
0766 
0767 }  //namespace ipcdetail {
0768 }  //namespace interprocess {
0769 }  //namespace boost {
0770 
0771 #include <boost/interprocess/detail/config_end.hpp>
0772 
0773 #endif   //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
0774