Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:26

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