Back to home page

EIC code displayed by LXR

 
 

    


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

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/core/no_exceptions_support.hpp>
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 
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    typedef MemoryAlgorithm memory_algorithm;
0079 
0080    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0081 
0082    //Experimental. Don't use
0083    typedef typename MemoryAlgorithm::multiallocation_chain    multiallocation_chain;
0084    typedef typename MemoryAlgorithm::difference_type  difference_type;
0085    typedef typename MemoryAlgorithm::size_type        size_type;
0086 
0087    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0088 
0089    //!This constant indicates the payload size
0090    //!associated with each allocation of the memory algorithm
0091    static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
0092 
0093    //!Constructor of the segment_manager_base
0094    //!
0095    //!"size" is the size of the memory segment where
0096    //!the basic segment manager is being constructed.
0097    //!
0098    //!"reserved_bytes" is the number of bytes
0099    //!after the end of the memory algorithm object itself
0100    //!that the memory algorithm will exclude from
0101    //!dynamic allocation
0102    //!
0103    //!Can throw
0104    segment_manager_base(size_type sz, size_type reserved_bytes)
0105       :  MemoryAlgorithm(sz, reserved_bytes)
0106    {
0107       BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
0108    }
0109 
0110    //!Returns the size of the memory
0111    //!segment
0112    size_type get_size() const
0113    {  return MemoryAlgorithm::get_size();  }
0114 
0115    //!Returns the number of free bytes of the memory
0116    //!segment
0117    size_type get_free_memory() const
0118    {  return MemoryAlgorithm::get_free_memory();  }
0119 
0120    //!Obtains the minimum size needed by
0121    //!the segment manager
0122    static size_type get_min_size (size_type size)
0123    {  return MemoryAlgorithm::get_min_size(size);  }
0124 
0125    //!Allocates nbytes bytes. This function is only used in
0126    //!single-segment management. Never throws
0127    void * allocate (size_type nbytes, const std::nothrow_t &)
0128    {  return MemoryAlgorithm::allocate(nbytes);   }
0129 
0130    //!Returns a reference to the internal memory algorithm.
0131    //!This function is useful for custom memory algorithms that
0132    //!need additional configuration options after construction. Never throws.
0133    //!This function should be only used by advanced users.
0134    MemoryAlgorithm &get_memory_algorithm()
0135    {  return static_cast<MemoryAlgorithm&>(*this);   }
0136 
0137    //!Returns a const reference to the internal memory algorithm.
0138    //!This function is useful for custom memory algorithms that
0139    //!need additional configuration options after construction. Never throws.
0140    //!This function should be only used by advanced users.
0141    const MemoryAlgorithm &get_memory_algorithm() const
0142    {  return static_cast<const MemoryAlgorithm&>(*this);   }
0143 
0144    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0145 
0146    //Experimental. Dont' use.
0147    //!Allocates n_elements of elem_bytes bytes.
0148    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0149    void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0150    {
0151       size_type prev_size = chain.size();
0152       MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
0153       if(!elem_bytes || chain.size() == prev_size){
0154          throw bad_alloc();
0155       }
0156    }
0157 
0158    //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
0159    //!Throws bad_alloc on failure. chain.size() is not increased on failure.
0160    void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0161    {
0162       size_type prev_size = chain.size();
0163       MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
0164       if(!sizeof_element || chain.size() == prev_size){
0165          throw bad_alloc();
0166       }
0167    }
0168 
0169    //!Allocates n_elements of elem_bytes bytes.
0170    //!Non-throwing version. chain.size() is not increased on failure.
0171    void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0172    {  MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
0173 
0174    //!Allocates n_elements, each one of
0175    //!element_lengths[i]*sizeof_element bytes.
0176    //!Non-throwing version. chain.size() is not increased on failure.
0177    void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0178    {  MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
0179 
0180    //!Deallocates all elements contained in chain.
0181    //!Never throws.
0182    void deallocate_many(multiallocation_chain &chain)
0183    {  MemoryAlgorithm::deallocate_many(chain); }
0184 
0185    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0186 
0187    //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
0188    //!on failure
0189    void * allocate(size_type nbytes)
0190    {
0191       void * ret = MemoryAlgorithm::allocate(nbytes);
0192       if(!ret)
0193          throw bad_alloc();
0194       return ret;
0195    }
0196 
0197    //!Allocates nbytes bytes. This function is only used in
0198    //!single-segment management. Never throws
0199    void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &)
0200    {  return MemoryAlgorithm::allocate_aligned(nbytes, alignment);   }
0201 
0202    //!Allocates nbytes bytes. This function is only used in
0203    //!single-segment management. Throws bad_alloc when fails
0204    void * allocate_aligned(size_type nbytes, size_type alignment)
0205    {
0206       void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
0207       if(!ret)
0208          throw bad_alloc();
0209       return ret;
0210    }
0211 
0212    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0213 
0214    template<class T>
0215    T *allocation_command  (boost::interprocess::allocation_type command, size_type limit_size,
0216                            size_type &prefer_in_recvd_out_size, T *&reuse)
0217    {
0218       T *ret = MemoryAlgorithm::allocation_command
0219          (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse);
0220       if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0221          throw bad_alloc();
0222       return ret;
0223    }
0224 
0225    void *raw_allocation_command  (boost::interprocess::allocation_type command,   size_type limit_objects,
0226                            size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1)
0227    {
0228       void *ret = MemoryAlgorithm::raw_allocation_command
0229          ( command | boost::interprocess::nothrow_allocation, limit_objects,
0230            prefer_in_recvd_out_size, reuse, sizeof_object);
0231       if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0232          throw bad_alloc();
0233       return ret;
0234    }
0235 
0236    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0237 
0238    //!Deallocates the bytes allocated with allocate/allocate_many()
0239    //!pointed by addr
0240    void   deallocate          (void *addr)
0241    {  MemoryAlgorithm::deallocate(addr);   }
0242 
0243    //!Increases managed memory in extra_size bytes more. This only works
0244    //!with single-segment management.
0245    void grow(size_type extra_size)
0246    {  MemoryAlgorithm::grow(extra_size);   }
0247 
0248    //!Decreases managed memory to the minimum. This only works
0249    //!with single-segment management.
0250    void shrink_to_fit()
0251    {  MemoryAlgorithm::shrink_to_fit();   }
0252 
0253    //!Returns the result of "all_memory_deallocated()" function
0254    //!of the used memory algorithm
0255    bool all_memory_deallocated()
0256    {   return MemoryAlgorithm::all_memory_deallocated(); }
0257 
0258    //!Returns the result of "check_sanity()" function
0259    //!of the used memory algorithm
0260    bool check_sanity()
0261    {   return MemoryAlgorithm::check_sanity(); }
0262 
0263    //!Writes to zero free memory (memory not yet allocated)
0264    //!of the memory algorithm
0265    void zero_free_memory()
0266    {   MemoryAlgorithm::zero_free_memory(); }
0267 
0268    //!Returns the size of the buffer previously allocated pointed by ptr
0269    size_type size(const void *ptr) const
0270    {   return MemoryAlgorithm::size(ptr); }
0271 
0272    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0273    protected:
0274    void * prot_anonymous_construct
0275       (size_type num, bool dothrow, ipcdetail::in_place_interface &table)
0276    {
0277       typedef ipcdetail::block_header<size_type> block_header_t;
0278       block_header_t block_info (  size_type(table.size*num)
0279                                  , size_type(table.alignment)
0280                                  , anonymous_type
0281                                  , 1
0282                                  , 0);
0283 
0284       //Allocate memory
0285       void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get());
0286 
0287       //Check if there is enough memory
0288       if(!ptr_struct){
0289          if(dothrow){
0290             throw bad_alloc();
0291          }
0292          else{
0293             return 0;
0294          }
0295       }
0296 
0297       //Build scoped ptr to avoid leaks with constructor exception
0298       ipcdetail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
0299 
0300       //Now construct the header
0301       block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info);
0302       void *ptr = 0; //avoid gcc warning
0303       ptr = hdr->value();
0304 
0305       //Now call constructors
0306       ipcdetail::array_construct(ptr, num, table);
0307 
0308       //All constructors successful, we don't want erase memory
0309       mem.release();
0310       return ptr;
0311    }
0312 
0313    //!Calls the destructor and makes an anonymous deallocate
0314    void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table)
0315    {
0316 
0317       //Get control data from associated with this object
0318       typedef ipcdetail::block_header<size_type> block_header_t;
0319       block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
0320 
0321       //-------------------------------
0322       //scoped_lock<rmutex> guard(m_header);
0323       //-------------------------------
0324 
0325       if(ctrl_data->alloc_type() != anonymous_type){
0326          //This is not an anonymous object, the pointer is wrong!
0327          BOOST_ASSERT(0);
0328       }
0329 
0330       //Call destructors and free memory
0331       //Build scoped ptr to avoid leaks with destructor exception
0332       std::size_t destroyed = 0;
0333      table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
0334       this->deallocate(ctrl_data);
0335    }
0336    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0337 };
0338 
0339 //!This object is placed in the beginning of memory segment and
0340 //!implements the allocation (named or anonymous) of portions
0341 //!of the segment. This object contains two indexes that
0342 //!maintain an association between a name and a portion of the segment.
0343 //!
0344 //!The first index contains the mappings for normal named objects using the
0345 //!char type specified in the template parameter.
0346 //!
0347 //!The second index contains the association for unique instances. The key will
0348 //!be the const char * returned from type_info.name() function for the unique
0349 //!type to be constructed.
0350 //!
0351 //!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
0352 //!from segment_manager_base<MemoryAlgorithm> and inherits from it
0353 //!many public functions related to anonymous object and raw memory allocation.
0354 //!See segment_manager_base reference to know about those functions.
0355 template<class CharType
0356         ,class MemoryAlgorithm
0357         ,template<class IndexConfig> class IndexType>
0358 class segment_manager
0359    :  public segment_manager_base<MemoryAlgorithm>
0360 {
0361    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0362    //Non-copyable
0363    segment_manager();
0364    segment_manager(const segment_manager &);
0365    segment_manager &operator=(const segment_manager &);
0366    typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
0367    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0368 
0369    public:
0370    typedef MemoryAlgorithm                                  memory_algorithm;
0371    typedef typename segment_manager_base_t::void_pointer    void_pointer;
0372    typedef typename segment_manager_base_t::size_type       size_type;
0373    typedef typename segment_manager_base_t::difference_type difference_type;
0374    typedef CharType                                         char_type;
0375 
0376    typedef segment_manager_base<MemoryAlgorithm>   segment_manager_base_type;
0377 
0378    static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
0379 
0380    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0381    private:
0382    typedef ipcdetail::block_header<size_type> block_header_t;
0383    typedef ipcdetail::index_config<CharType, MemoryAlgorithm>  index_config_named;
0384    typedef ipcdetail::index_config<char, MemoryAlgorithm>      index_config_unique;
0385    typedef IndexType<index_config_named>                    index_type;
0386    typedef ipcdetail::bool_<is_intrusive_index<index_type>::value >    is_intrusive_t;
0387    typedef ipcdetail::bool_<is_node_index<index_type>::value>          is_node_index_t;
0388 
0389    public:
0390    typedef IndexType<index_config_named>                    named_index_t;
0391    typedef IndexType<index_config_unique>                   unique_index_t;
0392    typedef ipcdetail::char_ptr_holder<CharType>                char_ptr_holder_t;
0393    typedef ipcdetail::segment_manager_iterator_transform
0394       <typename named_index_t::const_iterator
0395       ,is_intrusive_index<index_type>::value>   named_transform;
0396 
0397    typedef ipcdetail::segment_manager_iterator_transform
0398       <typename unique_index_t::const_iterator
0399       ,is_intrusive_index<index_type>::value>   unique_transform;
0400    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0401 
0402    typedef typename segment_manager_base_t::mutex_family       mutex_family;
0403 
0404    typedef transform_iterator
0405       <typename named_index_t::const_iterator, named_transform> const_named_iterator;
0406    typedef transform_iterator
0407       <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
0408 
0409    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0410 
0411    //!Constructor proxy object definition helper class
0412    template<class T>
0413    struct construct_proxy
0414    {
0415       typedef ipcdetail::named_proxy<segment_manager, T, false>   type;
0416    };
0417 
0418    //!Constructor proxy object definition helper class
0419    template<class T>
0420    struct construct_iter_proxy
0421    {
0422       typedef ipcdetail::named_proxy<segment_manager, T, true>   type;
0423    };
0424 
0425    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0426 
0427    //!Constructor of the segment manager
0428    //!"size" is the size of the memory segment where
0429    //!the segment manager is being constructed.
0430    //!Can throw
0431    explicit segment_manager(size_type segment_size)
0432       :  segment_manager_base_t(segment_size, priv_get_reserved_bytes())
0433       ,  m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
0434    {
0435       (void) anonymous_instance;   (void) unique_instance;
0436       //Check EBO is applied, it's required
0437       const void * const this_addr = this;
0438       const void *const segm_addr  = static_cast<segment_manager_base_t*>(this);
0439       (void)this_addr;  (void)segm_addr;
0440       BOOST_ASSERT( this_addr == segm_addr);
0441       const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
0442       BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
0443    }
0444 
0445    //!Tries to find a previous named/unique allocation. Returns the address
0446    //!and the object count. On failure the first member of the
0447    //!returned pair is 0.
0448    template <class T>
0449    std::pair<T*, size_type> find  (char_ptr_holder_t name)
0450    {  return this->priv_find_impl<T>(name, true);  }
0451 
0452    //!Tries to find a previous named/unique allocation. Returns the address
0453    //!and the object count. On failure the first member of the
0454    //!returned pair is 0. This search is not mutex-protected!
0455    //!Use it only inside atomic_func() calls, where the internal mutex
0456    //!is guaranteed to be locked.
0457    template <class T>
0458    std::pair<T*, size_type> find_no_lock  (char_ptr_holder_t name)
0459    {  return this->priv_find_impl<T>(name, false);  }
0460 
0461    //!Returns throwing "construct" proxy
0462    //!object
0463    template <class T>
0464    typename construct_proxy<T>::type
0465       construct(char_ptr_holder_t name)
0466    {  return typename construct_proxy<T>::type (this, name, false, true);  }
0467 
0468    //!Returns throwing "search or construct" proxy
0469    //!object
0470    template <class T>
0471    typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
0472    {  return typename construct_proxy<T>::type (this, name, true, true);  }
0473 
0474    //!Returns no throwing "construct" proxy
0475    //!object
0476    template <class T>
0477    typename construct_proxy<T>::type
0478       construct(char_ptr_holder_t name, const std::nothrow_t &)
0479    {  return typename construct_proxy<T>::type (this, name, false, false);  }
0480 
0481    //!Returns no throwing "search or construct"
0482    //!proxy object
0483    template <class T>
0484    typename construct_proxy<T>::type
0485       find_or_construct(char_ptr_holder_t name, const std::nothrow_t &)
0486    {  return typename construct_proxy<T>::type (this, name, true, false);  }
0487 
0488    //!Returns throwing "construct from iterators" proxy object
0489    template <class T>
0490    typename construct_iter_proxy<T>::type
0491       construct_it(char_ptr_holder_t name)
0492    {  return typename construct_iter_proxy<T>::type (this, name, false, true);  }
0493 
0494    //!Returns throwing "search or construct from iterators"
0495    //!proxy object
0496    template <class T>
0497    typename construct_iter_proxy<T>::type
0498       find_or_construct_it(char_ptr_holder_t name)
0499    {  return typename construct_iter_proxy<T>::type (this, name, true, true);  }
0500 
0501    //!Returns no throwing "construct from iterators"
0502    //!proxy object
0503    template <class T>
0504    typename construct_iter_proxy<T>::type
0505       construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0506    {  return typename construct_iter_proxy<T>::type (this, name, false, false);  }
0507 
0508    //!Returns no throwing "search or construct from iterators"
0509    //!proxy object
0510    template <class T>
0511    typename construct_iter_proxy<T>::type
0512       find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0513    {  return typename construct_iter_proxy<T>::type (this, name, true, false);  }
0514 
0515    //!Calls object function blocking recursive interprocess_mutex and guarantees that
0516    //!no new named_alloc or destroy will be executed by any process while
0517    //!executing the object function call
0518    template <class Func>
0519    void atomic_func(Func &f)
0520    {  scoped_lock<rmutex> guard(m_header);  f();  }
0521 
0522    //!Tries to calls a functor guaranteeing that no new construction, search or
0523    //!destruction will be executed by any process while executing the object
0524    //!function call. If the atomic function can't be immediatelly executed
0525    //!because the internal mutex is already locked, returns false.
0526    //!If the functor throws, this function throws.
0527    template <class Func>
0528    bool try_atomic_func(Func &f)
0529    {
0530       scoped_lock<rmutex> guard(m_header, try_to_lock);
0531       if(guard){
0532          f();
0533          return true;
0534       }
0535       else{
0536          return false;
0537       }
0538    }
0539 
0540    //!Destroys a previously created named/unique instance.
0541    //!Returns false if the object was not present.
0542    template <class T>
0543    bool destroy(char_ptr_holder_t name)
0544    {
0545       BOOST_ASSERT(!name.is_anonymous());
0546       ipcdetail::placement_destroy<T> dtor;
0547 
0548       if(name.is_unique()){
0549          return this->priv_generic_named_destroy<char>
0550             ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t());
0551       }
0552       else{
0553          return this->priv_generic_named_destroy<CharType>
0554             ( name.get(), m_header.m_named_index, dtor, is_intrusive_t());
0555       }
0556    }
0557 
0558    //!Destroys an anonymous, unique or named object
0559    //!using its address
0560    template <class T>
0561    void destroy_ptr(const T *p)
0562    {
0563       //If T is void transform it to char
0564       typedef typename ipcdetail::char_if_void<T>::type data_t;
0565       ipcdetail::placement_destroy<data_t> dtor;
0566       priv_destroy_ptr(p, dtor);
0567    }
0568 
0569    //!Returns the name of an object created with construct/find_or_construct
0570    //!functions. Does not throw
0571    template<class T>
0572    static const CharType *get_instance_name(const T *ptr)
0573    { return priv_get_instance_name(block_header_t::block_header_from_value(ptr));  }
0574 
0575    //!Returns the length of an object created with construct/find_or_construct
0576    //!functions. Does not throw.
0577    template<class T>
0578    static size_type get_instance_length(const T *ptr)
0579    {  return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T));  }
0580 
0581    //!Returns is the the name of an object created with construct/find_or_construct
0582    //!functions. Does not throw
0583    template<class T>
0584    static instance_type get_instance_type(const T *ptr)
0585    {  return priv_get_instance_type(block_header_t::block_header_from_value(ptr));  }
0586 
0587    //!Preallocates needed index resources to optimize the
0588    //!creation of "num" named objects in the managed memory segment.
0589    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0590    void reserve_named_objects(size_type num)
0591    {
0592       //-------------------------------
0593       scoped_lock<rmutex> guard(m_header);
0594       //-------------------------------
0595       m_header.m_named_index.reserve(num);
0596    }
0597 
0598    //!Preallocates needed index resources to optimize the
0599    //!creation of "num" unique objects in the managed memory segment.
0600    //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
0601    void reserve_unique_objects(size_type num)
0602    {
0603       //-------------------------------
0604       scoped_lock<rmutex> guard(m_header);
0605       //-------------------------------
0606       m_header.m_unique_index.reserve(num);
0607    }
0608 
0609    //!Calls shrink_to_fit in both named and unique object indexes
0610    //!to try to free unused memory from those indexes.
0611    void shrink_to_fit_indexes()
0612    {
0613       //-------------------------------
0614       scoped_lock<rmutex> guard(m_header);
0615       //-------------------------------
0616       m_header.m_named_index.shrink_to_fit();
0617       m_header.m_unique_index.shrink_to_fit();
0618    }
0619 
0620    //!Returns the number of named objects stored in
0621    //!the segment.
0622    size_type get_num_named_objects()
0623    {
0624       //-------------------------------
0625       scoped_lock<rmutex> guard(m_header);
0626       //-------------------------------
0627       return m_header.m_named_index.size();
0628    }
0629 
0630    //!Returns the number of unique objects stored in
0631    //!the segment.
0632    size_type get_num_unique_objects()
0633    {
0634       //-------------------------------
0635       scoped_lock<rmutex> guard(m_header);
0636       //-------------------------------
0637       return m_header.m_unique_index.size();
0638    }
0639 
0640    //!Obtains the minimum size needed by the
0641    //!segment manager
0642    static size_type get_min_size()
0643    {  return segment_manager_base_t::get_min_size(priv_get_reserved_bytes());  }
0644 
0645    //!Returns a constant iterator to the beginning of the information about
0646    //!the named allocations performed in this segment manager
0647    const_named_iterator named_begin() const
0648    {
0649       return (make_transform_iterator)
0650          (m_header.m_named_index.begin(), named_transform());
0651    }
0652 
0653    //!Returns a constant iterator to the end of the information about
0654    //!the named allocations performed in this segment manager
0655    const_named_iterator named_end() const
0656    {
0657       return (make_transform_iterator)
0658          (m_header.m_named_index.end(), named_transform());
0659    }
0660 
0661    //!Returns a constant iterator to the beginning of the information about
0662    //!the unique allocations performed in this segment manager
0663    const_unique_iterator unique_begin() const
0664    {
0665       return (make_transform_iterator)
0666          (m_header.m_unique_index.begin(), unique_transform());
0667    }
0668 
0669    //!Returns a constant iterator to the end of the information about
0670    //!the unique allocations performed in this segment manager
0671    const_unique_iterator unique_end() const
0672    {
0673       return (make_transform_iterator)
0674          (m_header.m_unique_index.end(), unique_transform());
0675    }
0676 
0677    //!This is the default allocator to allocate types T
0678    //!from this managed segment
0679    template<class T>
0680    struct allocator
0681    {
0682       typedef boost::interprocess::allocator<T, segment_manager> type;
0683    };
0684 
0685    //!Returns an instance of the default allocator for type T
0686    //!initialized that allocates memory from this segment manager.
0687    template<class T>
0688    typename allocator<T>::type
0689       get_allocator()
0690    {   return typename allocator<T>::type(this); }
0691 
0692    //!This is the default deleter to delete types T
0693    //!from this managed segment.
0694    template<class T>
0695    struct deleter
0696    {
0697       typedef boost::interprocess::deleter<T, segment_manager> type;
0698    };
0699 
0700    //!Returns an instance of the default deleter for type T
0701    //!that will delete an object constructed in this segment manager.
0702    template<class T>
0703    typename deleter<T>::type
0704       get_deleter()
0705    {   return typename deleter<T>::type(this); }
0706 
0707    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0708 
0709    //!Generic named/anonymous new function. Offers all the possibilities,
0710    //!such as throwing, search before creating, and the constructor is
0711    //!encapsulated in an object function.
0712    template<class T>
0713    T *generic_construct(const CharType *name,
0714                         size_type num,
0715                          bool try2find,
0716                          bool dothrow,
0717                          ipcdetail::in_place_interface &table)
0718    {
0719       return static_cast<T*>
0720          (priv_generic_construct(name, num, try2find, dothrow, table));
0721    }
0722 
0723    private:
0724    //!Tries to find a previous named allocation. Returns the address
0725    //!and the object count. On failure the first member of the
0726    //!returned pair is 0.
0727    template <class T>
0728    std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
0729    {
0730       //The name can't be null, no anonymous object can be found by name
0731       BOOST_ASSERT(name != 0);
0732       ipcdetail::placement_destroy<T> table;
0733       size_type sz;
0734       void *ret;
0735 
0736       if(name == reinterpret_cast<const CharType*>(-1)){
0737          ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock);
0738       }
0739       else{
0740          ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock);
0741       }
0742       return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
0743    }
0744 
0745    //!Tries to find a previous unique allocation. Returns the address
0746    //!and the object count. On failure the first member of the
0747    //!returned pair is 0.
0748    template <class T>
0749    std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t* name, bool lock)
0750    {
0751       ipcdetail::placement_destroy<T> table;
0752       size_type size;
0753       void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock);
0754       return std::pair<T*, size_type>(static_cast<T*>(ret), size);
0755    }
0756 
0757    void *priv_generic_construct
0758       (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table)
0759    {
0760       void *ret;
0761       //Security overflow check
0762       if(num > ((std::size_t)-1)/table.size){
0763          if(dothrow)
0764             throw bad_alloc();
0765          else
0766             return 0;
0767       }
0768       if(name == 0){
0769          ret = this->prot_anonymous_construct(num, dothrow, table);
0770       }
0771       else if(name == reinterpret_cast<const CharType*>(-1)){
0772          ret = this->priv_generic_named_construct<char>
0773             (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t());
0774       }
0775       else{
0776          ret = this->priv_generic_named_construct<CharType>
0777             (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t());
0778       }
0779       return ret;
0780    }
0781 
0782    void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor)
0783    {
0784       block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
0785       switch(ctrl_data->alloc_type()){
0786          case anonymous_type:
0787             this->prot_anonymous_destroy(ptr, dtor);
0788          break;
0789 
0790          case named_type:
0791             this->priv_generic_named_destroy<CharType>
0792                (ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
0793          break;
0794 
0795          case unique_type:
0796             this->priv_generic_named_destroy<char>
0797                (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
0798          break;
0799 
0800          default:
0801             //This type is unknown, bad pointer passed to this function!
0802             BOOST_ASSERT(0);
0803          break;
0804       }
0805    }
0806 
0807    //!Returns the name of an object created with construct/find_or_construct
0808    //!functions. Does not throw
0809    static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
0810    {
0811       boost::interprocess::allocation_type type = ctrl_data->alloc_type();
0812       if(type == anonymous_type){
0813          BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
0814                 (type == unique_type    && ctrl_data->m_num_char != 0) );
0815          return 0;
0816       }
0817       CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
0818 
0819       //Sanity checks
0820       BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
0821       BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
0822       return name;
0823    }
0824 
0825    static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
0826    {
0827       //Get header
0828       BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
0829       return ctrl_data->value_bytes()/sizeofvalue;
0830    }
0831 
0832    //!Returns is the the name of an object created with construct/find_or_construct
0833    //!functions. Does not throw
0834    static instance_type priv_get_instance_type(block_header_t *ctrl_data)
0835    {
0836       //Get header
0837       BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
0838       return (instance_type)ctrl_data->alloc_type();
0839    }
0840 
0841    static size_type priv_get_reserved_bytes()
0842    {
0843       //Get the number of bytes until the end of (*this)
0844       //beginning in the end of the segment_manager_base_t base.
0845       return sizeof(segment_manager) - sizeof(segment_manager_base_t);
0846    }
0847 
0848    template <class CharT>
0849    void *priv_generic_find
0850       (const CharT* name,
0851        IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0852        ipcdetail::in_place_interface &table,
0853        size_type &length, ipcdetail::true_ is_intrusive, bool use_lock)
0854    {
0855       (void)is_intrusive;
0856       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >         index_type_t;
0857       typedef typename index_type_t::iterator           index_it;
0858 
0859       //-------------------------------
0860       scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0861       //-------------------------------
0862       //Find name in index
0863       ipcdetail::intrusive_compare_key<CharT> key
0864          (name, std::char_traits<CharT>::length(name));
0865       index_it it = index.find(key);
0866 
0867       //Initialize return values
0868       void *ret_ptr  = 0;
0869       length         = 0;
0870 
0871       //If found, assign values
0872       if(it != index.end()){
0873          //Get header
0874          block_header_t *ctrl_data = it->get_block_header();
0875 
0876          //Sanity check
0877          BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0878          BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
0879          ret_ptr  = ctrl_data->value();
0880          length  = ctrl_data->m_value_bytes/table.size;
0881       }
0882       return ret_ptr;
0883    }
0884 
0885    template <class CharT>
0886    void *priv_generic_find
0887       (const CharT* name,
0888        IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0889        ipcdetail::in_place_interface &table,
0890        size_type &length, ipcdetail::false_ is_intrusive, bool use_lock)
0891    {
0892       (void)is_intrusive;
0893       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >      char_aware_index_type;
0894       typedef typename char_aware_index_type::key_type        key_type;
0895       typedef typename char_aware_index_type::iterator        index_it;
0896 
0897       //-------------------------------
0898       scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0899       //-------------------------------
0900       //Find name in index
0901       index_it it = index.find(key_type(name, std::char_traits<CharT>::length(name)));
0902 
0903       //Initialize return values
0904       void *ret_ptr  = 0;
0905       length         = 0;
0906 
0907       //If found, assign values
0908       if(it != index.end()){
0909          //Get header
0910          block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
0911                                     (ipcdetail::to_raw_pointer(it->second.m_ptr));
0912 
0913          //Sanity check
0914          BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0915          BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
0916          ret_ptr  = ctrl_data->value();
0917          length  = ctrl_data->m_value_bytes/table.size;
0918       }
0919       return ret_ptr;
0920    }
0921 
0922    template <class CharT>
0923    bool priv_generic_named_destroy
0924      (block_header_t *block_header,
0925       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0926       ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index)
0927    {
0928       (void)is_node_index;
0929       typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
0930 
0931       index_it *ihdr = block_header_t::template to_first_header<index_it>(block_header);
0932       return this->priv_generic_named_destroy_impl<CharT>(*ihdr, index, table);
0933    }
0934 
0935    template <class CharT>
0936    bool priv_generic_named_destroy
0937      (block_header_t *block_header,
0938       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0939       ipcdetail::in_place_interface &table,
0940       ipcdetail::false_ is_node_index)
0941    {
0942       (void)is_node_index;
0943       CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
0944       return this->priv_generic_named_destroy<CharT>(name, index, table, is_intrusive_t());
0945    }
0946 
0947    template <class CharT>
0948    bool priv_generic_named_destroy(const CharT *name,
0949                                    IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0950                                    ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index)
0951    {
0952       (void)is_intrusive_index;
0953       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >         index_type_t;
0954       typedef typename index_type_t::iterator           index_it;
0955       typedef typename index_type_t::value_type         intrusive_value_type;
0956 
0957       //-------------------------------
0958       scoped_lock<rmutex> guard(m_header);
0959       //-------------------------------
0960       //Find name in index
0961       ipcdetail::intrusive_compare_key<CharT> key
0962          (name, std::char_traits<CharT>::length(name));
0963       index_it it = index.find(key);
0964 
0965       //If not found, return false
0966       if(it == index.end()){
0967          //This name is not present in the index, wrong pointer or name!
0968          //BOOST_ASSERT(0);
0969          return false;
0970       }
0971 
0972       block_header_t *ctrl_data = it->get_block_header();
0973       intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
0974       void *memory = iv;
0975       void *values = ctrl_data->value();
0976       std::size_t num = ctrl_data->m_value_bytes/table.size;
0977 
0978       //Sanity check
0979       BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0980       BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
0981 
0982       //Erase node from index
0983       index.erase(it);
0984 
0985       //Destroy the headers
0986       ctrl_data->~block_header_t();
0987       iv->~intrusive_value_type();
0988 
0989       //Call destructors and free memory
0990       std::size_t destroyed;
0991       table.destroy_n(values, num, destroyed);
0992       this->deallocate(memory);
0993       return true;
0994    }
0995 
0996    template <class CharT>
0997    bool priv_generic_named_destroy(const CharT *name,
0998                                    IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0999                                    ipcdetail::in_place_interface &table,
1000                                    ipcdetail::false_ is_intrusive_index)
1001    {
1002       (void)is_intrusive_index;
1003       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >            char_aware_index_type;
1004       typedef typename char_aware_index_type::iterator              index_it;
1005       typedef typename char_aware_index_type::key_type              key_type;
1006 
1007       //-------------------------------
1008       scoped_lock<rmutex> guard(m_header);
1009       //-------------------------------
1010       //Try to find the name in the index
1011       index_it it = index.find(key_type (name,
1012                                      std::char_traits<CharT>::length(name)));
1013 
1014       //If not found, return false
1015       if(it == index.end()){
1016          //This name is not present in the index, wrong pointer or name!
1017          //BOOST_ASSERT(0);
1018          return false;
1019       }
1020       return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
1021    }
1022 
1023    template <class CharT>
1024    bool priv_generic_named_destroy_impl
1025       (const typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
1026       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
1027       ipcdetail::in_place_interface &table)
1028    {
1029       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >      char_aware_index_type;
1030       typedef typename char_aware_index_type::iterator        index_it;
1031 
1032       //Get allocation parameters
1033       block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
1034                                  (ipcdetail::to_raw_pointer(it->second.m_ptr));
1035       char *stored_name       = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
1036       (void)stored_name;
1037 
1038       //Check if the distance between the name pointer and the memory pointer
1039       //is correct (this can detect incorrect type in destruction)
1040       std::size_t num = ctrl_data->m_value_bytes/table.size;
1041       void *values = ctrl_data->value();
1042 
1043       //Sanity check
1044       BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
1045       BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
1046       BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
1047 
1048       //Erase node from index
1049       index.erase(it);
1050 
1051       //Destroy the header
1052       ctrl_data->~block_header_t();
1053 
1054       void *memory;
1055       if(is_node_index_t::value){
1056          index_it *ihdr = block_header_t::template
1057             to_first_header<index_it>(ctrl_data);
1058          ihdr->~index_it();
1059          memory = ihdr;
1060       }
1061       else{
1062          memory = ctrl_data;
1063       }
1064 
1065       //Call destructors and free memory
1066       std::size_t destroyed;
1067       table.destroy_n(values, num, destroyed);
1068       this->deallocate(memory);
1069       return true;
1070    }
1071 
1072    template<class CharT>
1073    void * priv_generic_named_construct
1074       (unsigned char type, const CharT *name, size_type num, bool try2find,
1075       bool dothrow, ipcdetail::in_place_interface &table, 
1076       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive)
1077    {
1078       (void)is_intrusive;
1079      std::size_t namelen  = std::char_traits<CharT>::length(name);
1080 
1081       block_header_t block_info ( size_type(table.size*num)
1082                                  , size_type(table.alignment)
1083                                  , type
1084                                  , sizeof(CharT)
1085                                  , namelen);
1086 
1087       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >            index_type_t;
1088       typedef typename index_type_t::iterator              index_it;
1089       typedef std::pair<index_it, bool>                  index_ib;
1090 
1091       //-------------------------------
1092       scoped_lock<rmutex> guard(m_header);
1093       //-------------------------------
1094       //Insert the node. This can throw.
1095       //First, we want to know if the key is already present before
1096       //we allocate any memory, and if the key is not present, we
1097       //want to allocate all memory in a single buffer that will
1098       //contain the name and the user buffer.
1099       //
1100       //Since equal_range(key) + insert(hint, value) approach is
1101       //quite inefficient in container implementations
1102       //(they re-test if the position is correct), I've chosen
1103       //to insert the node, do an ugly un-const cast and modify
1104       //the key (which is a smart pointer) to an equivalent one
1105       index_ib insert_ret;
1106 
1107       typename index_type_t::insert_commit_data   commit_data;
1108       typedef typename index_type_t::value_type   intrusive_value_type;
1109 
1110       BOOST_TRY{
1111          ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
1112          insert_ret = index.insert_check(key, commit_data);
1113       }
1114       //Ignore exceptions
1115       BOOST_CATCH(...){
1116          if(dothrow)
1117             BOOST_RETHROW
1118          return 0;
1119       }
1120       BOOST_CATCH_END
1121 
1122       index_it it = insert_ret.first;
1123 
1124       //If found and this is find or construct, return data
1125       //else return null
1126       if(!insert_ret.second){
1127          if(try2find){
1128             return it->get_block_header()->value();
1129          }
1130          if(dothrow){
1131             throw interprocess_exception(already_exists_error);
1132          }
1133          else{
1134             return 0;
1135          }
1136       }
1137 
1138       //Allocates buffer for name + data, this can throw (it hurts)
1139       void *buffer_ptr;
1140 
1141       //Check if there is enough memory
1142       if(dothrow){
1143          buffer_ptr = this->allocate
1144             (block_info.template total_size_with_header<intrusive_value_type>());
1145       }
1146       else{
1147          buffer_ptr = this->allocate
1148             (block_info.template total_size_with_header<intrusive_value_type>(), nothrow<>::get());
1149          if(!buffer_ptr)
1150             return 0;
1151       }
1152 
1153       //Now construct the intrusive hook plus the header
1154       intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type();
1155       block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t())block_header_t(block_info);
1156       void *ptr = 0; //avoid gcc warning
1157       ptr = hdr->value();
1158 
1159       //Copy name to memory segment and insert data
1160       CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1161       std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1162 
1163       BOOST_TRY{
1164          //Now commit the insertion using previous context data
1165          it = index.insert_commit(*intrusive_hdr, commit_data);
1166       }
1167       //Ignore exceptions
1168       BOOST_CATCH(...){
1169          if(dothrow)
1170             BOOST_RETHROW
1171          return 0;
1172       }
1173       BOOST_CATCH_END
1174 
1175       //Avoid constructions if constructor is trivial
1176       //Build scoped ptr to avoid leaks with constructor exception
1177       ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1178          (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1179 
1180       //Initialize the node value_eraser to erase inserted node
1181       //if something goes wrong. This will be executed *before*
1182       //the memory allocation as the intrusive value is built in that
1183       //memory
1184       value_eraser<index_type_t> v_eraser(index, it);
1185 
1186       //Construct array, this can throw
1187       ipcdetail::array_construct(ptr, num, table);
1188 
1189       //Release rollbacks since construction was successful
1190       v_eraser.release();
1191       mem.release();
1192       return ptr;
1193    }
1194 
1195    //!Generic named new function for
1196    //!named functions
1197    template<class CharT>
1198    void * priv_generic_named_construct
1199       (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
1200       ipcdetail::in_place_interface &table, 
1201       IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive)
1202    {
1203       (void)is_intrusive;
1204       std::size_t namelen  = std::char_traits<CharT>::length(name);
1205 
1206       block_header_t block_info ( size_type(table.size*num)
1207                                  , size_type(table.alignment)
1208                                  , type
1209                                  , sizeof(CharT)
1210                                  , namelen);
1211 
1212       typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >            index_type_t;
1213       typedef typename index_type_t::key_type              key_type;
1214       typedef typename index_type_t::mapped_type           mapped_type;
1215       typedef typename index_type_t::value_type            value_type;
1216       typedef typename index_type_t::iterator              index_it;
1217       typedef std::pair<index_it, bool>                  index_ib;
1218 
1219       //-------------------------------
1220       scoped_lock<rmutex> guard(m_header);
1221       //-------------------------------
1222       //Insert the node. This can throw.
1223       //First, we want to know if the key is already present before
1224       //we allocate any memory, and if the key is not present, we
1225       //want to allocate all memory in a single buffer that will
1226       //contain the name and the user buffer.
1227       //
1228       //Since equal_range(key) + insert(hint, value) approach is
1229       //quite inefficient in container implementations
1230       //(they re-test if the position is correct), I've chosen
1231       //to insert the node, do an ugly un-const cast and modify
1232       //the key (which is a smart pointer) to an equivalent one
1233       index_ib insert_ret;
1234       BOOST_TRY{
1235          insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
1236       }
1237       //Ignore exceptions
1238       BOOST_CATCH(...){
1239          if(dothrow)
1240             BOOST_RETHROW;
1241          return 0;
1242       }
1243       BOOST_CATCH_END
1244 
1245       index_it it = insert_ret.first;
1246 
1247       //If found and this is find or construct, return data
1248       //else return null
1249       if(!insert_ret.second){
1250          if(try2find){
1251             block_header_t *hdr = static_cast<block_header_t*>
1252                (ipcdetail::to_raw_pointer(it->second.m_ptr));
1253             return hdr->value();
1254          }
1255          return 0;
1256       }
1257       //Initialize the node value_eraser to erase inserted node
1258       //if something goes wrong
1259       value_eraser<index_type_t> v_eraser(index, it);
1260 
1261       //Allocates buffer for name + data, this can throw (it hurts)
1262       void *buffer_ptr;
1263       block_header_t * hdr;
1264 
1265       //Allocate and construct the headers
1266       if(is_node_index_t::value){
1267          size_type total_size = block_info.template total_size_with_header<index_it>();
1268          if(dothrow){
1269             buffer_ptr = this->allocate(total_size);
1270          }
1271          else{
1272             buffer_ptr = this->allocate(total_size, nothrow<>::get());
1273             if(!buffer_ptr)
1274                return 0;
1275          }
1276          index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it);
1277          hdr = block_header_t::template from_first_header<index_it>(idr);
1278       }
1279       else{
1280          if(dothrow){
1281             buffer_ptr = this->allocate(block_info.total_size());
1282          }
1283          else{
1284             buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get());
1285             if(!buffer_ptr)
1286                return 0;
1287          }
1288          hdr = static_cast<block_header_t*>(buffer_ptr);
1289       }
1290 
1291       hdr = ::new(hdr, boost_container_new_t())block_header_t(block_info);
1292       void *ptr = 0; //avoid gcc warning
1293       ptr = hdr->value();
1294 
1295       //Copy name to memory segment and insert data
1296       CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1297       std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1298 
1299       //Do the ugly cast, please mama, forgive me!
1300       //This new key points to an identical string, so it must have the
1301       //same position than the overwritten key according to the predicate
1302       const_cast<key_type &>(it->first).name(name_ptr);
1303       it->second.m_ptr  = hdr;
1304 
1305       //Build scoped ptr to avoid leaks with constructor exception
1306       ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1307          (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1308 
1309       //Construct array, this can throw
1310       ipcdetail::array_construct(ptr, num, table);
1311 
1312       //All constructors successful, we don't want to release memory
1313       mem.release();
1314 
1315       //Release node v_eraser since construction was successful
1316       v_eraser.release();
1317       return ptr;
1318    }
1319 
1320    private:
1321    //!Returns the this pointer
1322    segment_manager *get_this_pointer()
1323    {  return this;  }
1324 
1325    typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type   rmutex;
1326 
1327    scoped_lock<rmutex> priv_get_lock(bool use_lock)
1328    {
1329       scoped_lock<rmutex> local(m_header, defer_lock);
1330       if(use_lock){
1331          local.lock();
1332       }
1333       return scoped_lock<rmutex>(boost::move(local));
1334    }
1335 
1336    //!This struct includes needed data and derives from
1337    //!rmutex to allow EBO when using null interprocess_mutex
1338    struct header_t
1339       :  public rmutex
1340    {
1341       named_index_t           m_named_index;
1342       unique_index_t          m_unique_index;
1343 
1344       header_t(segment_manager_base_t *segment_mngr_base)
1345          :  m_named_index (segment_mngr_base)
1346          ,  m_unique_index(segment_mngr_base)
1347       {}
1348    }  m_header;
1349 
1350    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
1351 };
1352 
1353 
1354 }} //namespace boost { namespace interprocess
1355 
1356 #include <boost/interprocess/detail/config_end.hpp>
1357 
1358 #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
1359