Imported Upstream version 1.49.0
[platform/upstream/boost.git] / boost / interprocess / allocators / allocator.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2011. 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_ALLOCATOR_HPP
12 #define BOOST_INTERPROCESS_ALLOCATOR_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/intrusive/pointer_traits.hpp>
22
23 #include <boost/interprocess/interprocess_fwd.hpp>
24 #include <boost/interprocess/containers/allocation_type.hpp>
25 #include <boost/container/detail/multiallocation_chain.hpp>
26 #include <boost/interprocess/allocators/detail/allocator_common.hpp>
27 #include <boost/interprocess/detail/utilities.hpp>
28 #include <boost/interprocess/containers/version_type.hpp>
29 #include <boost/interprocess/exceptions.hpp>
30 #include <boost/assert.hpp>
31 #include <boost/utility/addressof.hpp>
32 #include <boost/interprocess/detail/type_traits.hpp>
33
34 #include <memory>
35 #include <new>
36 #include <algorithm>
37 #include <cstddef>
38 #include <stdexcept>
39
40 //!\file
41 //!Describes an allocator that allocates portions of fixed size
42 //!memory buffer (shared memory, mapped file...)
43
44 namespace boost {
45 namespace interprocess {
46
47
48 //!An STL compatible allocator that uses a segment manager as 
49 //!memory source. The internal pointer type will of the same type (raw, smart) as
50 //!"typename SegmentManager::void_pointer" type. This allows
51 //!placing the allocator in shared memory, memory mapped-files, etc...
52 template<class T, class SegmentManager>
53 class allocator 
54 {
55    public:
56    //Segment manager
57    typedef SegmentManager                                segment_manager;
58    typedef typename SegmentManager::void_pointer         void_pointer;
59
60    /// @cond
61    private:
62
63    //Self type
64    typedef allocator<T, SegmentManager>   self_t;
65
66    //Pointer to void
67    typedef typename segment_manager::void_pointer  aux_pointer_t;
68
69    //Typedef to const void pointer
70    typedef typename boost::intrusive::
71       pointer_traits<aux_pointer_t>::template
72          rebind_pointer<const void>::type          cvoid_ptr;
73
74    //Pointer to the allocator
75    typedef typename boost::intrusive::
76       pointer_traits<cvoid_ptr>::template
77          rebind_pointer<segment_manager>::type          alloc_ptr_t;
78
79    //Not assignable from related allocator
80    template<class T2, class SegmentManager2>
81    allocator& operator=(const allocator<T2, SegmentManager2>&);
82
83    //Not assignable from other allocator
84    allocator& operator=(const allocator&);
85
86    //Pointer to the allocator
87    alloc_ptr_t mp_mngr;
88    /// @endcond
89
90    public:
91    typedef T                                    value_type;
92    typedef typename boost::intrusive::
93       pointer_traits<cvoid_ptr>::template
94          rebind_pointer<T>::type                pointer;
95    typedef typename boost::intrusive::
96       pointer_traits<pointer>::template
97          rebind_pointer<const T>::type          const_pointer;
98    typedef typename ipcdetail::add_reference
99                      <value_type>::type         reference;
100    typedef typename ipcdetail::add_reference
101                      <const value_type>::type   const_reference;
102    typedef typename segment_manager::size_type               size_type;
103    typedef typename segment_manager::difference_type         difference_type;
104
105    typedef boost::interprocess::version_type<allocator, 2>   version;
106
107    /// @cond
108
109    //Experimental. Don't use.
110    typedef boost::container::container_detail::transform_multiallocation_chain
111       <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
112    /// @endcond
113
114    //!Obtains an allocator that allocates
115    //!objects of type T2
116    template<class T2>
117    struct rebind
118    {   
119       typedef allocator<T2, SegmentManager>     other;
120    };
121
122    //!Returns the segment manager.
123    //!Never throws
124    segment_manager* get_segment_manager()const
125    {  return ipcdetail::to_raw_pointer(mp_mngr);   }
126
127    //!Constructor from the segment manager.
128    //!Never throws
129    allocator(segment_manager *segment_mngr) 
130       : mp_mngr(segment_mngr) { }
131
132    //!Constructor from other allocator.
133    //!Never throws
134    allocator(const allocator &other) 
135       : mp_mngr(other.get_segment_manager()){ }
136
137    //!Constructor from related allocator.
138    //!Never throws
139    template<class T2>
140    allocator(const allocator<T2, SegmentManager> &other) 
141       : mp_mngr(other.get_segment_manager()){}
142
143    //!Allocates memory for an array of count elements. 
144    //!Throws boost::interprocess::bad_alloc if there is no enough memory
145    pointer allocate(size_type count, cvoid_ptr hint = 0)
146    {
147       (void)hint;
148       if(count > this->max_size())
149          throw bad_alloc();
150       return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T))));
151    }
152
153    //!Deallocates memory previously allocated.
154    //!Never throws
155    void deallocate(const pointer &ptr, size_type)
156    {  mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr));  }
157
158    //!Returns the number of elements that could be allocated.
159    //!Never throws
160    size_type max_size() const
161    {  return mp_mngr->get_size()/sizeof(T);   }
162
163    //!Swap segment manager. Does not throw. If each allocator is placed in
164    //!different memory segments, the result is undefined.
165    friend void swap(self_t &alloc1, self_t &alloc2)
166    {  ipcdetail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr);   }
167
168    //!Returns maximum the number of objects the previously allocated memory
169    //!pointed by p can hold. This size only works for memory allocated with
170    //!allocate, allocation_command and allocate_many.
171    size_type size(const pointer &p) const
172    {  
173       return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
174    }
175
176    std::pair<pointer, bool>
177       allocation_command(boost::interprocess::allocation_type command,
178                          size_type limit_size, 
179                          size_type preferred_size,
180                          size_type &received_size, const pointer &reuse = 0)
181    {
182       return mp_mngr->allocation_command
183          (command, limit_size, preferred_size, received_size, ipcdetail::to_raw_pointer(reuse));
184    }
185
186    //!Allocates many elements of size elem_size in a contiguous block
187    //!of memory. The minimum number to be allocated is min_elements,
188    //!the preferred and maximum number is
189    //!preferred_elements. The number of actually allocated elements is
190    //!will be assigned to received_size. The elements must be deallocated
191    //!with deallocate(...)
192    multiallocation_chain allocate_many
193       (size_type elem_size, size_type num_elements)
194    {
195       return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
196    }
197
198    //!Allocates n_elements elements, each one of size elem_sizes[i]in a
199    //!contiguous block
200    //!of memory. The elements must be deallocated
201    multiallocation_chain allocate_many
202       (const size_type *elem_sizes, size_type n_elements)
203    {
204       multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
205    }
206
207    //!Allocates many elements of size elem_size in a contiguous block
208    //!of memory. The minimum number to be allocated is min_elements,
209    //!the preferred and maximum number is
210    //!preferred_elements. The number of actually allocated elements is
211    //!will be assigned to received_size. The elements must be deallocated
212    //!with deallocate(...)
213    void deallocate_many(multiallocation_chain chain)
214    {
215       return mp_mngr->deallocate_many(chain.extract_multiallocation_chain());
216    }
217
218    //!Allocates just one object. Memory allocated with this function
219    //!must be deallocated only with deallocate_one().
220    //!Throws boost::interprocess::bad_alloc if there is no enough memory
221    pointer allocate_one()
222    {  return this->allocate(1);  }
223
224    //!Allocates many elements of size == 1 in a contiguous block
225    //!of memory. The minimum number to be allocated is min_elements,
226    //!the preferred and maximum number is
227    //!preferred_elements. The number of actually allocated elements is
228    //!will be assigned to received_size. Memory allocated with this function
229    //!must be deallocated only with deallocate_one().
230    multiallocation_chain allocate_individual
231       (size_type num_elements)
232    {  return this->allocate_many(1, num_elements); }
233
234    //!Deallocates memory previously allocated with allocate_one().
235    //!You should never use deallocate_one to deallocate memory allocated
236    //!with other functions different from allocate_one(). Never throws
237    void deallocate_one(const pointer &p)
238    {  return this->deallocate(p, 1);  }
239
240    //!Allocates many elements of size == 1 in a contiguous block
241    //!of memory. The minimum number to be allocated is min_elements,
242    //!the preferred and maximum number is
243    //!preferred_elements. The number of actually allocated elements is
244    //!will be assigned to received_size. Memory allocated with this function
245    //!must be deallocated only with deallocate_one().
246    void deallocate_individual(multiallocation_chain chain)
247    {  return this->deallocate_many(boost::move(chain)); }
248
249    //!Returns address of mutable object.
250    //!Never throws
251    pointer address(reference value) const
252    {  return pointer(boost::addressof(value));  }
253
254    //!Returns address of non mutable object.
255    //!Never throws
256    const_pointer address(const_reference value) const
257    {  return const_pointer(boost::addressof(value));  }
258
259    //!Constructs an object
260    //!Throws if T's constructor throws
261    //!For backwards compatibility with libraries using C++03 allocators
262    template<class P>
263    void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
264    {  ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p));  }
265
266    //!Destroys object. Throws if object's
267    //!destructor throws
268    void destroy(const pointer &ptr)
269    {  BOOST_ASSERT(ptr != 0); (*ptr).~value_type();  }
270
271 };
272
273 //!Equality test for same type
274 //!of allocator
275 template<class T, class SegmentManager> inline
276 bool operator==(const allocator<T , SegmentManager>  &alloc1, 
277                 const allocator<T, SegmentManager>  &alloc2)
278    {  return alloc1.get_segment_manager() == alloc2.get_segment_manager(); }
279
280 //!Inequality test for same type
281 //!of allocator
282 template<class T, class SegmentManager> inline
283 bool operator!=(const allocator<T, SegmentManager>  &alloc1, 
284                 const allocator<T, SegmentManager>  &alloc2)
285    {  return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
286
287 }  //namespace interprocess {
288
289 /// @cond
290
291 template<class T>
292 struct has_trivial_destructor;
293
294 template<class T, class SegmentManager>
295 struct has_trivial_destructor
296    <boost::interprocess::allocator <T, SegmentManager> >
297 {
298    static const bool value = true;
299 };
300 /// @endcond
301
302 }  //namespace boost {
303
304 #include <boost/interprocess/detail/config_end.hpp>
305
306 #endif   //BOOST_INTERPROCESS_ALLOCATOR_HPP
307