Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-30 08:20:55

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_SEGMENT_MANAGER_HPP
0012 #define BOOST_INTERPROCESS_SEGMENT_MANAGER_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/detail/type_traits.hpp>
0026 
0027 #include <boost/interprocess/detail/transform_iterator.hpp>
0028 
0029 #include <boost/interprocess/detail/mpl.hpp>
0030 #include <boost/interprocess/detail/nothrow.hpp>
0031 #include <boost/interprocess/detail/segment_manager_helper.hpp>
0032 #include <boost/interprocess/detail/named_proxy.hpp>
0033 #include <boost/interprocess/detail/utilities.hpp>
0034 #include <boost/interprocess/offset_ptr.hpp>
0035 #include <boost/interprocess/indexes/iset_index.hpp>
0036 #include <boost/interprocess/exceptions.hpp>
0037 #include <boost/interprocess/allocators/allocator.hpp>
0038 #include <boost/interprocess/smart_ptr/deleter.hpp>
0039 #include <boost/move/utility_core.hpp>
0040 #include <boost/interprocess/sync/scoped_lock.hpp>
0041 // container/detail
0042 #include <boost/container/detail/minimal_char_traits_header.hpp>
0043 #include <boost/container/detail/placement_new.hpp>
0044 // std
0045 #include <cstddef>   //std::size_t
0046 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0047 #include <boost/assert.hpp>
0048 #ifndef BOOST_NO_EXCEPTIONS
0049 #include <exception>
0050 #endif
0051 #include <typeinfo>
0052 
0053 //!\file
0054 //!Describes the object placed in a memory segment that provides
0055 //!named object allocation capabilities for single-segment and
0056 //!multi-segment allocations.
0057 
0058 namespace boost{
0059 namespace interprocess{
0060 
0061 //!This object is the public base class of segment manager.
0062 //!This class only depends on the memory allocation algorithm
0063 //!and implements all the allocation features not related
0064 //!to named or unique objects.
0065 //!
0066 //!Storing a reference to segment_manager forces
0067 //!the holder class to be dependent on index types and character types.
0068 //!When such dependence is not desirable and only anonymous and raw
0069 //!allocations are needed, segment_manager_base is the correct answer.
0070 template<class MemoryAlgorithm>
0071 class segment_manager_base
0072    :  private MemoryAlgorithm
0073 {
0074    public:
0075    typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
0076    typedef typename MemoryAlgorithm::void_pointer  void_pointer;
0077    typedef typename MemoryAlgorithm::mutex_family  mutex_family;
0078    static const std::size_t MemAlignment = MemoryAlgorithm::Alignment;
0079    typedef MemoryAlgorithm memory_algorithm;
0080 
0081    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0082 
0083    //Experimental. Don't use
0084    typedef typename MemoryAlgorithm::multiallocation_chain    multiallocation_chain;
0085    typedef typename MemoryAlgorithm::difference_type  difference_type;
0086    typedef typename MemoryAlgorithm::size_type        size_type;
0087 
0088    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0089 
0090    //!This constant indicates the payload size
0091    //!associated with each allocation of the memory algorithm
0092    static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
0093 
0094    //!Constructor of the segment_manager_base
0095    //!
0096    //!"size" is the size of the memory segment where
0097    //!the basic segment manager is being constructed.
0098    //!
0099    //!"reserved_bytes" is the number of bytes
0100    //!after the end of the memory algorithm object itself
0101    //!that the memory algorithm will exclude from
0102    //!dynamic allocation
0103    //!
0104    //!Can throw
0105    segment_manager_base(size_type sz, size_type reserved_bytes)
0106       :  MemoryAlgorithm(sz, reserved_bytes)
0107    {
0108       BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
0109    }
0110 
0111    //!Returns the size of the memory
0112    //!segment
0113    size_type get_size() const
0114    {  return MemoryAlgorithm::get_size();  }
0115 
0116    //!Returns the number of free bytes of the memory
0117    //!segment
0118    size_type get_free_memory() const
0119    {  return MemoryAlgorithm::get_free_memory();  }
0120 
0121    //!Obtains the minimum size needed by
0122    //!the segment manager
0123    static size_type get_min_size (size_type size)
0124    {  return MemoryAlgorithm::get_min_size(size);  }
0125 
0126    //!Allocates nbytes bytes. This function is only used in
0127    //!single-segment management. Never throws
0128    void * allocate (size_type nbytes, const std::nothrow_t &)
0129    {  return MemoryAlgorithm::allocate(nbytes);   }
0130 
0131    //!Returns a reference to the internal memory algorithm.
0132    //!This function is useful for custom memory algorithms that
0133    //!need additional configuration options after construction. Never throws.
0134    //!This function should be only used by advanced users.
0135    MemoryAlgorithm &get_memory_algorithm()
0136    {  return static_cast<MemoryAlgorithm&>(*this);   }
0137 
0138    //!Returns a const reference to the internal memory algorithm.
0139    //!This function is useful for custom memory algorithms that
0140    //!need additional configuration options after construction. Never throws.
0141    //!This function should be only used by advanced users.
0142    const MemoryAlgorithm &get_memory_algorithm() const
0143    {  return static_cast<const MemoryAlgorithm&>(*this);   }
0144 
0145    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0146 
0147    //Experimental. Dont' use.
0148    //!Allocates n_elements of elem_bytes bytes.
0149    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0150    void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0151    {
0152       size_type prev_size = chain.size();
0153       MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
0154       if(!elem_bytes || chain.size() == prev_size){
0155          throw bad_alloc();
0156       }
0157    }
0158 
0159    //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
0160    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0161    void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0162    {
0163       size_type prev_size = chain.size();
0164       MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
0165       if(!sizeof_element || chain.size() == prev_size){
0166          throw bad_alloc();
0167       }
0168    }
0169 
0170    //!Allocates n_elements of elem_bytes bytes.
0171    //!Non-throwing version. chain.size() is not increased on failure.
0172    void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0173    {  MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
0174 
0175    //!Allocates n_elements, each one of
0176    //!element_lengths[i]*sizeof_element bytes.
0177    //!Non-throwing version. chain.size() is not increased on failure.
0178    void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0179    {  MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
0180 
0181    //!Deallocates all elements contained in chain.
0182    //!Never throws.
0183    void deallocate_many(multiallocation_chain &chain)
0184    {  MemoryAlgorithm::deallocate_many(chain); }
0185 
0186    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0187 
0188    //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
0189    //!on failure
0190    void * allocate(size_type nbytes)
0191    {
0192       void * ret = MemoryAlgorithm::allocate(nbytes);
0193       if(!ret)
0194          throw bad_alloc();
0195       return ret;
0196    }
0197 
0198    //!Allocates nbytes bytes. This function is only used in
0199    //!single-segment management. Never throws
0200    void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &)
0201    {  return MemoryAlgorithm::allocate_aligned(nbytes, alignment);   }
0202 
0203    //!Allocates nbytes bytes. This function is only used in
0204    //!single-segment management. Throws bad_alloc when fails
0205    void * allocate_aligned(size_type nbytes, size_type alignment)
0206    {
0207       void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
0208       if(!ret)
0209          throw bad_alloc();
0210       return ret;
0211    }
0212 
0213    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0214 
0215    template<class T>
0216    T *allocation_command  (boost::interprocess::allocation_type command, size_type limit_size,
0217                            size_type &prefer_in_recvd_out_size, T *&reuse)
0218    {
0219       T *ret = MemoryAlgorithm::allocation_command
0220          (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse);
0221       if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0222          throw bad_alloc();
0223       return ret;
0224    }
0225 
0226    void *raw_allocation_command  (boost::interprocess::allocation_type command,   size_type limit_objects,
0227                            size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1)
0228    {
0229       void *ret = MemoryAlgorithm::raw_allocation_command
0230          ( command | boost::interprocess::nothrow_allocation, limit_objects,
0231            prefer_in_recvd_out_size, reuse, sizeof_object);
0232       if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0233          throw bad_alloc();
0234       return ret;
0235    }
0236 
0237    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0238 
0239    //!Deallocates the bytes allocated with allocate/allocate_many()
0240    //!pointed by addr
0241    void   deallocate          (void *addr)
0242    {  MemoryAlgorithm::deallocate(addr);   }
0243 
0244    //!Increases managed memory in extra_size bytes more. This only works
0245    //!with single-segment management.
0246    void grow(size_type extra_size)
0247    {
0248       //Growing managed segments that use raw pointers is UB, so disallow it.
0249       BOOST_INTERPROCESS_STATIC_ASSERT(!(ipcdetail::is_same<void*, void_pointer>::value));
0250       MemoryAlgorithm::grow(extra_size);
0251    }
0252 
0253    //!Decreases managed memory to the minimum. This only works
0254    //!with single-segment management.
0255    void shrink_to_fit()
0256    {  MemoryAlgorithm::shrink_to_fit();   }
0257 
0258    //!Returns the result of "all_memory_deallocated()" function
0259    //!of the used memory algorithm
0260    bool all_memory_deallocated()
0261    {   return MemoryAlgorithm::all_memory_deallocated(); }
0262 
0263    //!Returns the result of "check_sanity()" function
0264    //!of the used memory algorithm
0265    bool check_sanity()
0266    {   return MemoryAlgorithm::check_sanity(); }
0267 
0268    //!Writes to zero free memory (memory not yet allocated)
0269    //!of the memory algorithm
0270    void zero_free_memory()
0271    {   MemoryAlgorithm::zero_free_memory(); }
0272 
0273    //!Returns the size of the buffer previously allocated pointed by ptr
0274    size_type size(const void *ptr) const
0275    {   return MemoryAlgorithm::size(ptr); }
0276 };
0277 
0278 //!This object is placed in the beginning of memory segment and
0279 //!implements the allocation (named or anonymous) of portions
0280 //!of the segment. This object contains two indexes that
0281 //!maintain an association between a name and a portion of the segment.
0282 //!
0283 //!The first index contains the mappings for normal named objects using the
0284 //!char type specified in the template parameter.
0285 //!
0286 //!The second index contains the association for unique instances. The key will
0287 //!be the const char * returned from type_info.name() function for the unique
0288 //!type to be constructed.
0289 //!
0290 //!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
0291 //!from segment_manager_base<MemoryAlgorithm> and inherits from it
0292 //!many public functions related to anonymous object and raw memory allocation.
0293 //!See segment_manager_base reference to know about those functions.
0294 template<class CharType
0295         ,class MemoryAlgorithm
0296         ,template<class IndexConfig> class IndexType>
0297 class segment_manager
0298    :  public segment_manager_base<MemoryAlgorithm>
0299 {
0300    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0301    //Non-copyable
0302    segment_manager();
0303    segment_manager(const segment_manager &);
0304    segment_manager &operator=(const segment_manager &);
0305    typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
0306    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0307 
0308    public:
0309    typedef MemoryAlgorithm                                  memory_algorithm;
0310    typedef typename segment_manager_base_t::void_pointer    void_pointer;
0311    typedef typename segment_manager_base_t::size_type       size_type;
0312    typedef typename segment_manager_base_t::difference_type difference_type;
0313    typedef CharType                                         char_type;
0314 
0315    typedef segment_manager_base<MemoryAlgorithm>   segment_manager_base_type;
0316 
0317    static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
0318    static const size_type MemAlignment         = segment_manager_base_t::MemAlignment;
0319 
0320    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0321    private:
0322    typedef ipcdetail::block_header<size_type> block_header_t;
0323    typedef ipcdetail::index_config<CharType, MemoryAlgorithm>  index_config_named;
0324    typedef ipcdetail::index_config<char, MemoryAlgorithm>      index_config_unique;
0325    typedef IndexType<index_config_named>                    index_type;
0326    typedef ipcdetail::bool_<is_intrusive_index<index_type>::value >    is_intrusive_t;
0327    typedef ipcdetail::bool_<is_node_index<index_type>::value>          is_node_index_t;
0328 
0329    public:
0330    typedef IndexType<index_config_named>                    named_index_t;
0331    typedef IndexType<index_config_unique>                   unique_index_t;
0332    typedef ipcdetail::char_ptr_holder<CharType>                char_ptr_holder_t;
0333    typedef ipcdetail::segment_manager_iterator_transform
0334       <typename named_index_t::const_iterator
0335       ,is_intrusive_index<index_type>::value>   named_transform;
0336 
0337    typedef ipcdetail::segment_manager_iterator_transform
0338       <typename unique_index_t::const_iterator
0339       ,is_intrusive_index<index_type>::value>   unique_transform;
0340    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0341 
0342    typedef typename segment_manager_base_t::mutex_family       mutex_family;
0343 
0344    typedef transform_iterator
0345       <typename named_index_t::const_iterator, named_transform> const_named_iterator;
0346    typedef transform_iterator
0347       <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
0348 
0349    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0350 
0351    //!Constructor proxy object definition helper class
0352    template<class T>
0353    struct construct_proxy
0354    {
0355       typedef ipcdetail::named_proxy<segment_manager, T, false>   type;
0356    };
0357 
0358    //!Constructor proxy object definition helper class
0359    template<class T>
0360    struct construct_iter_proxy
0361    {
0362       typedef ipcdetail::named_proxy<segment_manager, T, true>   type;
0363    };
0364 
0365    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0366 
0367    //!Constructor of the segment manager
0368    //!"size" is the size of the memory segment where
0369    //!the segment manager is being constructed.
0370    //!Can throw
0371    explicit segment_manager(size_type segment_size)
0372       :  segment_manager_base_t(segment_size, priv_get_reserved_bytes())
0373       ,  m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
0374    {
0375       (void) anonymous_instance;   (void) unique_instance;
0376       //Check EBO is applied, it's required
0377       const void * const this_addr = this;
0378       const void *const segm_addr  = static_cast<segment_manager_base_t*>(this);
0379       (void)this_addr;  (void)segm_addr;
0380       BOOST_ASSERT( this_addr == segm_addr);
0381       const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
0382       BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
0383    }
0384 
0385    //!Tries to find a previous named/unique allocation. Returns the address
0386    //!and the object count. On failure the first member of the
0387    //!returned pair is 0.
0388    template <class T>
0389    std::pair<T*, size_type> find  (char_ptr_holder_t name)
0390    {  return this->priv_find_impl<T>(name, true);  }
0391 
0392    //!Tries to find a previous named/unique allocation. Returns the address
0393    //!and the object count. On failure the first member of the
0394    //!returned pair is 0. This search is not mutex-protected!
0395    //!Use it only inside atomic_func() calls, where the internal mutex
0396    //!is guaranteed to be locked.
0397    template <class T>
0398    std::pair<T*, size_type> find_no_lock  (char_ptr_holder_t name)
0399    {  return this->priv_find_impl<T>(name, false);  }
0400 
0401    //!Returns throwing "construct" proxy
0402    //!object
0403    template <class T>
0404    typename construct_proxy<T>::type
0405       construct(char_ptr_holder_t name)
0406    {  return typename construct_proxy<T>::type (this, name, false, true);  }
0407 
0408    //!Returns throwing "search or construct" proxy
0409    //!object
0410    template <class T>
0411    typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
0412    {  return typename construct_proxy<T>::type (this, name, true, true);  }
0413 
0414    //!Returns no throwing "construct" proxy
0415    //!object
0416    template <class T>
0417    typename construct_proxy<T>::type
0418       construct(char_ptr_holder_t name, const std::nothrow_t &)
0419    {  return typename construct_proxy<T>::type (this, name, false, false);  }
0420 
0421    //!Returns no throwing "search or construct"
0422    //!proxy object
0423    template <class T>
0424    typename construct_proxy<T>::type
0425       find_or_construct(char_ptr_holder_t name, const std::nothrow_t &)
0426    {  return typename construct_proxy<T>::type (this, name, true, false);  }
0427 
0428    //!Returns throwing "construct from iterators" proxy object
0429    template <class T>
0430    typename construct_iter_proxy<T>::type
0431       construct_it(char_ptr_holder_t name)
0432    {  return typename construct_iter_proxy<T>::type (this, name, false, true);  }
0433 
0434    //!Returns throwing "search or construct from iterators"
0435    //!proxy object
0436    template <class T>
0437    typename construct_iter_proxy<T>::type
0438       find_or_construct_it(char_ptr_holder_t name)
0439    {  return typename construct_iter_proxy<T>::type (this, name, true, true);  }
0440 
0441    //!Returns no throwing "construct from iterators"
0442    //!proxy object
0443    template <class T>
0444    typename construct_iter_proxy<T>::type
0445       construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0446    {  return typename construct_iter_proxy<T>::type (this, name, false, false);  }
0447 
0448    //!Returns no throwing "search or construct from iterators"
0449    //!proxy object
0450    template <class T>
0451    typename construct_iter_proxy<T>::type
0452       find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0453    {  return typename construct_iter_proxy<T>::type (this, name, true, false);  }
0454 
0455    //!Calls object function blocking recursive interprocess_mutex and guarantees that
0456    //!no new named_alloc or destroy will be executed by any process while
0457    //!executing the object function call
0458    template <class Func>
0459    void atomic_func(Func &f)
0460    {  scoped_lock<rmutex> guard(m_header);  f();  }
0461 
0462    //!Tries to calls a functor guaranteeing that no new construction, search or
0463    //!destruction will be executed by any process while executing the object
0464    //!function call. If the atomic function can't be immediatelly executed
0465    //!because the internal mutex is already locked, returns false.
0466    //!If the functor throws, this function throws.
0467    template <class Func>
0468    bool try_atomic_func(Func &f)
0469    {
0470       scoped_lock<rmutex> guard(m_header, try_to_lock);
0471       if(guard){
0472          f();
0473          return true;
0474       }
0475       else{
0476          return false;
0477       }
0478    }
0479 
0480    //!Destroys a previously created named/unique instance.
0481    //!Returns false if the object was not present.
0482    template <class T>
0483    bool destroy(char_ptr_holder_t name)
0484    {
0485       BOOST_ASSERT(!name.is_anonymous());
0486 
0487       if(name.is_unique()){
0488          return this->priv_generic_named_destroy<T, char>(typeid(T).name(), m_header.m_unique_index);
0489       }
0490       else{
0491          return this->priv_generic_named_destroy<T, CharType>(name.get(), m_header.m_named_index);
0492       }
0493    }
0494 
0495    //!Destroys an anonymous, unique or named object
0496    //!using its address
0497    template <class T>
0498    void destroy_ptr(const T *p)
0499    {
0500       priv_destroy_ptr(p);
0501    }
0502 
0503    //!Returns the name of an object created with construct/find_or_construct
0504    //!functions. Does not throw
0505    template<class T>
0506    static const CharType *get_instance_name(const T *ptr)
0507    { return priv_get_instance_name(block_header_t::block_header_from_value(ptr));  }
0508 
0509    //!Returns the length of an object created with construct/find_or_construct
0510    //!functions. Does not throw.
0511    template<class T>
0512    static size_type get_instance_length(const T *ptr)
0513    {  return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T));  }
0514 
0515    //!Returns is the the name of an object created with construct/find_or_construct
0516    //!functions. Does not throw
0517    template<class T>
0518    static instance_type get_instance_type(const T *ptr)
0519    {  return priv_get_instance_type(block_header_t::block_header_from_value(ptr));  }
0520 
0521    //!Preallocates needed index resources to optimize the
0522    //!creation of "num" named objects in the managed memory segment.
0523    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0524    void reserve_named_objects(size_type num)
0525    {
0526       //-------------------------------
0527       scoped_lock<rmutex> guard(m_header);
0528       //-------------------------------
0529       m_header.m_named_index.reserve(num);
0530    }
0531 
0532    //!Preallocates needed index resources to optimize the
0533    //!creation of "num" unique objects in the managed memory segment.
0534    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0535    void reserve_unique_objects(size_type num)
0536    {
0537       //-------------------------------
0538       scoped_lock<rmutex> guard(m_header);
0539       //-------------------------------
0540       m_header.m_unique_index.reserve(num);
0541    }
0542 
0543    //!Calls shrink_to_fit in both named and unique object indexes
0544    //!to try to free unused memory from those indexes.
0545    void shrink_to_fit_indexes()
0546    {
0547       //-------------------------------
0548       scoped_lock<rmutex> guard(m_header);
0549       //-------------------------------
0550       m_header.m_named_index.shrink_to_fit();
0551       m_header.m_unique_index.shrink_to_fit();
0552    }
0553 
0554    //!Returns the number of named objects stored in
0555    //!the segment.
0556    size_type get_num_named_objects()
0557    {
0558       //-------------------------------
0559       scoped_lock<rmutex> guard(m_header);
0560       //-------------------------------
0561       return m_header.m_named_index.size();
0562    }
0563 
0564    //!Returns the number of unique objects stored in
0565    //!the segment.
0566    size_type get_num_unique_objects()
0567    {
0568       //-------------------------------
0569       scoped_lock<rmutex> guard(m_header);
0570       //-------------------------------
0571       return m_header.m_unique_index.size();
0572    }
0573 
0574    //!Obtains the minimum size needed by the
0575    //!segment manager
0576    static size_type get_min_size()
0577    {  return segment_manager_base_t::get_min_size(priv_get_reserved_bytes());  }
0578 
0579    //!Returns a constant iterator to the beginning of the information about
0580    //!the named allocations performed in this segment manager
0581    const_named_iterator named_begin() const
0582    {
0583       return (make_transform_iterator)
0584          (m_header.m_named_index.begin(), named_transform());
0585    }
0586 
0587    //!Returns a constant iterator to the end of the information about
0588    //!the named allocations performed in this segment manager
0589    const_named_iterator named_end() const
0590    {
0591       return (make_transform_iterator)
0592          (m_header.m_named_index.end(), named_transform());
0593    }
0594 
0595    //!Returns a constant iterator to the beginning of the information about
0596    //!the unique allocations performed in this segment manager
0597    const_unique_iterator unique_begin() const
0598    {
0599       return (make_transform_iterator)
0600          (m_header.m_unique_index.begin(), unique_transform());
0601    }
0602 
0603    //!Returns a constant iterator to the end of the information about
0604    //!the unique allocations performed in this segment manager
0605    const_unique_iterator unique_end() const
0606    {
0607       return (make_transform_iterator)
0608          (m_header.m_unique_index.end(), unique_transform());
0609    }
0610 
0611    //!This is the default allocator to allocate types T
0612    //!from this managed segment
0613    template<class T>
0614    struct allocator
0615    {
0616       typedef boost::interprocess::allocator<T, segment_manager> type;
0617    };
0618 
0619    //!Returns an instance of the default allocator for type T
0620    //!initialized that allocates memory from this segment manager.
0621    template<class T>
0622    typename allocator<T>::type
0623       get_allocator()
0624    {   return typename allocator<T>::type(this); }
0625 
0626    //!This is the default deleter to delete types T
0627    //!from this managed segment.
0628    template<class T>
0629    struct deleter
0630    {
0631       typedef boost::interprocess::deleter<T, segment_manager> type;
0632    };
0633 
0634    //!Returns an instance of the default deleter for type T
0635    //!that will delete an object constructed in this segment manager.
0636    template<class T>
0637    typename deleter<T>::type
0638       get_deleter()
0639    {   return typename deleter<T>::type(this); }
0640 
0641    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0642 
0643    //!Generic named/anonymous new function. Offers all the possibilities,
0644    //!such as throwing, search before creating, and the constructor is
0645    //!encapsulated in an object function.
0646    template<class Proxy>
0647    typename Proxy::object_type * generic_construct
0648       (Proxy& pr, const CharType *name, size_type num, bool try2find, bool dothrow)
0649    {
0650       typedef typename Proxy::object_type object_type;
0651 
0652       //Security overflow check
0653       if(num > ((size_type)-1)/sizeof(object_type)){
0654          return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
0655       }
0656       if(name == 0){
0657          return this->priv_anonymous_construct(pr, num, dothrow);
0658       }
0659       else if(name == reinterpret_cast<const CharType*>(-1)){
0660          return this->priv_generic_named_construct
0661             (pr, unique_type, typeid(object_type).name(), num, try2find, dothrow, m_header.m_unique_index);
0662       }
0663       else{
0664          return this->priv_generic_named_construct
0665             (pr, named_type, name, num, try2find, dothrow, m_header.m_named_index);
0666       }
0667    }
0668 
0669    private:
0670    //!Tries to find a previous named allocation. Returns the address
0671    //!and the object count. On failure the first member of the
0672    //!returned pair is 0.
0673    template <class T>
0674    std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
0675    {
0676       //The name can't be null, no anonymous object can be found by name
0677       BOOST_ASSERT(name != 0);
0678       size_type sz;
0679       void *ret;
0680 
0681       if(name == reinterpret_cast<const CharType*>(-1)){
0682          ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, sz, lock);
0683       }
0684       else{
0685          ret = priv_generic_find<T>(name, m_header.m_named_index, sz, lock);
0686       }
0687       return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
0688    }
0689 
0690    //!Tries to find a previous unique allocation. Returns the address
0691    //!and the object count. On failure the first member of the
0692    //!returned pair is 0.
0693    template <class T>
0694    std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t*, bool lock)
0695    {
0696       size_type size;
0697       void *ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, size, lock);
0698       return std::pair<T*, size_type>(static_cast<T*>(ret), size);
0699    }
0700 
0701 
0702    template<class Proxy>
0703    typename Proxy::object_type * priv_anonymous_construct(Proxy pr, size_type num, bool dothrow)
0704    {
0705       typedef typename Proxy::object_type object_type;
0706       BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
0707       block_header_t block_info (  size_type(sizeof(object_type)*num)
0708                                  , size_type(t_alignment)
0709                                  , anonymous_type
0710                                  , 1
0711                                  , 0);
0712 
0713       //Check if there is enough memory
0714       const std::size_t total_size = block_info.template total_anonymous_size<t_alignment>();
0715       #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
0716       void *ptr_struct = this->allocate(total_size, nothrow<>::get());
0717       #else
0718       void* ptr_struct = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
0719       #endif
0720       if(!ptr_struct){
0721          return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
0722       }
0723 
0724       //Build scoped ptr to avoid leaks with constructor exception
0725       ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
0726          (ptr_struct, *static_cast<segment_manager_base_type*>(this));
0727 
0728       //Now construct the header
0729       const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0730 
0731       block_header_t * const hdr = ::new((char*)ptr_struct + front_space, boost_container_new_t()) block_header_t(block_info);
0732       BOOST_ASSERT(is_ptr_aligned(hdr));
0733       void *ptr = 0; //avoid gcc warning
0734       ptr = hdr->value();
0735 
0736       //Now call constructors
0737       pr.construct_n(ptr, num);
0738 
0739       //All constructors successful, disable rollback
0740       mem.release();
0741       object_type* const pret = static_cast<object_type*>(ptr);
0742       BOOST_ASSERT(is_ptr_aligned(pret));
0743       return pret;
0744    }
0745 
0746    //!Calls the destructor and makes an anonymous deallocate
0747    template <class T>
0748    void priv_anonymous_destroy(const T *object)
0749    {
0750       BOOST_ASSERT(is_ptr_aligned(object));
0751       //Get control data from associated with this object
0752       block_header_t *ctrl_data = block_header_t::block_header_from_value(object);
0753 
0754       //-------------------------------
0755       //scoped_lock<rmutex> guard(m_header);
0756       //-------------------------------
0757 
0758       //This is not an anonymous object, the pointer is wrong!
0759       BOOST_ASSERT(ctrl_data->alloc_type() == anonymous_type);
0760 
0761       //Call destructors and free memory
0762       //Build scoped ptr to avoid leaks with destructor exception
0763       priv_destroy_n(object, ctrl_data->value_bytes()/sizeof(T));
0764 
0765       BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
0766          boost::move_detail::alignment_of<T>::value;
0767       const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0768       this->deallocate((char*)ctrl_data - front_space);
0769    }
0770 
0771    template<class T>
0772    void priv_destroy_ptr(const T *ptr)
0773    {
0774       BOOST_ASSERT(is_ptr_aligned(ptr));
0775       block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
0776       switch(ctrl_data->alloc_type()){
0777          case anonymous_type:
0778             this->priv_anonymous_destroy(ptr);
0779          break;
0780 
0781          case named_type:
0782             this->priv_generic_named_destroy<T, CharType>
0783                (ctrl_data, m_header.m_named_index, is_node_index_t());
0784          break;
0785 
0786          case unique_type:
0787             this->priv_generic_named_destroy<T, char>
0788                (ctrl_data, m_header.m_unique_index, is_node_index_t());
0789          break;
0790 
0791          default:
0792             //This type is unknown, bad pointer passed to this function!
0793             BOOST_ASSERT(0);
0794          break;
0795       }
0796    }
0797 
0798    template<class T>
0799    static void priv_destroy_n(T* memory, std::size_t num)
0800    {
0801       for (std::size_t destroyed = 0; destroyed < num; ++destroyed)
0802          (memory++)->~T();
0803    }
0804 
0805    //!Returns the name of an object created with construct/find_or_construct
0806    //!functions. Does not throw
0807    static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
0808    {
0809       boost::interprocess::allocation_type type = ctrl_data->alloc_type();
0810       if(type == anonymous_type){
0811          BOOST_ASSERT(ctrl_data->name_length() == 0);
0812          return 0;
0813       }
0814 
0815       BOOST_ASSERT(ctrl_data->name_length() != 0);
0816       CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
0817 
0818       //Sanity checks
0819       BOOST_ASSERT(ctrl_data->name_length() == std::char_traits<CharType>::length(name));
0820       return name;
0821    }
0822 
0823    static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
0824    {
0825       //Get header
0826       BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
0827       return ctrl_data->value_bytes()/sizeofvalue;
0828    }
0829 
0830    //!Returns is the the name of an object created with construct/find_or_construct
0831    //!functions. Does not throw
0832    static instance_type priv_get_instance_type(block_header_t *ctrl_data)
0833    {
0834       //Get header
0835       BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
0836       return (instance_type)ctrl_data->alloc_type();
0837    }
0838 
0839    static size_type priv_get_reserved_bytes()
0840    {
0841       //Get the number of bytes until the end of (*this)
0842       //beginning in the end of the segment_manager_base_t base.
0843       return sizeof(segment_manager) - sizeof(segment_manager_base_t);
0844    }
0845 
0846    template <class T, class CharT>
0847    T *priv_generic_find
0848       (const CharT* name,
0849        IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0850        size_type &length, bool use_lock)
0851    {
0852       typedef IndexType<ipcdetail::index_config
0853                            <CharT, MemoryAlgorithm> > index_t;
0854       typedef typename index_t::iterator              index_it;
0855       typedef typename index_t::compare_key_type      compare_key_t;
0856 
0857       //-------------------------------
0858       scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0859       //-------------------------------
0860       //Find name in index
0861       compare_key_t key (name, std::char_traits<CharT>::length(name));
0862       index_it it = index.find(key);
0863 
0864       //Initialize return values
0865       void *ret_ptr  = 0;
0866       length         = 0;
0867 
0868       //If found, assign values
0869       if(it != index.end()){
0870          //Get header
0871          block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
0872 
0873          //Sanity check
0874          BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
0875          ret_ptr  = ctrl_data->value();
0876          length  = ctrl_data->value_bytes()/ sizeof(T);
0877       }
0878       return static_cast<T*>(ret_ptr);
0879    }
0880 
0881    template <class T, class CharT>
0882    bool priv_generic_named_destroy
0883      (block_header_t *block_header
0884      ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
0885      ,ipcdetail::true_ is_node_index)
0886    {
0887       (void)is_node_index;
0888       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >  index_t;
0889       typedef typename index_t::index_data_t         index_data_t;
0890 
0891       index_data_t* si = block_header_t::template to_first_header<index_data_t>(block_header);
0892       return this->priv_generic_named_destroy_impl<T, CharT>(*si, index);
0893    }
0894 
0895    template <class T, class CharT>
0896    bool priv_generic_named_destroy
0897      (block_header_t *block_header
0898      ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
0899      ,ipcdetail::false_ is_node_index)
0900    {
0901       (void)is_node_index;
0902       CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
0903       return this->priv_generic_named_destroy<T, CharT>(name, index);
0904    }
0905 
0906    template <class T, class CharT>
0907    bool priv_generic_named_destroy(const CharT *name,
0908                                    IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0909    {
0910       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >  index_t;
0911       typedef typename index_t::iterator              index_it;
0912       typedef typename index_t::compare_key_type      compare_key_t;
0913 
0914       //-------------------------------
0915       scoped_lock<rmutex> guard(m_header);
0916       //-------------------------------
0917       //Find name in index
0918       compare_key_t key(name, std::char_traits<CharT>::length(name));
0919       index_it it = index.find(key);
0920 
0921       //If not found, return false
0922       if(it == index.end()){
0923          //This name is not present in the index, wrong pointer or name!
0924          //BOOST_ASSERT(0);
0925          return false;
0926       }
0927       return this->priv_generic_named_destroy_impl<T, CharT>(it, index);
0928    }
0929 
0930    template <class T, class CharT>
0931    bool priv_generic_named_destroy_impl
0932       (typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator it,
0933       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0934    {
0935       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >  index_t;
0936       typedef typename index_t::index_data_t         index_data_t;
0937 
0938       //Get allocation parameters
0939       BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
0940          boost::move_detail::alignment_of<T>::value;
0941       block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
0942 
0943       //Sanity checks
0944       BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
0945 
0946       //Erase node from index
0947       index.erase(it);
0948 
0949       void *memory;
0950       BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
0951          index_data_t*ihdr = block_header_t::template to_first_header<index_data_t>(ctrl_data);
0952          const std::size_t front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
0953          memory = (char*)ihdr - front_space;
0954          ihdr->~index_data_t();
0955       }
0956       else{
0957          const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0958          memory = (char*)ctrl_data - front_space;
0959       }
0960 
0961       //Call destructors and free memory
0962       priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->value_bytes()/sizeof(T));
0963 
0964       //Destroy the headers
0965       ctrl_data->~block_header_t();
0966 
0967       this->deallocate(memory);
0968       return true;
0969    }
0970 
0971    template<class IndexIt>
0972    static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::true_) //is_intrusive
0973    {  return block_header_t::from_first_header(&*it); }
0974 
0975    template<class IndexIt>
0976    static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::false_ ) //!is_intrusive
0977    {
0978       return static_cast<block_header_t*>(ipcdetail::to_raw_pointer(it->second.m_ptr));
0979    }
0980 
0981    //!Generic named new function for
0982    //!named functions
0983    template<class Proxy, class CharT>
0984    typename Proxy::object_type * priv_generic_named_construct
0985       (Proxy pr, unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
0986       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0987    {
0988       typedef typename Proxy::object_type object_type;
0989       std::size_t namelen  = std::char_traits<CharT>::length(name);
0990       BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
0991 
0992       block_header_t block_info ( size_type(sizeof(object_type)*num)
0993                                 , size_type(t_alignment)
0994                                 , type
0995                                 , sizeof(CharT)
0996                                 , namelen);
0997 
0998       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >  index_t;
0999       typedef typename index_t::iterator                       index_it;
1000       typedef typename index_t::compare_key_type               compare_key_t;
1001       typedef typename index_t::insert_commit_data   commit_data_t;
1002       typedef typename index_t::index_data_t  index_data_t;
1003 
1004       //-------------------------------
1005       scoped_lock<rmutex> guard(m_header);
1006       //-------------------------------
1007       //First, we want to know if the key is already present before
1008       //we allocate any memory, and if the key is not present, we
1009       //want to allocate all memory in a single buffer that will
1010       //contain the name and the user buffer.
1011       index_it existing_it;
1012       bool found = false;
1013 
1014       commit_data_t       commit_data;
1015       BOOST_INTERPROCESS_TRY{
1016          typedef std::pair<index_it, bool>                  index_ib;
1017          index_ib insert_ret = index.insert_check(compare_key_t(name, namelen), commit_data);
1018          existing_it = insert_ret.first;
1019          found = !insert_ret.second;
1020       }
1021       //Ignore exceptions
1022       BOOST_INTERPROCESS_CATCH(...){
1023          if(dothrow)
1024             BOOST_INTERPROCESS_RETHROW
1025          return 0;
1026       }
1027       BOOST_INTERPROCESS_CATCH_END
1028 
1029       //If found and this is find or construct, return data, error otherwise
1030       if(found){
1031          if(try2find){
1032             return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive_t())->value());
1033          }
1034          return ipcdetail::null_or_already_exists<object_type>(dothrow);
1035       }
1036 
1037       //Allocates buffer for name + data, this can throw (it hurts)
1038       void *buffer_ptr;
1039       block_header_t * hdr;
1040       std::size_t front_space;
1041 
1042       //Allocate and construct the headers
1043       BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
1044          const size_type total_size = block_info.template total_named_size_with_header<t_alignment, CharT, index_data_t>(namelen);
1045          #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
1046          buffer_ptr = this->allocate(total_size, nothrow<>::get());
1047          #else
1048          buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
1049          #endif
1050          
1051          if(!buffer_ptr)
1052             return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
1053 
1054          front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
1055          hdr = block_header_t::template from_first_header(reinterpret_cast<index_data_t*>((void*)((char*)buffer_ptr + front_space)));
1056       }
1057       else{
1058          const size_type total_size = block_info.template total_named_size<t_alignment, CharT>(namelen);
1059          #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
1060          buffer_ptr = this->allocate(total_size, nothrow<>::get());
1061          #else
1062          buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
1063          #endif
1064 
1065          front_space = block_header_t::template front_space_without_header<t_alignment>();
1066          
1067          //Check if there is enough memory
1068          if (!buffer_ptr)
1069             return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
1070          hdr = reinterpret_cast<block_header_t*>((void*)((char*)buffer_ptr + front_space));
1071       }
1072 
1073       BOOST_ASSERT(is_ptr_aligned(hdr));
1074       hdr = ::new(hdr, boost_container_new_t()) block_header_t(block_info);
1075 
1076       //Build scoped ptr to avoid leaks with constructor exception
1077       ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1078          (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1079 
1080       void *ptr = hdr->value();
1081 
1082       //Copy name to memory segment and insert data
1083       hdr->store_name_length(static_cast<typename block_header_t::name_len_t>(namelen));
1084       CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1085       std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1086 
1087       index_it it;
1088       BOOST_INTERPROCESS_TRY{
1089          BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value) {
1090             index_data_t* index_data = ::new((char*)buffer_ptr + front_space, boost_container_new_t()) index_data_t();
1091             BOOST_ASSERT(is_ptr_aligned(index_data));
1092             it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, *index_data, commit_data);
1093          }
1094          else{
1095             index_data_t id;
1096             it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, id, commit_data);
1097          }
1098       }
1099       //Ignore exceptions
1100       BOOST_INTERPROCESS_CATCH(...){
1101          if(dothrow)
1102             BOOST_INTERPROCESS_RETHROW
1103          return 0;
1104       }
1105       BOOST_INTERPROCESS_CATCH_END
1106 
1107       //Initialize the node value_eraser to erase inserted node
1108       //if something goes wrong
1109       value_eraser<index_t> v_eraser(index, it);
1110 
1111       //Construct array, this can throw
1112       pr.construct_n(ptr, num);
1113 
1114       //Release rollbacks since construction was successful
1115       v_eraser.release();
1116       mem.release();
1117       object_type* const pret = static_cast<object_type*>(ptr);
1118       BOOST_ASSERT(is_ptr_aligned(pret));
1119       return pret;
1120    }
1121 
1122    private:
1123    //!Returns the this pointer
1124    segment_manager *get_this_pointer()
1125    {  return this;  }
1126 
1127    typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type   rmutex;
1128 
1129    scoped_lock<rmutex> priv_get_lock(bool use_lock)
1130    {
1131       scoped_lock<rmutex> local(m_header, defer_lock);
1132       if(use_lock){
1133          local.lock();
1134       }
1135       return scoped_lock<rmutex>(boost::move(local));
1136    }
1137 
1138    //!This struct includes needed data and derives from
1139    //!rmutex to allow EBO when using null interprocess_mutex
1140    struct header_t
1141       :  public rmutex
1142    {
1143       named_index_t           m_named_index;
1144       unique_index_t          m_unique_index;
1145 
1146       header_t(segment_manager_base_t *segment_mngr_base)
1147          :  m_named_index (segment_mngr_base)
1148          ,  m_unique_index(segment_mngr_base)
1149       {}
1150    }  m_header;
1151 
1152    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
1153 };
1154 
1155 
1156 }} //namespace boost { namespace interprocess
1157 
1158 #include <boost/interprocess/detail/config_end.hpp>
1159 
1160 #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
1161