PageRenderTime 102ms CodeModel.GetById 15ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/interprocess/segment_manager.hpp

http://hadesmem.googlecode.com/
C++ Header | 1361 lines | 839 code | 187 blank | 335 comment | 71 complexity | 649a334305859d9fb288f5ccb0c8ba45 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1//////////////////////////////////////////////////////////////////////////////
   2//
   3// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
   4// Software License, Version 1.0. (See accompanying file
   5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
   6//
   7// See http://www.boost.org/libs/interprocess for documentation.
   8//
   9//////////////////////////////////////////////////////////////////////////////
  10
  11#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
  12#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
  13
  14#if (defined _MSC_VER) && (_MSC_VER >= 1200)
  15#  pragma once
  16#endif
  17
  18#include <boost/interprocess/detail/config_begin.hpp>
  19#include <boost/interprocess/detail/workaround.hpp>
  20
  21#include <boost/detail/no_exceptions_support.hpp>
  22#include <boost/interprocess/detail/type_traits.hpp>
  23
  24#include <boost/interprocess/detail/transform_iterator.hpp>
  25
  26#include <boost/interprocess/detail/mpl.hpp>
  27#include <boost/interprocess/detail/segment_manager_helper.hpp>
  28#include <boost/interprocess/detail/named_proxy.hpp>
  29#include <boost/interprocess/detail/utilities.hpp>
  30#include <boost/interprocess/offset_ptr.hpp>
  31#include <boost/interprocess/indexes/iset_index.hpp>
  32#include <boost/interprocess/exceptions.hpp>
  33#include <boost/interprocess/allocators/allocator.hpp>
  34#include <boost/interprocess/smart_ptr/deleter.hpp>
  35#include <boost/interprocess/detail/move.hpp>
  36#include <boost/interprocess/sync/scoped_lock.hpp>
  37#include <cstddef>   //std::size_t
  38#include <string>    //char_traits
  39#include <new>       //std::nothrow
  40#include <utility>   //std::pair
  41#include <boost/assert.hpp>
  42#ifndef BOOST_NO_EXCEPTIONS
  43#include <exception>
  44#endif
  45
  46//!\file
  47//!Describes the object placed in a memory segment that provides
  48//!named object allocation capabilities for single-segment and
  49//!multi-segment allocations.
  50
  51namespace boost{
  52namespace interprocess{
  53
  54//!This object is the public base class of segment manager.
  55//!This class only depends on the memory allocation algorithm
  56//!and implements all the allocation features not related
  57//!to named or unique objects.
  58//!
  59//!Storing a reference to segment_manager forces
  60//!the holder class to be dependent on index types and character types.
  61//!When such dependence is not desirable and only anonymous and raw
  62//!allocations are needed, segment_manager_base is the correct answer.
  63template<class MemoryAlgorithm>
  64class segment_manager_base
  65   :  private MemoryAlgorithm
  66{
  67   public:
  68   typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
  69   typedef typename MemoryAlgorithm::void_pointer  void_pointer;
  70   typedef typename MemoryAlgorithm::mutex_family  mutex_family;
  71   typedef MemoryAlgorithm memory_algorithm;
  72   
  73   /// @cond
  74   
  75   //Experimental. Don't use
  76   typedef typename MemoryAlgorithm::multiallocation_chain    multiallocation_chain;
  77
  78   /// @endcond
  79
  80   //!This constant indicates the payload size
  81   //!associated with each allocation of the memory algorithm
  82   static const std::size_t PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
  83
  84   //!Constructor of the segment_manager_base
  85   //!
  86   //!"size" is the size of the memory segment where
  87   //!the basic segment manager is being constructed.
  88   //!
  89   //!"reserved_bytes" is the number of bytes 
  90   //!after the end of the memory algorithm object itself
  91   //!that the memory algorithm will exclude from
  92   //!dynamic allocation
  93   //!
  94   //!Can throw
  95   segment_manager_base(std::size_t size, std::size_t reserved_bytes)
  96      :  MemoryAlgorithm(size, reserved_bytes)
  97   {
  98      BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
  99   }
 100
 101   //!Returns the size of the memory
 102   //!segment
 103   std::size_t get_size() const
 104   {  return MemoryAlgorithm::get_size();  }
 105
 106   //!Returns the number of free bytes of the memory
 107   //!segment
 108   std::size_t get_free_memory() const
 109   {  return MemoryAlgorithm::get_free_memory();  }
 110
 111   //!Obtains the minimum size needed by
 112   //!the segment manager
 113   static std::size_t get_min_size (std::size_t size)
 114   {  return MemoryAlgorithm::get_min_size(size);  }
 115
 116   //!Allocates nbytes bytes. This function is only used in 
 117   //!single-segment management. Never throws
 118   void * allocate (std::size_t nbytes, std::nothrow_t)
 119   {  return MemoryAlgorithm::allocate(nbytes);   }
 120
 121   /// @cond
 122
 123   //Experimental. Dont' use.
 124   //!Allocates n_elements of
 125   //!elem_size bytes. Throws bad_alloc on failure.
 126   multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
 127   {
 128      multiallocation_chain mem(MemoryAlgorithm::allocate_many(elem_bytes, num_elements));
 129      if(mem.empty()) throw bad_alloc();
 130      return boost::interprocess::move(mem);
 131   }
 132
 133   //!Allocates n_elements, each one of
 134   //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure.
 135   multiallocation_chain allocate_many
 136      (const std::size_t *element_lenghts, std::size_t n_elements, std::size_t sizeof_element = 1)
 137   {
 138      multiallocation_chain mem(MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element));
 139      if(mem.empty()) throw bad_alloc();
 140      return boost::interprocess::move(mem);
 141   }
 142
 143   //!Allocates n_elements of
 144   //!elem_size bytes. Returns a default constructed iterator on failure.
 145   multiallocation_chain allocate_many
 146      (std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t)
 147   {  return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); }
 148
 149   //!Allocates n_elements, each one of
 150   //!element_lenghts[i]*sizeof_element bytes.
 151   //!Returns a default constructed iterator on failure.
 152   multiallocation_chain allocate_many
 153      (const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t)
 154   {  return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); }
 155
 156   //!Deallocates elements pointed by the
 157   //!multiallocation iterator range.
 158   void deallocate_many(multiallocation_chain chain)
 159   {  MemoryAlgorithm::deallocate_many(boost::interprocess::move(chain)); }
 160
 161   /// @endcond
 162
 163   //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
 164   //!on failure
 165   void * allocate(std::size_t nbytes)
 166   {  
 167      void * ret = MemoryAlgorithm::allocate(nbytes);
 168      if(!ret)
 169         throw bad_alloc();
 170      return ret;
 171   }
 172
 173   //!Allocates nbytes bytes. This function is only used in 
 174   //!single-segment management. Never throws
 175   void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t)
 176   {  return MemoryAlgorithm::allocate_aligned(nbytes, alignment);   }
 177
 178   //!Allocates nbytes bytes. This function is only used in 
 179   //!single-segment management. Throws bad_alloc when fails
 180   void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
 181   {  
 182      void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
 183      if(!ret)
 184         throw bad_alloc();
 185      return ret;
 186   }
 187
 188   template<class T>
 189   std::pair<T *, bool>
 190      allocation_command  (boost::interprocess::allocation_type command,   std::size_t limit_size,
 191                           std::size_t preferred_size,std::size_t &received_size,
 192                           T *reuse_ptr = 0)
 193   {
 194      std::pair<T *, bool> ret = MemoryAlgorithm::allocation_command
 195         ( command | boost::interprocess::nothrow_allocation, limit_size, preferred_size, received_size
 196         , reuse_ptr);
 197      if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
 198         throw bad_alloc();
 199      return ret;
 200   }
 201
 202   std::pair<void *, bool>
 203      raw_allocation_command  (boost::interprocess::allocation_type command,   std::size_t limit_objects,
 204                           std::size_t preferred_objects,std::size_t &received_objects,
 205                           void *reuse_ptr = 0, std::size_t sizeof_object = 1)
 206   {
 207      std::pair<void *, bool> ret = MemoryAlgorithm::raw_allocation_command
 208         ( command | boost::interprocess::nothrow_allocation, limit_objects, preferred_objects, received_objects
 209         , reuse_ptr, sizeof_object);
 210      if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
 211         throw bad_alloc();
 212      return ret;
 213   }
 214
 215   //!Deallocates the bytes allocated with allocate/allocate_many()
 216   //!pointed by addr
 217   void   deallocate          (void *addr)
 218   {  MemoryAlgorithm::deallocate(addr);   }
 219
 220   //!Increases managed memory in extra_size bytes more. This only works
 221   //!with single-segment management.
 222   void grow(std::size_t extra_size)
 223   {  MemoryAlgorithm::grow(extra_size);   }
 224
 225   //!Decreases managed memory to the minimum. This only works
 226   //!with single-segment management.
 227   void shrink_to_fit()
 228   {  MemoryAlgorithm::shrink_to_fit();   }
 229
 230   //!Returns the result of "all_memory_deallocated()" function
 231   //!of the used memory algorithm
 232   bool all_memory_deallocated()
 233   {   return MemoryAlgorithm::all_memory_deallocated(); }
 234
 235   //!Returns the result of "check_sanity()" function
 236   //!of the used memory algorithm
 237   bool check_sanity()
 238   {   return MemoryAlgorithm::check_sanity(); }
 239
 240   //!Writes to zero free memory (memory not yet allocated)
 241   //!of the memory algorithm
 242   void zero_free_memory()
 243   {   MemoryAlgorithm::zero_free_memory(); }
 244
 245   //!Returns the size of the buffer previously allocated pointed by ptr
 246   std::size_t size(const void *ptr) const
 247   {   return MemoryAlgorithm::size(ptr); }
 248
 249   /// @cond
 250   protected:
 251   void * prot_anonymous_construct
 252      (std::size_t num, bool dothrow, detail::in_place_interface &table)
 253   {
 254      typedef detail::block_header block_header_t;
 255      block_header_t block_info (  table.size*num
 256                                 , table.alignment
 257                                 , anonymous_type
 258                                 , 1
 259                                 , 0);
 260
 261      //Allocate memory
 262      void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t());
 263
 264      //Check if there is enough memory
 265      if(!ptr_struct){
 266         if(dothrow){
 267            throw bad_alloc();
 268         }
 269         else{
 270            return 0; 
 271         }
 272      }
 273
 274      //Build scoped ptr to avoid leaks with constructor exception
 275      detail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
 276
 277      //Now construct the header
 278      block_header_t * hdr = new(ptr_struct) block_header_t(block_info);
 279      void *ptr = 0; //avoid gcc warning
 280      ptr = hdr->value();
 281
 282      //Now call constructors
 283      detail::array_construct(ptr, num, table);
 284
 285      //All constructors successful, we don't want erase memory
 286      mem.release();
 287      return ptr;
 288   }
 289
 290   //!Calls the destructor and makes an anonymous deallocate
 291   void prot_anonymous_destroy(const void *object, detail::in_place_interface &table)
 292   {
 293
 294      //Get control data from associated with this object    
 295      typedef detail::block_header block_header_t;
 296      block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
 297
 298      //-------------------------------
 299      //scoped_lock<rmutex> guard(m_header);
 300      //-------------------------------
 301
 302      if(ctrl_data->alloc_type() != anonymous_type){
 303         //This is not an anonymous object, the pointer is wrong!
 304         BOOST_ASSERT(0);
 305      }
 306
 307      //Call destructors and free memory
 308      //Build scoped ptr to avoid leaks with destructor exception
 309      std::size_t destroyed = 0;
 310      table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
 311      this->deallocate(ctrl_data);
 312   }
 313   /// @endcond
 314};
 315
 316//!This object is placed in the beginning of memory segment and
 317//!implements the allocation (named or anonymous) of portions
 318//!of the segment. This object contains two indexes that
 319//!maintain an association between a name and a portion of the segment. 
 320//!
 321//!The first index contains the mappings for normal named objects using the 
 322//!char type specified in the template parameter.
 323//!
 324//!The second index contains the association for unique instances. The key will
 325//!be the const char * returned from type_info.name() function for the unique
 326//!type to be constructed.
 327//!
 328//!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
 329//!from segment_manager_base<MemoryAlgorithm> and inherits from it
 330//!many public functions related to anonymous object and raw memory allocation.
 331//!See segment_manager_base reference to know about those functions.
 332template<class CharType
 333        ,class MemoryAlgorithm
 334        ,template<class IndexConfig> class IndexType>
 335class segment_manager
 336   :  public segment_manager_base<MemoryAlgorithm>
 337{ 
 338   /// @cond
 339   //Non-copyable
 340   segment_manager();
 341   segment_manager(const segment_manager &);
 342   segment_manager &operator=(const segment_manager &);
 343   typedef segment_manager_base<MemoryAlgorithm> Base;
 344   typedef detail::block_header block_header_t;
 345   /// @endcond
 346
 347   public:
 348   typedef MemoryAlgorithm                memory_algorithm;
 349   typedef typename Base::void_pointer    void_pointer;
 350   typedef CharType                       char_type;
 351
 352   typedef segment_manager_base<MemoryAlgorithm>   segment_manager_base_type;
 353
 354   static const std::size_t PayloadPerAllocation = Base::PayloadPerAllocation;
 355
 356   /// @cond
 357   private:
 358   typedef detail::index_config<CharType, MemoryAlgorithm>  index_config_named;
 359   typedef detail::index_config<char, MemoryAlgorithm>      index_config_unique;
 360   typedef IndexType<index_config_named>                    index_type;
 361   typedef detail::bool_<is_intrusive_index<index_type>::value >    is_intrusive_t;
 362   typedef detail::bool_<is_node_index<index_type>::value>          is_node_index_t;
 363
 364   public:
 365   typedef IndexType<index_config_named>                    named_index_t;
 366   typedef IndexType<index_config_unique>                   unique_index_t;
 367   typedef detail::char_ptr_holder<CharType>                char_ptr_holder_t;
 368   typedef detail::segment_manager_iterator_transform
 369      <typename named_index_t::const_iterator
 370      ,is_intrusive_index<index_type>::value>   named_transform;
 371
 372   typedef detail::segment_manager_iterator_transform
 373      <typename unique_index_t::const_iterator
 374      ,is_intrusive_index<index_type>::value>   unique_transform;
 375   /// @endcond
 376
 377   typedef typename Base::mutex_family       mutex_family;
 378
 379   typedef transform_iterator
 380      <typename named_index_t::const_iterator, named_transform> const_named_iterator;
 381   typedef transform_iterator
 382      <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
 383
 384   /// @cond
 385
 386   //!Constructor proxy object definition helper class
 387   template<class T>
 388   struct construct_proxy
 389   {
 390      typedef detail::named_proxy<segment_manager, T, false>   type;
 391   };
 392
 393   //!Constructor proxy object definition helper class
 394   template<class T>
 395   struct construct_iter_proxy
 396   {
 397      typedef detail::named_proxy<segment_manager, T, true>   type;
 398   };
 399
 400   /// @endcond
 401
 402   //!Constructor of the segment manager
 403   //!"size" is the size of the memory segment where
 404   //!the segment manager is being constructed.
 405   //!Can throw
 406   segment_manager(std::size_t size)
 407      :  Base(size, priv_get_reserved_bytes())
 408      ,  m_header(static_cast<Base*>(get_this_pointer()))
 409   {
 410      (void) anonymous_instance;   (void) unique_instance;
 411      BOOST_ASSERT(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this)));
 412   }
 413
 414   //!Tries to find a previous named allocation. Returns the address
 415   //!and the object count. On failure the first member of the
 416   //!returned pair is 0.
 417   template <class T>
 418   std::pair<T*, std::size_t> find  (const CharType* name)
 419   {  return this->priv_find_impl<T>(name, true);  }
 420
 421   //!Tries to find a previous unique allocation. Returns the address
 422   //!and the object count. On failure the first member of the
 423   //!returned pair is 0.
 424   template <class T>
 425   std::pair<T*, std::size_t> find (const detail::unique_instance_t* name)
 426   {  return this->priv_find_impl<T>(name, true);  }
 427
 428   //!Tries to find a previous named allocation. Returns the address
 429   //!and the object count. On failure the first member of the
 430   //!returned pair is 0. This search is not mutex-protected!
 431   template <class T>
 432   std::pair<T*, std::size_t> find_no_lock  (const CharType* name)
 433   {  return this->priv_find_impl<T>(name, false);  }
 434
 435   //!Tries to find a previous unique allocation. Returns the address
 436   //!and the object count. On failure the first member of the
 437   //!returned pair is 0. This search is not mutex-protected!
 438   template <class T>
 439   std::pair<T*, std::size_t> find_no_lock (const detail::unique_instance_t* name)
 440   {  return this->priv_find_impl<T>(name, false);  }
 441
 442   //!Returns throwing "construct" proxy
 443   //!object
 444   template <class T>
 445   typename construct_proxy<T>::type      
 446      construct(char_ptr_holder_t name)
 447   {  return typename construct_proxy<T>::type (this, name, false, true);  }
 448
 449   //!Returns throwing "search or construct" proxy
 450   //!object
 451   template <class T>
 452   typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
 453   {  return typename construct_proxy<T>::type (this, name, true, true);  }
 454
 455   //!Returns no throwing "construct" proxy
 456   //!object
 457   template <class T>
 458   typename construct_proxy<T>::type
 459      construct(char_ptr_holder_t name, std::nothrow_t)
 460   {  return typename construct_proxy<T>::type (this, name, false, false);  }
 461
 462   //!Returns no throwing "search or construct"
 463   //!proxy object
 464   template <class T>
 465   typename construct_proxy<T>::type   
 466      find_or_construct(char_ptr_holder_t name, std::nothrow_t)
 467   {  return typename construct_proxy<T>::type (this, name, true, false);  }
 468
 469   //!Returns throwing "construct from iterators" proxy object
 470   template <class T>
 471   typename construct_iter_proxy<T>::type     
 472      construct_it(char_ptr_holder_t name)
 473   {  return typename construct_iter_proxy<T>::type (this, name, false, true);  }
 474
 475   //!Returns throwing "search or construct from iterators"
 476   //!proxy object
 477   template <class T>
 478   typename construct_iter_proxy<T>::type   
 479      find_or_construct_it(char_ptr_holder_t name)
 480   {  return typename construct_iter_proxy<T>::type (this, name, true, true);  }
 481
 482   //!Returns no throwing "construct from iterators"
 483   //!proxy object
 484   template <class T>
 485   typename construct_iter_proxy<T>::type   
 486      construct_it(char_ptr_holder_t name, std::nothrow_t)
 487   {  return typename construct_iter_proxy<T>::type (this, name, false, false);  }
 488
 489   //!Returns no throwing "search or construct from iterators"
 490   //!proxy object
 491   template <class T>
 492   typename construct_iter_proxy<T>::type 
 493      find_or_construct_it(char_ptr_holder_t name, std::nothrow_t)
 494   {  return typename construct_iter_proxy<T>::type (this, name, true, false);  }
 495
 496   //!Calls object function blocking recursive interprocess_mutex and guarantees that 
 497   //!no new named_alloc or destroy will be executed by any process while 
 498   //!executing the object function call*/
 499   template <class Func>
 500   void atomic_func(Func &f)
 501   {  scoped_lock<rmutex> guard(m_header);  f();  }
 502
 503   //!Tries to calls a functor guaranteeing that no new construction, search or
 504   //!destruction will be executed by any process while executing the object
 505   //!function call. If the atomic function can't be immediatelly executed
 506   //!because the internal mutex is already locked, returns false.
 507   //!If the functor throws, this function throws.
 508   template <class Func>
 509   bool try_atomic_func(Func &f)
 510   {
 511      scoped_lock<rmutex> guard(m_header, try_to_lock);
 512      if(guard){
 513         f();
 514         return true;
 515      }
 516      else{
 517         return false;
 518      }
 519   }
 520
 521   //!Destroys a previously created unique instance.
 522   //!Returns false if the object was not present.
 523   template <class T>
 524   bool destroy(const detail::unique_instance_t *)
 525   {
 526      detail::placement_destroy<T> dtor;
 527      return this->priv_generic_named_destroy<char>
 528         (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t());
 529   }
 530
 531   //!Destroys the named object with
 532   //!the given name. Returns false if that object can't be found.
 533   template <class T>
 534   bool destroy(const CharType *name)
 535   {
 536      detail::placement_destroy<T> dtor;
 537      return this->priv_generic_named_destroy<CharType>
 538               (name, m_header.m_named_index, dtor, is_intrusive_t());
 539   }
 540
 541   //!Destroys an anonymous, unique or named object
 542   //!using it's address
 543   template <class T>
 544   void destroy_ptr(const T *p)
 545   {
 546      //If T is void transform it to char
 547      typedef typename detail::char_if_void<T>::type data_t;
 548      detail::placement_destroy<data_t> dtor;
 549      priv_destroy_ptr(p, dtor);
 550   }
 551
 552   //!Returns the name of an object created with construct/find_or_construct
 553   //!functions. Does not throw
 554   template<class T>
 555   static const CharType *get_instance_name(const T *ptr)
 556   { return priv_get_instance_name(block_header_t::block_header_from_value(ptr));  }
 557
 558   //!Returns the length of an object created with construct/find_or_construct
 559   //!functions. Does not throw.
 560   template<class T>
 561   static std::size_t get_instance_length(const T *ptr)
 562   {  return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T));  }
 563
 564   //!Returns is the the name of an object created with construct/find_or_construct
 565   //!functions. Does not throw
 566   template<class T>
 567   static instance_type get_instance_type(const T *ptr)
 568   {  return priv_get_instance_type(block_header_t::block_header_from_value(ptr));  }
 569
 570   //!Preallocates needed index resources to optimize the 
 571   //!creation of "num" named objects in the managed memory segment.
 572   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
 573   void reserve_named_objects(std::size_t num)
 574   {  
 575      //-------------------------------
 576      scoped_lock<rmutex> guard(m_header);
 577      //-------------------------------
 578      m_header.m_named_index.reserve(num);  
 579   }
 580
 581   //!Preallocates needed index resources to optimize the 
 582   //!creation of "num" unique objects in the managed memory segment.
 583   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
 584   void reserve_unique_objects(std::size_t num)
 585   {  
 586      //-------------------------------
 587      scoped_lock<rmutex> guard(m_header);
 588      //-------------------------------
 589      m_header.m_unique_index.reserve(num);
 590   }
 591
 592   //!Calls shrink_to_fit in both named and unique object indexes
 593   //!to try to free unused memory from those indexes.
 594   void shrink_to_fit_indexes()
 595   {  
 596      //-------------------------------
 597      scoped_lock<rmutex> guard(m_header);
 598      //-------------------------------
 599      m_header.m_named_index.shrink_to_fit();  
 600      m_header.m_unique_index.shrink_to_fit();  
 601   }
 602
 603   //!Returns the number of named objects stored in
 604   //!the segment.
 605   std::size_t get_num_named_objects()
 606   {  
 607      //-------------------------------
 608      scoped_lock<rmutex> guard(m_header);
 609      //-------------------------------
 610      return m_header.m_named_index.size();  
 611   }
 612
 613   //!Returns the number of unique objects stored in
 614   //!the segment.
 615   std::size_t get_num_unique_objects()
 616   {  
 617      //-------------------------------
 618      scoped_lock<rmutex> guard(m_header);
 619      //-------------------------------
 620      return m_header.m_unique_index.size();  
 621   }
 622
 623   //!Obtains the minimum size needed by the
 624   //!segment manager
 625   static std::size_t get_min_size()
 626   {  return Base::get_min_size(priv_get_reserved_bytes());  }
 627
 628   //!Returns a constant iterator to the beginning of the information about
 629   //!the named allocations performed in this segment manager
 630   const_named_iterator named_begin() const
 631   {
 632      return make_transform_iterator
 633         (m_header.m_named_index.begin(), named_transform());
 634   }
 635
 636   //!Returns a constant iterator to the end of the information about
 637   //!the named allocations performed in this segment manager
 638   const_named_iterator named_end() const
 639   {
 640      return make_transform_iterator
 641         (m_header.m_named_index.end(), named_transform());
 642   }
 643
 644   //!Returns a constant iterator to the beginning of the information about
 645   //!the unique allocations performed in this segment manager
 646   const_unique_iterator unique_begin() const
 647   {
 648      return make_transform_iterator
 649         (m_header.m_unique_index.begin(), unique_transform());
 650   }
 651
 652   //!Returns a constant iterator to the end of the information about
 653   //!the unique allocations performed in this segment manager
 654   const_unique_iterator unique_end() const
 655   {
 656      return make_transform_iterator
 657         (m_header.m_unique_index.end(), unique_transform());
 658   }
 659
 660   //!This is the default allocator to allocate types T
 661   //!from this managed segment
 662   template<class T>
 663   struct allocator
 664   {
 665      typedef boost::interprocess::allocator<T, segment_manager> type;
 666   };
 667
 668   //!Returns an instance of the default allocator for type T
 669   //!initialized that allocates memory from this segment manager.
 670   template<class T>
 671   typename allocator<T>::type
 672      get_allocator()
 673   {   return typename allocator<T>::type(this); }
 674
 675   //!This is the default deleter to delete types T
 676   //!from this managed segment.
 677   template<class T>
 678   struct deleter
 679   {
 680      typedef boost::interprocess::deleter<T, segment_manager> type;
 681   };
 682
 683   //!Returns an instance of the default allocator for type T
 684   //!initialized that allocates memory from this segment manager.
 685   template<class T>
 686   typename deleter<T>::type
 687      get_deleter()
 688   {   return typename deleter<T>::type(this); }
 689
 690   /// @cond
 691
 692   //!Generic named/anonymous new function. Offers all the possibilities, 
 693   //!such as throwing, search before creating, and the constructor is 
 694   //!encapsulated in an object function.
 695   template<class T>
 696   T *generic_construct(const CharType *name, 
 697                         std::size_t num, 
 698                         bool try2find, 
 699                         bool dothrow,
 700                         detail::in_place_interface &table)
 701   {
 702      return static_cast<T*>
 703         (priv_generic_construct(name, num, try2find, dothrow, table));
 704   }
 705
 706   private:
 707   //!Tries to find a previous named allocation. Returns the address
 708   //!and the object count. On failure the first member of the
 709   //!returned pair is 0.
 710   template <class T>
 711   std::pair<T*, std::size_t> priv_find_impl (const CharType* name, bool lock)
 712   {  
 713      //The name can't be null, no anonymous object can be found by name
 714      BOOST_ASSERT(name != 0);
 715      detail::placement_destroy<T> table;
 716      std::size_t size;
 717      void *ret;
 718
 719      if(name == reinterpret_cast<const CharType*>(-1)){
 720         ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), lock);
 721      }
 722      else{
 723         ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), lock);
 724      }
 725      return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
 726   }
 727
 728   //!Tries to find a previous unique allocation. Returns the address
 729   //!and the object count. On failure the first member of the
 730   //!returned pair is 0.
 731   template <class T>
 732   std::pair<T*, std::size_t> priv_find__impl (const detail::unique_instance_t* name, bool lock)
 733   {
 734      detail::placement_destroy<T> table;
 735      std::size_t size;
 736      void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock); 
 737      return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
 738   }
 739
 740   void *priv_generic_construct(const CharType *name, 
 741                         std::size_t num, 
 742                         bool try2find, 
 743                         bool dothrow,
 744                         detail::in_place_interface &table)
 745   {
 746      void *ret;
 747      //Security overflow check
 748      if(num > ((std::size_t)-1)/table.size){
 749         if(dothrow)
 750            throw bad_alloc();
 751         else
 752            return 0;
 753      }
 754      if(name == 0){
 755         ret = this->prot_anonymous_construct(num, dothrow, table);
 756      }
 757      else if(name == reinterpret_cast<const CharType*>(-1)){
 758         ret = this->priv_generic_named_construct<char>
 759            (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t());
 760      }
 761      else{
 762         ret = this->priv_generic_named_construct<CharType>
 763            (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t());
 764      }
 765      return ret;
 766   }
 767
 768   void priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor)
 769   {
 770      block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
 771      switch(ctrl_data->alloc_type()){
 772         case anonymous_type:
 773            this->prot_anonymous_destroy(ptr, dtor);
 774         break;
 775
 776         case named_type:
 777            this->priv_generic_named_destroy<CharType>
 778               (ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
 779         break;
 780
 781         case unique_type:
 782            this->priv_generic_named_destroy<char>
 783               (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
 784         break;
 785
 786         default:
 787            //This type is unknown, bad pointer passed to this function!
 788            BOOST_ASSERT(0);
 789         break;
 790      }
 791   }
 792
 793   //!Returns the name of an object created with construct/find_or_construct
 794   //!functions. Does not throw
 795   static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
 796   {
 797      boost::interprocess::allocation_type type = ctrl_data->alloc_type();
 798      if(type != named_type){
 799         BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
 800                (type == unique_type    && ctrl_data->m_num_char != 0) );
 801         return 0;
 802      }
 803      CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
 804   
 805      //Sanity checks
 806      BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
 807      BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
 808      return name;
 809   }
 810
 811   static std::size_t priv_get_instance_length(block_header_t *ctrl_data, std::size_t sizeofvalue)
 812   {
 813      //Get header
 814      BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
 815      return ctrl_data->value_bytes()/sizeofvalue;
 816   }
 817
 818   //!Returns is the the name of an object created with construct/find_or_construct
 819   //!functions. Does not throw
 820   static instance_type priv_get_instance_type(block_header_t *ctrl_data)
 821   {
 822      //Get header
 823      BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
 824      return (instance_type)ctrl_data->alloc_type();
 825   }
 826
 827   static std::size_t priv_get_reserved_bytes()
 828   {
 829      //Get the number of bytes until the end of (*this)
 830      //beginning in the end of the Base base.
 831      return sizeof(segment_manager) - sizeof(Base);
 832   }
 833
 834   template <class CharT>
 835   void *priv_generic_find
 836      (const CharT* name, 
 837       IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 838       detail::in_place_interface &table,
 839       std::size_t &length,
 840       detail::true_ is_intrusive,
 841       bool use_lock)
 842   {
 843      (void)is_intrusive;
 844      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >         index_type;
 845      typedef detail::index_key<CharT, void_pointer>  index_key_t;
 846      typedef typename index_type::iterator           index_it;
 847
 848      //-------------------------------
 849      scoped_lock<rmutex> guard(priv_get_lock(use_lock));
 850      //-------------------------------
 851      //Find name in index
 852      detail::intrusive_compare_key<CharT> key
 853         (name, std::char_traits<CharT>::length(name));
 854      index_it it = index.find(key);
 855
 856      //Initialize return values
 857      void *ret_ptr  = 0;
 858      length         = 0;
 859
 860      //If found, assign values
 861      if(it != index.end()){
 862         //Get header
 863         block_header_t *ctrl_data = it->get_block_header();
 864
 865         //Sanity check
 866         BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
 867         BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
 868         ret_ptr  = ctrl_data->value();
 869         length  = ctrl_data->m_value_bytes/table.size;
 870      }
 871      return ret_ptr;
 872   }
 873
 874   template <class CharT>
 875   void *priv_generic_find
 876      (const CharT* name, 
 877       IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 878       detail::in_place_interface &table,
 879       std::size_t &length,
 880       detail::false_ is_intrusive,
 881       bool use_lock)
 882   {
 883      (void)is_intrusive;
 884      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >      index_type;
 885      typedef typename index_type::key_type        key_type;
 886      typedef typename index_type::iterator        index_it;
 887
 888      //-------------------------------
 889      scoped_lock<rmutex> guard(priv_get_lock(use_lock));
 890      //-------------------------------
 891      //Find name in index
 892      index_it it = index.find(key_type(name, std::char_traits<CharT>::length(name)));
 893
 894      //Initialize return values
 895      void *ret_ptr  = 0;
 896      length         = 0;
 897
 898      //If found, assign values
 899      if(it != index.end()){
 900         //Get header
 901         block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
 902                                    (detail::get_pointer(it->second.m_ptr));
 903
 904         //Sanity check
 905         BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
 906         BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
 907         ret_ptr  = ctrl_data->value();
 908         length  = ctrl_data->m_value_bytes/table.size;
 909      }
 910      return ret_ptr;
 911   }
 912
 913   template <class CharT>
 914   bool priv_generic_named_destroy
 915     (block_header_t *block_header,
 916      IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 917      detail::in_place_interface &table,
 918      detail::true_ is_node_index)
 919   {
 920      (void)is_node_index;
 921      typedef typename IndexType<detail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
 922
 923      index_it *ihdr = block_header_t::to_first_header<index_it>(block_header);
 924      return this->priv_generic_named_destroy_impl<CharT>(*ihdr, index, table);
 925   }
 926
 927   template <class CharT>
 928   bool priv_generic_named_destroy
 929     (block_header_t *block_header,
 930      IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 931      detail::in_place_interface &table,
 932      detail::false_ is_node_index)
 933   {
 934      (void)is_node_index;
 935      CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
 936      return this->priv_generic_named_destroy<CharT>(name, index, table, is_intrusive_t());
 937   }
 938
 939   template <class CharT>
 940   bool priv_generic_named_destroy(const CharT *name, 
 941                                   IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 942                                   detail::in_place_interface &table,
 943                                   detail::true_ is_intrusive_index)
 944   {
 945      (void)is_intrusive_index;
 946      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >         index_type;
 947      typedef detail::index_key<CharT, void_pointer>  index_key_t;
 948      typedef typename index_type::iterator           index_it;
 949      typedef typename index_type::value_type         intrusive_value_type;
 950      
 951      //-------------------------------
 952      scoped_lock<rmutex> guard(m_header);
 953      //-------------------------------
 954      //Find name in index
 955      detail::intrusive_compare_key<CharT> key
 956         (name, std::char_traits<CharT>::length(name));
 957      index_it it = index.find(key);
 958
 959      //If not found, return false
 960      if(it == index.end()){
 961         //This name is not present in the index, wrong pointer or name!
 962         //BOOST_ASSERT(0);
 963         return false;
 964      }
 965
 966      block_header_t *ctrl_data = it->get_block_header();
 967      intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
 968      void *memory = iv;
 969      void *values = ctrl_data->value();
 970      std::size_t num = ctrl_data->m_value_bytes/table.size;
 971      
 972      //Sanity check
 973      BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
 974      BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
 975
 976      //Erase node from index
 977      index.erase(it);
 978
 979      //Destroy the headers
 980      ctrl_data->~block_header_t();
 981      iv->~intrusive_value_type();
 982
 983      //Call destructors and free memory
 984      std::size_t destroyed;
 985      table.destroy_n(values, num, destroyed);
 986      this->deallocate(memory);
 987      return true;
 988   }
 989
 990   template <class CharT>
 991   bool priv_generic_named_destroy(const CharT *name, 
 992                                   IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
 993                                   detail::in_place_interface &table,
 994                                   detail::false_ is_intrusive_index)
 995   {
 996      (void)is_intrusive_index;
 997      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >            index_type;
 998      typedef typename index_type::iterator              index_it;
 999      typedef typename index_type::key_type              key_type;
1000
1001      //-------------------------------
1002      scoped_lock<rmutex> guard(m_header);
1003      //-------------------------------
1004      //Try to find the name in the index
1005      index_it it = index.find(key_type (name, 
1006                                     std::char_traits<CharT>::length(name)));
1007
1008      //If not found, return false
1009      if(it == index.end()){
1010         //This name is not present in the index, wrong pointer or name!
1011         //BOOST_ASSERT(0);
1012         return false;
1013      }
1014      return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
1015   }
1016
1017   template <class CharT>
1018   bool priv_generic_named_destroy_impl
1019      (const typename IndexType<detail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
1020      IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
1021      detail::in_place_interface &table)
1022   {
1023      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >      index_type;
1024      typedef typename index_type::iterator        index_it;
1025
1026      //Get allocation parameters
1027      block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
1028                                 (detail::get_pointer(it->second.m_ptr));
1029      char *stored_name       = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
1030      (void)stored_name;
1031
1032      //Check if the distance between the name pointer and the memory pointer 
1033      //is correct (this can detect incorrect type in destruction)
1034      std::size_t num = ctrl_data->m_value_bytes/table.size;
1035      void *values = ctrl_data->value();
1036
1037      //Sanity check
1038      BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
1039      BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
1040      BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
1041
1042      //Erase node from index
1043      index.erase(it);
1044
1045      //Destroy the header
1046      ctrl_data->~block_header_t();
1047
1048      void *memory;
1049      if(is_node_index_t::value){
1050         index_it *ihdr = block_header_t::
1051            to_first_header<index_it>(ctrl_data);
1052         ihdr->~index_it();
1053         memory = ihdr;
1054      }
1055      else{
1056         memory = ctrl_data;
1057      }
1058
1059      //Call destructors and free memory
1060      std::size_t destroyed;
1061      table.destroy_n(values, num, destroyed);
1062      this->deallocate(memory);
1063      return true;
1064   }
1065
1066   template<class CharT>
1067   void * priv_generic_named_construct(std::size_t type,
1068                               const CharT *name,
1069                               std::size_t num, 
1070                               bool try2find, 
1071                               bool dothrow,
1072                               detail::in_place_interface &table,
1073                               IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
1074                               detail::true_ is_intrusive)
1075   {
1076      (void)is_intrusive;
1077      std::size_t namelen  = std::char_traits<CharT>::length(name);
1078
1079      block_header_t block_info ( table.size*num
1080                                 , table.alignment
1081                                 , type
1082                                 , sizeof(CharT)
1083                                 , namelen);
1084
1085      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >            index_type;
1086      typedef typename index_type::iterator              index_it;
1087      typedef std::pair<index_it, bool>                  index_ib;
1088
1089      //-------------------------------
1090      scoped_lock<rmutex> guard(m_header);
1091      //-------------------------------
1092      //Insert the node. This can throw.
1093      //First, we want to know if the key is already present before
1094      //we allocate any memory, and if the key is not present, we 
1095      //want to allocate all memory in a single buffer that will
1096      //contain the name and the user buffer.
1097      //
1098      //Since equal_range(key) + insert(hint, value) approach is
1099      //quite inefficient in container implementations 
1100      //(they re-test if the position is correct), I've chosen
1101      //to insert the node, do an ugly un-const cast and modify
1102      //the key (which is a smart pointer) to an equivalent one
1103      index_ib insert_ret;
1104
1105      typename index_type::insert_commit_data   commit_data;
1106      typedef typename index_type::value_type   intrusive_value_type;
1107
1108      BOOST_TRY{
1109         detail::intrusive_compare_key<CharT> key(name, namelen);
1110         insert_ret = index.insert_check(key, commit_data);
1111      }
1112      //Ignore exceptions
1113      BOOST_CATCH(...){
1114         if(dothrow)
1115            BOOST_RETHROW
1116         return 0;
1117      }
1118      BOOST_CATCH_END
1119
1120      index_it it = insert_ret.first;
1121
1122      //If found and this is find or construct, return data
1123      //else return null
1124      if(!insert_ret.second){
1125         if(try2find){
1126            return it->get_block_header()->value();
1127         }
1128         if(dothrow){
1129            throw interprocess_exception(already_exists_error);
1130         }
1131         else{
1132            return 0;
1133         }
1134      }
1135
1136      //Allocates buffer for name + data, this can throw (it hurts)
1137      void *buffer_ptr; 
1138
1139      //Check if there is enough memory
1140      if(dothrow){
1141         buffer_ptr = this->allocate
1142            (block_info.total_size_with_header<intrusive_value_type>());
1143      }
1144      else{
1145         buffer_ptr = this->allocate
1146            (block_info.total_size_with_header<intrusive_value_type>(), std::nothrow_t());
1147         if(!buffer_ptr)
1148            return 0; 
1149      }
1150
1151      //Now construct the intrusive hook plus the header
1152      intrusive_value_type * intrusive_hdr = new(buffer_ptr) intrusive_value_type();
1153      block_header_t * hdr = new(intrusive_hdr->get_block_header())block_header_t(block_info);
1154      void *ptr = 0; //avoid gcc warning
1155      ptr = hdr->value();
1156
1157      //Copy name to memory segment and insert data
1158      CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1159      std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1160
1161      BOOST_TRY{
1162         //Now commit the insertion using previous context data
1163         it = index.insert_commit(*intrusive_hdr, commit_data);
1164      }
1165      //Ignore exceptions
1166      BOOST_CATCH(...){
1167         if(dothrow)
1168            BOOST_RETHROW
1169         return 0;
1170      }
1171      BOOST_CATCH_END
1172
1173      //Avoid constructions if constructor is trivial
1174      //Build scoped ptr to avoid leaks with constructor exception
1175      detail::mem_algo_deallocator<segment_manager_base_type> mem
1176         (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1177
1178      //Initialize the node value_eraser to erase inserted node
1179      //if something goes wrong. This will be executed *before*
1180      //the memory allocation as the intrusive value is built in that
1181      //memory
1182      value_eraser<index_type> v_eraser(index, it);
1183      
1184      //Construct array, this can throw
1185      detail::array_construct(ptr, num, table);
1186
1187      //Release rollbacks since construction was successful
1188      v_eraser.release();
1189      mem.release();
1190      return ptr;
1191   }
1192
1193   //!Generic named new function for
1194   //!named functions
1195   template<class CharT>
1196   void * priv_generic_named_construct(std::size_t type,  
1197                               const CharT *name,
1198                               std::size_t num, 
1199                               bool try2find, 
1200                               bool dothrow,
1201                               detail::in_place_interface &table,
1202                               IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
1203                               detail::false_ is_intrusive)
1204   {
1205      (void)is_intrusive;
1206      std::size_t namelen  = std::char_traits<CharT>::length(name);
1207
1208      block_header_t block_info ( table.size*num
1209                                 , table.alignment
1210                                 , type
1211                                 , sizeof(CharT)
1212                                 , namelen);
1213
1214      typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> >            index_type;
1215      typedef typename index_type::key_type              key_type;
1216      typedef typename index_type::mapped_type           mapped_type;
1217      typedef typename index_type::value_type            value_type;
1218      typedef typename index_type::iterator              index_it;
1219      typedef std::pair<index_it, bool>                  index_ib;
1220
1221      //-------------------------------
1222      scoped_lock<rmutex> guard(m_header);
1223      //-------------------------------
1224      //Insert the node. This can throw.
1225      //First, we want to know if the key is already present before
1226      //we allocate any memory, and if the key is not present, we 
1227      //want to allocate all memory in a single buffer that will
1228      //contain the name and the user buffer.
1229      //
1230      //Since equal_range(key) + insert(hint, value) approach is
1231      //quite inefficient in container implementations 
1232      //(they re-test if the position is correct), I've chosen
1233      //to insert the node, do an ugly un-const cast and modify
1234      //the key (which is a smart pointer) to an equivalent one
1235      index_ib insert_ret;
1236      BOOST_TRY{
1237         insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
1238      }
1239      //Ignore exceptions
1240      BOOST_CATCH(...){
1241         if(dothrow)
1242            BOOST_RETHROW;
1243         return 0;
1244      }
1245      BOOST_CATCH_END
1246
1247      index_it it = insert_ret.first;
1248
1249      //If found and this is find or construct, return data
1250      //else return null
1251      if(!insert_ret.second){
1252         if(try2find){
1253            block_header_t *hdr = static_cast<block_header_t*>
1254               (detail::get_pointer(it->second.m_ptr));
1255            return hdr->value();
1256         }
1257         return 0;
1258      }
1259      //Initialize the node value_eraser to erase inserted node
1260      //if something goes wrong
1261      value_eraser<index_type> v_eraser(index, it);
1262
1263      //Allocates buffer for name + data, this can throw (it hurts)
1264      void *buffer_ptr; 
1265      block_header_t * hdr;
1266
1267      //Allocate and construct the headers
1268      if(is_node_index_t::value){
1269         std::size_t total_size = block_info.total_size_with_header<index_it>();
1270         if(dothrow){
1271            buffer_ptr = this->allocate(total_size);
1272         }
1273         else{
1274            buffer_ptr = this->allocate(total_size, std::nothrow_t());
1275            if(!buffer_ptr)
1276               return 0; 
1277         }
1278         index_it *idr = new(buffer_ptr) index_it(it);
1279         hdr = block_header_t::from_first_header<index_it>(idr);
1280      }
1281      else{
1282         if(dothrow){
1283            buffer_ptr = this->allocate(block_info.total_size());
1284         }
1285         else{
1286            buffer_ptr = this->allocate(block_info.total_size(), std::nothrow_t());
1287            if(!buffer_ptr)
1288               return 0; 
1289         }
1290         hdr = static_cast<block_header_t*>(buffer_ptr);
1291      }
1292
1293      hdr = new(hdr)block_header_t(block_info);
1294      void *ptr = 0; //avoid gcc warning
1295      ptr = hdr->value();
1296
1297      //Copy name to memory segment and insert data
1298      CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1299      std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1300
1301      //Do the ugly cast, please mama, forgive me!
1302      //This new key points to an identical string, so it must have the 
1303      //same position than the overwritten key according to the predicate
1304      const_cast<key_type &>(it->first).name(name_ptr);
1305      it->second.m_ptr  = hdr;
1306
1307      //Build scoped ptr to avoid leaks with constructor exception
1308      detail::mem_algo_deallocator<segment_manager_base_type> mem
1309         (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1310
1311      //Construct array, this can throw
1312      detail::array_construct(ptr, num, table);
1313
1314      //All constructors successful, we don't want to release memory
1315      mem.release();
1316
1317      //Release node v_eraser since construction was successful
1318      v_eraser.release();
1319      return ptr;
1320   }
1321
1322   private:
1323   //!Returns the this pointer
1324   segment_manager *get_this_pointer()
1325   {  return this;  }
1326
1327   typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type   rmutex;
1328
1329   scoped_lock<rmutex> priv_get_lock(bool use_lock)
1330   {
1331      scoped_lock<rmutex> local(m_header, defer_lock);
1332      if(use_lock){
1333         local.lock();
1334      }
1335      return scoped_lock<rmutex>(boost::interprocess::move(local));
1336   }
1337
1338   //!This struct includes needed data and derives from
1339   //!rmutex to allow EBO when using null interprocess_mutex
1340   struct header_t
1341      :  public rmutex
1342   {
1343      named_index_t           m_named_index;
1344      unique_index_t          m_unique_index;
1345   
1346      header_t(Base *restricted_segment_mngr)
1347

Large files files are truncated, but you can click here to view the full file