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