PageRenderTime 83ms CodeModel.GetById 21ms app.highlight 54ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/interprocess/detail/managed_memory_impl.hpp

http://hadesmem.googlecode.com/
C++ Header | 752 lines | 335 code | 95 blank | 322 comment | 17 complexity | 41324236962c21f2be1ad6775974930f MD5 | raw 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_DETAIL_MANAGED_MEMORY_IMPL_HPP
 12#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_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/interprocess/interprocess_fwd.hpp>
 22#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
 23#include <boost/interprocess/sync/mutex_family.hpp>
 24#include <boost/interprocess/detail/utilities.hpp>
 25#include <boost/interprocess/detail/os_file_functions.hpp>
 26#include <boost/interprocess/creation_tags.hpp>
 27#include <boost/interprocess/sync/interprocess_mutex.hpp>
 28#include <boost/interprocess/exceptions.hpp>
 29#include <boost/interprocess/offset_ptr.hpp>
 30#include <boost/interprocess/segment_manager.hpp>
 31#include <boost/interprocess/sync/scoped_lock.hpp>
 32//
 33#include <boost/detail/no_exceptions_support.hpp>
 34//
 35#include <utility>
 36#include <fstream>
 37#include <new>
 38#include <boost/assert.hpp>
 39
 40//!\file
 41//!Describes a named shared memory allocation user class. 
 42//!
 43
 44namespace boost {
 45namespace interprocess {
 46namespace detail {
 47
 48template<class BasicManagedMemoryImpl>
 49class create_open_func;
 50
 51template<
 52         class CharType, 
 53         class MemoryAlgorithm,
 54         template<class IndexConfig> class IndexType
 55        >
 56struct segment_manager_type
 57{
 58   typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
 59};
 60
 61//!This class is designed to be a base class to classes that manage 
 62//!creation of objects in a fixed size memory buffer. Apart 
 63//!from allocating raw memory, the user can construct named objects. To 
 64//!achieve this, this class uses the reserved space provided by the allocation
 65//!algorithm to place a named_allocator_algo, who takes care of name mappings.
 66//!The class can be customized with the char type used for object names
 67//!and the memory allocation algorithm to be used.*/
 68template <  class CharType 
 69         ,  class MemoryAlgorithm
 70         ,  template<class IndexConfig> class IndexType
 71         ,  std::size_t Offset = 0
 72         >
 73class basic_managed_memory_impl
 74{
 75   //Non-copyable
 76   basic_managed_memory_impl(const basic_managed_memory_impl &);
 77   basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
 78
 79   template<class BasicManagedMemoryImpl>
 80   friend class create_open_func;
 81
 82   public:
 83   typedef typename segment_manager_type
 84      <CharType, MemoryAlgorithm, IndexType>::type    segment_manager;
 85   typedef CharType                                   char_type;
 86   typedef MemoryAlgorithm                            memory_algorithm;
 87   typedef typename MemoryAlgorithm::mutex_family     mutex_family;
 88   typedef CharType                                   char_t;
 89   typedef std::ptrdiff_t                             handle_t;
 90   typedef typename segment_manager::
 91      const_named_iterator                            const_named_iterator;
 92   typedef typename segment_manager::
 93      const_unique_iterator                           const_unique_iterator;
 94
 95   /// @cond
 96
 97   typedef typename 
 98           segment_manager::char_ptr_holder_t         char_ptr_holder_t;
 99   //Experimental. Don't use.
100
101   typedef typename segment_manager::multiallocation_chain  multiallocation_chain;
102
103   /// @endcond
104
105   static const std::size_t PayloadPerAllocation = segment_manager::PayloadPerAllocation;
106
107   private:
108   typedef basic_managed_memory_impl
109               <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
110   protected:
111   template<class ManagedMemory>
112   static bool grow(const char *filename, std::size_t extra_bytes)
113   {
114      typedef typename ManagedMemory::device_type device_type;
115      //Increase file size
116      try{
117         offset_t old_size;
118         {
119            device_type f(open_or_create, filename, read_write);
120            if(!f.get_size(old_size))
121               return false;
122            f.truncate(old_size + extra_bytes);
123         }
124         ManagedMemory managed_memory(open_only, filename);
125         //Grow always works
126         managed_memory.self_t::grow(extra_bytes);
127      }
128      catch(...){
129         return false;
130      }
131      return true;
132   }
133
134   template<class ManagedMemory>
135   static bool shrink_to_fit(const char *filename)
136   {
137      typedef typename ManagedMemory::device_type device_type;
138      std::size_t new_size, old_size;
139      try{
140         ManagedMemory managed_memory(open_only, filename);
141         old_size = managed_memory.get_size();
142         managed_memory.self_t::shrink_to_fit();
143         new_size = managed_memory.get_size();
144      }
145      catch(...){
146         return false;
147      }
148
149      //Decrease file size
150      {
151         device_type f(open_or_create, filename, read_write);
152         f.truncate(new_size);
153      }
154      return true;
155   }
156
157   //!Constructor. Allocates basic resources. Never throws.
158   basic_managed_memory_impl() 
159      : mp_header(0){}
160
161   //!Destructor. Calls close. Never throws.
162   ~basic_managed_memory_impl()
163   {  this->close_impl(); }
164
165   //!Places segment manager in the reserved space. This can throw.
166   bool  create_impl   (void *addr, std::size_t size)
167   {
168      if(mp_header)  return false;
169
170      //Check if there is enough space
171      if(size < segment_manager::get_min_size())
172         return false;
173
174      //This function should not throw. The index construction can 
175      //throw if constructor allocates memory. So we must catch it.
176      BOOST_TRY{
177         //Let's construct the allocator in memory            
178         mp_header       = new(addr) segment_manager(size);
179      }
180      BOOST_CATCH(...){
181         return false;
182      }
183      BOOST_CATCH_END
184      return true;    
185   }
186 
187   //!Connects to a segment manager in the reserved buffer. Never throws.
188   bool  open_impl     (void *addr, std::size_t)
189   {
190      if(mp_header)  return false;
191      mp_header = static_cast<segment_manager*>(addr);
192      return true;
193   }
194
195   //!Frees resources. Never throws.
196   bool close_impl()
197   {  
198      bool ret = mp_header != 0;
199      mp_header = 0;
200      return ret;
201   }
202
203   //!Frees resources and destroys common resources. Never throws.
204   bool destroy_impl()
205   {
206      if(mp_header == 0)
207         return false;
208      mp_header->~segment_manager();
209      this->close_impl();
210         return true;
211   }
212
213   //!
214   void grow(std::size_t extra_bytes)
215   {  mp_header->grow(extra_bytes); }
216
217   void shrink_to_fit()
218   {  mp_header->shrink_to_fit(); }
219
220   public:
221
222   //!Returns segment manager. Never throws.
223   segment_manager *get_segment_manager() const
224   {   return mp_header; }
225
226   //!Returns the base address of the memory in this process. Never throws.
227   void *   get_address   () const
228   {   return reinterpret_cast<char*>(mp_header) - Offset; }
229
230   //!Returns the size of memory segment. Never throws.
231   std::size_t   get_size   () const
232   {   return mp_header->get_size() + Offset;  }
233
234   //!Returns the number of free bytes of the memory
235   //!segment
236   std::size_t get_free_memory() const
237   {  return mp_header->get_free_memory();  }
238
239   //!Returns the result of "all_memory_deallocated()" function
240   //!of the used memory algorithm
241   bool all_memory_deallocated()
242   {   return mp_header->all_memory_deallocated(); }
243
244   //!Returns the result of "check_sanity()" function
245   //!of the used memory algorithm
246   bool check_sanity()
247   {   return mp_header->check_sanity(); }
248
249   //!Writes to zero free memory (memory not yet allocated) of
250   //!the memory algorithm
251   void zero_free_memory()
252   {   mp_header->zero_free_memory(); }
253
254   //!Transforms an absolute address into an offset from base address. 
255   //!The address must belong to the memory segment. Never throws.
256   handle_t get_handle_from_address   (const void *ptr) const
257   {
258      return reinterpret_cast<const char*>(ptr) - 
259             reinterpret_cast<const char*>(this->get_address());  
260   }
261
262   //!Returns true if the address belongs to the managed memory segment
263   bool belongs_to_segment (const void *ptr) const
264   {  
265      return ptr >= this->get_address() && 
266             ptr <  (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
267   }
268
269   //!Transforms previously obtained offset into an absolute address in the 
270   //!process space of the current process. Never throws.*/
271   void *    get_address_from_handle (handle_t offset) const
272   {  return reinterpret_cast<char*>(this->get_address()) + offset; }
273
274   //!Searches for nbytes of free memory in the segment, marks the
275   //!memory as used and return the pointer to the memory. If no 
276   //!memory is available throws a boost::interprocess::bad_alloc exception
277   void* allocate             (std::size_t nbytes)
278   {   return mp_header->allocate(nbytes);   }
279
280   //!Searches for nbytes of free memory in the segment, marks the 
281   //!memory as used and return the pointer to the memory. If no memory 
282   //!is available returns 0. Never throws.
283   void* allocate             (std::size_t nbytes, std::nothrow_t nothrow)
284   {   return mp_header->allocate(nbytes, nothrow);  }
285
286   //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
287   //!must be power of two. If no memory 
288   //!is available returns 0. Never throws.
289   void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t nothrow)
290   {   return mp_header->allocate_aligned(nbytes, alignment, nothrow);  }
291
292   template<class T>
293   std::pair<T *, bool>
294      allocation_command  (boost::interprocess::allocation_type command,   std::size_t limit_size,
295                           std::size_t preferred_size,std::size_t &received_size,
296                           T *reuse_ptr = 0)
297   {  
298      return mp_header->allocation_command
299         (command, limit_size, preferred_size, received_size, reuse_ptr);
300   }
301
302   //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
303   //!must be power of two. If no 
304   //!memory is available throws a boost::interprocess::bad_alloc exception
305   void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
306   {   return mp_header->allocate_aligned(nbytes, alignment);  }
307
308   /// @cond
309
310   //Experimental. Don't use.
311
312   //!Allocates n_elements of elem_size bytes.
313   multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
314   {  return mp_header->allocate_many(elem_bytes, num_elements); }
315
316   //!Allocates n_elements, each one of elem_sizes[i] bytes.
317   multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements)
318   {  return mp_header->allocate_many(elem_sizes, n_elements); }
319
320   //!Allocates n_elements of elem_size bytes.
321   multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t nothrow)
322   {  return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
323
324   //!Allocates n_elements, each one of elem_sizes[i] bytes.
325   multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::nothrow_t nothrow)
326   {  return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
327
328   //!Allocates n_elements, each one of elem_sizes[i] bytes.
329   void deallocate_many(multiallocation_chain chain)
330   {  return mp_header->deallocate_many(boost::interprocess::move(chain)); }
331
332   /// @endcond
333
334   //!Marks previously allocated memory as free. Never throws.
335   void  deallocate           (void *addr)
336   {   if (mp_header) mp_header->deallocate(addr);  }
337
338   //!Tries to find a previous named allocation address. Returns a memory
339   //!buffer and the object count. If not found returned pointer is 0.
340   //!Never throws.
341   template <class T>
342   std::pair<T*, std::size_t> find  (char_ptr_holder_t name)
343   {   return mp_header->template find<T>(name); }
344
345   //!Creates a named object or array in memory
346   //!
347   //!Allocates and constructs a T object or an array of T in memory, 
348   //!associates this with the given name and returns a pointer to the 
349   //!created object. If an array is being constructed all objects are
350   //!created using the same parameters given to this function.
351   //!
352   //!-> If the name was previously used, returns 0.
353   //!
354   //!-> Throws boost::interprocess::bad_alloc if there is no available memory 
355   //!
356   //!-> If T's constructor throws, the function throws that exception.
357   //!
358   //!Memory is freed automatically if T's constructor throws and if an 
359   //!array was being constructed, destructors of created objects are called
360   //!before freeing the memory.
361   template <class T>
362   typename segment_manager::template construct_proxy<T>::type
363      construct(char_ptr_holder_t name)
364   {   return mp_header->template construct<T>(name);  }
365
366   //!Finds or creates a named object or array in memory
367   //!
368   //!Tries to find an object with the given name in memory. If 
369   //!found, returns the pointer to this pointer. If the object is not found, 
370   //!allocates and constructs a T object or an array of T in memory, 
371   //!associates this with the given name and returns a pointer to the 
372   //!created object. If an array is being constructed all objects are
373   //!created using the same parameters given to this function.
374   //!
375   //!-> Throws boost::interprocess::bad_alloc if there is no available memory 
376   //!
377   //!-> If T's constructor throws, the function throws that exception.
378   //!
379   //!Memory is freed automatically if T's constructor throws and if an 
380   //!array was being constructed, destructors of created objects are called
381   //!before freeing the memory.
382   template <class T>
383   typename segment_manager::template construct_proxy<T>::type
384      find_or_construct(char_ptr_holder_t name)
385   {   return mp_header->template find_or_construct<T>(name);  }
386
387   //!Creates a named object or array in memory
388   //!
389   //!Allocates and constructs a T object or an array of T in memory, 
390   //!associates this with the given name and returns a pointer to the 
391   //!created object. If an array is being constructed all objects are
392   //!created using the same parameters given to this function.
393   //!
394   //!-> If the name was previously used, returns 0.
395   //!
396   //!-> Returns 0 if there is no available memory 
397   //!
398   //!-> If T's constructor throws, the function throws that exception.
399   //!
400   //!Memory is freed automatically if T's constructor throws and if an 
401   //!array was being constructed, destructors of created objects are called
402   //!before freeing the memory.
403   template <class T>
404   typename segment_manager::template construct_proxy<T>::type
405      construct(char_ptr_holder_t name, std::nothrow_t nothrow)
406   {   return mp_header->template construct<T>(name, nothrow);  }
407
408   //!Finds or creates a named object or array in memory
409   //!
410   //!Tries to find an object with the given name in memory. If 
411   //!found, returns the pointer to this pointer. If the object is not found, 
412   //!allocates and constructs a T object or an array of T in memory, 
413   //!associates this with the given name and returns a pointer to the 
414   //!created object. If an array is being constructed all objects are
415   //!created using the same parameters given to this function.
416   //!
417   //!-> Returns 0 if there is no available memory 
418   //!
419   //!-> If T's constructor throws, the function throws that exception.
420   //!
421   //!Memory is freed automatically if T's constructor throws and if an 
422   //!array was being constructed, destructors of created objects are called
423   //!before freeing the memory.
424   template <class T>
425   typename segment_manager::template construct_proxy<T>::type
426      find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
427   {   return mp_header->template find_or_construct<T>(name, nothrow);  }
428
429   //!Creates a named array from iterators in memory 
430   //!
431   //!Allocates and constructs an array of T in memory, 
432   //!associates this with the given name and returns a pointer to the 
433   //!created object. Each element in the array is created using the
434   //!objects returned when dereferencing iterators as parameters
435   //!and incrementing all iterators for each element.
436   //!
437   //!-> If the name was previously used, returns 0.
438   //!
439   //!-> Throws boost::interprocess::bad_alloc if there is no available memory 
440   //!
441   //!-> If T's constructor throws, the function throws that exception.
442   //!
443   //!Memory is freed automatically if T's constructor throws and 
444   //!destructors of created objects are called before freeing the memory.
445   template <class T>
446   typename segment_manager::template construct_iter_proxy<T>::type
447      construct_it(char_ptr_holder_t name)
448   {   return mp_header->template construct_it<T>(name);  }
449
450   //!Finds or creates a named array from iterators in memory 
451   //!
452   //!Tries to find an object with the given name in memory. If 
453   //!found, returns the pointer to this pointer. If the object is not found, 
454   //!allocates and constructs an array of T in memory, 
455   //!associates this with the given name and returns a pointer to the 
456   //!created object. Each element in the array is created using the
457   //!objects returned when dereferencing iterators as parameters
458   //!and incrementing all iterators for each element.
459   //!
460   //!-> If the name was previously used, returns 0.
461   //!
462   //!-> Throws boost::interprocess::bad_alloc if there is no available memory 
463   //!
464   //!-> If T's constructor throws, the function throws that exception.
465   //!
466   //!Memory is freed automatically if T's constructor throws and 
467   //!destructors of created objects are called before freeing the memory.
468   template <class T>
469   typename segment_manager::template construct_iter_proxy<T>::type
470      find_or_construct_it(char_ptr_holder_t name)
471   {   return mp_header->template find_or_construct_it<T>(name);  }
472
473   //!Creates a named array from iterators in memory 
474   //!
475   //!Allocates and constructs an array of T in memory, 
476   //!associates this with the given name and returns a pointer to the 
477   //!created object. Each element in the array is created using the
478   //!objects returned when dereferencing iterators as parameters
479   //!and incrementing all iterators for each element.
480   //!
481   //!-> If the name was previously used, returns 0.
482   //!
483   //!-> If there is no available memory, returns 0.
484   //!
485   //!-> If T's constructor throws, the function throws that exception.
486   //!
487   //!Memory is freed automatically if T's constructor throws and 
488   //!destructors of created objects are called before freeing the memory.*/
489   template <class T>
490   typename segment_manager::template construct_iter_proxy<T>::type
491      construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
492   {   return mp_header->template construct_it<T>(name, nothrow);  }
493
494   //!Finds or creates a named array from iterators in memory 
495   //!
496   //!Tries to find an object with the given name in memory. If 
497   //!found, returns the pointer to this pointer. If the object is not found, 
498   //!allocates and constructs an array of T in memory, 
499   //!associates this with the given name and returns a pointer to the 
500   //!created object. Each element in the array is created using the
501   //!objects returned when dereferencing iterators as parameters
502   //!and incrementing all iterators for each element.
503   //!
504   //!-> If the name was previously used, returns 0.
505   //!
506   //!-> If there is no available memory, returns 0.
507   //!
508   //!-> If T's constructor throws, the function throws that exception.
509   //!
510   //!Memory is freed automatically if T's constructor throws and 
511   //!destructors of created objects are called before freeing the memory.*/
512   template <class T>
513   typename segment_manager::template construct_iter_proxy<T>::type
514      find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
515   {   return mp_header->template find_or_construct_it<T>(name, nothrow);  }
516
517   //!Calls a functor and guarantees that no new construction, search or
518   //!destruction will be executed by any process while executing the object
519   //!function call. If the functor throws, this function throws.
520   template <class Func>
521   void atomic_func(Func &f)
522   {   mp_header->atomic_func(f);  }
523
524   //!Tries to call a functor guaranteeing that no new construction, search or
525   //!destruction will be executed by any process while executing the object
526   //!function call. If the atomic function can't be immediatelly executed
527   //!because the internal mutex is already locked, returns false.
528   //!If the functor throws, this function throws.
529   template <class Func>
530   bool try_atomic_func(Func &f)
531   {   return mp_header->try_atomic_func(f); }
532
533   //!Destroys a named memory object or array.
534   //!
535   //!Finds the object with the given name, calls its destructors,
536   //!frees used memory and returns true.
537   //!
538   //!-> If the object is not found, it returns false.
539   //!
540   //!Exception Handling:
541   //!
542   //!When deleting a dynamically object or array, the Standard 
543   //!does not guarantee that dynamically allocated memory, will be released.
544   //!Also, when deleting arrays, the Standard doesn't require calling 
545   //!destructors for the rest of the objects if for one of them the destructor 
546   //!terminated with an exception. 
547   //!
548   //!Destroying an object:
549   //!
550   //!If the destructor throws, the memory will be freed and that exception
551   //!will be thrown.
552   //!
553   //!Destroying an array:
554   //!
555   //!When destroying an array, if a destructor throws, the rest of 
556   //!destructors are called. If any of these throws, the exceptions are
557   //!ignored. The name association will be erased, memory will be freed and
558   //!the first exception will be thrown. This guarantees the unlocking of
559   //!mutexes and other resources.
560   //!
561   //!For all theses reasons, classes with throwing destructors are not 
562   //!recommended.
563   template <class T>
564   bool destroy(const CharType *name)
565   {   return mp_header->template destroy<T>(name); }
566
567   //!Destroys the unique instance of type T
568   //!
569   //!Calls the destructor, frees used memory and returns true.
570   //!
571   //!Exception Handling:
572   //!
573   //!When deleting a dynamically object, the Standard does not 
574   //!guarantee that dynamically allocated memory will be released.
575   //!
576   //!Destroying an object:
577   //!
578   //!If the destructor throws, the memory will be freed and that exception
579   //!will be thrown.
580   //!
581   //!For all theses reasons, classes with throwing destructors are not 
582   //!recommended for  memory.
583   template <class T>
584   bool destroy(const detail::unique_instance_t *const )
585   {   return mp_header->template destroy<T>(unique_instance);  }
586
587   //!Destroys the object (named, unique, or anonymous)
588   //!
589   //!Calls the destructor, frees used memory and returns true.
590   //!
591   //!Exception Handling:
592   //!
593   //!When deleting a dynamically object, the Standard does not 
594   //!guarantee that dynamically allocated memory will be released.
595   //!
596   //!Destroying an object:
597   //!
598   //!If the destructor throws, the memory will be freed and that exception
599   //!will be thrown.
600   //!
601   //!For all theses reasons, classes with throwing destructors are not 
602   //!recommended for  memory.
603   template <class T>
604   void destroy_ptr(const T *ptr)
605   {  mp_header->template destroy_ptr<T>(ptr); }
606
607   //!Returns the name of an object created with construct/find_or_construct
608   //!functions. Does not throw
609   template<class T>
610   static const char_type *get_instance_name(const T *ptr)
611   {  return segment_manager::get_instance_name(ptr);   }
612
613   //!Returns is the type an object created with construct/find_or_construct
614   //!functions. Does not throw.
615   template<class T>
616   static instance_type get_instance_type(const T *ptr)
617   {  return segment_manager::get_instance_type(ptr); }
618
619   //!Returns the length of an object created with construct/find_or_construct
620   //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
621   template<class T>
622   static std::size_t get_instance_length(const T *ptr)
623   {  return segment_manager::get_instance_length(ptr); }
624
625   //!Preallocates needed index resources to optimize the 
626   //!creation of "num" named objects in the  memory segment.
627   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
628   void reserve_named_objects(std::size_t num)
629   {  mp_header->reserve_named_objects(num);  }
630
631   //!Preallocates needed index resources to optimize the 
632   //!creation of "num" unique objects in the  memory segment.
633   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
634   void reserve_unique_objects(std::size_t num)
635   {  mp_header->reserve_unique_objects(num);  }
636
637   //!Calls shrink_to_fit in both named and unique object indexes
638   //to try to free unused memory from those indexes.
639   void shrink_to_fit_indexes()
640   {  mp_header->shrink_to_fit_indexes();  }
641
642   //!Returns the number of named objects stored
643   //!in the managed segment.
644   std::size_t get_num_named_objects()
645   {  return mp_header->get_num_named_objects();  }
646
647   //!Returns the number of unique objects stored
648   //!in the managed segment.
649   std::size_t get_num_unique_objects()
650   {  return mp_header->get_num_unique_objects();  }
651
652   //!Returns a constant iterator to the index storing the
653   //!named allocations. NOT thread-safe. Never throws.
654   const_named_iterator named_begin() const
655   {  return mp_header->named_begin(); }
656
657   //!Returns a constant iterator to the end of the index 
658   //!storing the named allocations. NOT thread-safe. Never throws.
659   const_named_iterator named_end() const
660   {  return mp_header->named_end(); }
661
662   //!Returns a constant iterator to the index storing the
663   //!unique allocations. NOT thread-safe. Never throws.
664   const_unique_iterator unique_begin() const
665   {  return mp_header->unique_begin(); }
666
667   //!Returns a constant iterator to the end of the index 
668   //!storing the unique allocations. NOT thread-safe. Never throws.
669   const_unique_iterator unique_end() const
670   {  return mp_header->unique_end(); }
671
672   //!This is the default allocator to allocate types T
673   //!from this managed segment
674   template<class T>
675   struct allocator
676   {
677      typedef typename segment_manager::template allocator<T>::type type;
678   };
679
680   //!Returns an instance of the default allocator for type T
681   //!initialized that allocates memory from this segment manager.
682   template<class T>
683   typename allocator<T>::type
684      get_allocator()
685   {   return mp_header->template get_allocator<T>(); }
686
687   //!This is the default deleter to delete types T
688   //!from this managed segment.
689   template<class T>
690   struct deleter
691   {
692      typedef typename segment_manager::template deleter<T>::type type;
693   };
694
695   //!Returns an instance of the default allocator for type T
696   //!initialized that allocates memory from this segment manager.
697   template<class T>
698   typename deleter<T>::type
699      get_deleter()
700   {   return mp_header->template get_deleter<T>(); }
701
702   /// @cond
703   //!Tries to find a previous named allocation address. Returns a memory
704   //!buffer and the object count. If not found returned pointer is 0.
705   //!Never throws.
706   template <class T>
707   std::pair<T*, std::size_t> find_no_lock  (char_ptr_holder_t name)
708   {   return mp_header->template find_no_lock<T>(name); }
709   /// @endcond
710
711   protected:
712   //!Swaps the segment manager's managed by this managed memory segment.
713   //!NOT thread-safe. Never throws.
714   void swap(basic_managed_memory_impl &other)
715   {  std::swap(mp_header, other.mp_header); }
716
717   private:
718   segment_manager *mp_header;
719};
720
721template<class BasicManagedMemoryImpl>
722class create_open_func
723{
724   public:
725   create_open_func(BasicManagedMemoryImpl * const frontend, detail::create_enum_t type)
726      : m_frontend(frontend), m_type(type){}
727
728   bool operator()(void *addr, std::size_t size, bool created) const
729   {  
730      if(((m_type == detail::DoOpen)   &&  created) || 
731         ((m_type == detail::DoCreate) && !created))
732         return false;
733
734      if(created)
735         return m_frontend->create_impl(addr, size);
736      else
737         return m_frontend->open_impl  (addr, size);
738   }
739
740   private:
741   BasicManagedMemoryImpl *m_frontend;
742   detail::create_enum_t           m_type;
743};
744
745}  //namespace detail {
746}  //namespace interprocess {
747}  //namespace boost {
748
749#include <boost/interprocess/detail/config_end.hpp>
750
751#endif   //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
752