Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-13 08:21:23

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