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