PageRenderTime 46ms CodeModel.GetById 23ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/interprocess/allocators/private_node_allocator.hpp

http://hadesmem.googlecode.com/
C++ Header | 442 lines | 247 code | 76 blank | 119 comment | 3 complexity | fae33fe5380c00960d5288c794ab5aac 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_PRIVATE_NODE_ALLOCATOR_HPP
 12#define BOOST_INTERPROCESS_PRIVATE_NODE_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/pointer_to_other.hpp>
 22
 23#include <boost/interprocess/interprocess_fwd.hpp>
 24#include <boost/assert.hpp>
 25#include <boost/utility/addressof.hpp>
 26#include <boost/interprocess/allocators/detail/node_pool.hpp>
 27#include <boost/interprocess/containers/container/detail/multiallocation_chain.hpp>
 28#include <boost/interprocess/exceptions.hpp>
 29#include <boost/interprocess/detail/utilities.hpp>
 30#include <boost/interprocess/detail/workaround.hpp>
 31#include <memory>
 32#include <algorithm>
 33#include <cstddef>
 34
 35//!\file
 36//!Describes private_node_allocator_base pooled shared memory STL compatible allocator 
 37
 38namespace boost {
 39namespace interprocess {
 40
 41/// @cond
 42
 43namespace detail {
 44
 45template < unsigned int Version
 46         , class T
 47         , class SegmentManager
 48         , std::size_t NodesPerBlock
 49         >
 50class private_node_allocator_base
 51   : public node_pool_allocation_impl
 52   < private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock>
 53   , Version
 54   , T
 55   , SegmentManager
 56   >
 57{
 58   public:
 59   //Segment manager
 60   typedef SegmentManager                                segment_manager;
 61   typedef typename SegmentManager::void_pointer         void_pointer;
 62
 63   /// @cond
 64   private:
 65   typedef private_node_allocator_base
 66      < Version, T, SegmentManager, NodesPerBlock>       self_t;
 67   typedef detail::private_node_pool
 68      <SegmentManager
 69      , sizeof_value<T>::value
 70      , NodesPerBlock
 71      > node_pool_t;
 72
 73   BOOST_STATIC_ASSERT((Version <=2));
 74
 75   /// @endcond
 76
 77   public:
 78   typedef typename boost::
 79      pointer_to_other<void_pointer, T>::type            pointer;
 80   typedef typename boost::
 81      pointer_to_other<void_pointer, const T>::type      const_pointer;
 82   typedef T                                             value_type;
 83   typedef typename detail::add_reference
 84                     <value_type>::type                  reference;
 85   typedef typename detail::add_reference
 86                     <const value_type>::type            const_reference;
 87   typedef std::size_t                                   size_type;
 88   typedef std::ptrdiff_t                                difference_type;
 89   typedef boost::interprocess::version_type
 90      <private_node_allocator_base, Version>              version;
 91   typedef boost::container::containers_detail::transform_multiallocation_chain
 92      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
 93
 94   //!Obtains node_allocator from other node_allocator
 95   template<class T2>
 96   struct rebind
 97   {  
 98      typedef private_node_allocator_base
 99         <Version, T2, SegmentManager, NodesPerBlock>   other;
100   };
101
102   /// @cond
103   template <int dummy>
104   struct node_pool
105   {
106      typedef detail::private_node_pool
107      <SegmentManager
108      , sizeof_value<T>::value
109      , NodesPerBlock
110      > type;
111
112      static type *get(void *p)
113      {  return static_cast<type*>(p);  }
114   };
115
116   private:
117   //!Not assignable from related private_node_allocator_base
118   template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2>
119   private_node_allocator_base& operator=
120      (const private_node_allocator_base<Version2, T2, MemoryAlgorithm2, N2>&);
121
122   //!Not assignable from other private_node_allocator_base
123   private_node_allocator_base& operator=(const private_node_allocator_base&);
124   /// @endcond
125
126   public:
127   //!Constructor from a segment manager
128   private_node_allocator_base(segment_manager *segment_mngr)
129      : m_node_pool(segment_mngr)
130   {}
131
132   //!Copy constructor from other private_node_allocator_base. Never throws
133   private_node_allocator_base(const private_node_allocator_base &other)
134      : m_node_pool(other.get_segment_manager())
135   {}
136
137   //!Copy constructor from related private_node_allocator_base. Never throws.
138   template<class T2>
139   private_node_allocator_base
140      (const private_node_allocator_base
141         <Version, T2, SegmentManager, NodesPerBlock> &other)
142      : m_node_pool(other.get_segment_manager())
143   {}
144
145   //!Destructor, frees all used memory. Never throws
146   ~private_node_allocator_base() 
147   {}
148
149   //!Returns the segment manager. Never throws
150   segment_manager* get_segment_manager()const
151   {  return m_node_pool.get_segment_manager(); }
152
153   //!Returns the internal node pool. Never throws
154   node_pool_t* get_node_pool() const
155   {  return const_cast<node_pool_t*>(&m_node_pool); }
156
157   //!Swaps allocators. Does not throw. If each allocator is placed in a
158   //!different shared memory segments, the result is undefined.
159   friend void swap(self_t &alloc1,self_t &alloc2)
160   {  alloc1.m_node_pool.swap(alloc2.m_node_pool);  }
161
162   /// @cond
163   private:
164   node_pool_t m_node_pool;
165   /// @endcond
166};
167
168//!Equality test for same type of private_node_allocator_base
169template<unsigned int V, class T, class S, std::size_t NPC> inline
170bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1, 
171                const private_node_allocator_base<V, T, S, NPC> &alloc2)
172{  return &alloc1 == &alloc2; }
173
174//!Inequality test for same type of private_node_allocator_base
175template<unsigned int V, class T, class S, std::size_t NPC> inline
176bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1, 
177                const private_node_allocator_base<V, T, S, NPC> &alloc2)
178{  return &alloc1 != &alloc2; }
179
180template < class T
181         , class SegmentManager
182         , std::size_t NodesPerBlock = 64
183         >
184class private_node_allocator_v1
185   :  public private_node_allocator_base
186         < 1
187         , T
188         , SegmentManager
189         , NodesPerBlock
190         >
191{
192   public:
193   typedef detail::private_node_allocator_base
194         < 1, T, SegmentManager, NodesPerBlock> base_t;
195
196   template<class T2>
197   struct rebind
198   {  
199      typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock>  other;
200   };
201
202   private_node_allocator_v1(SegmentManager *segment_mngr) 
203      : base_t(segment_mngr)
204   {}
205
206   template<class T2>
207   private_node_allocator_v1
208      (const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
209      : base_t(other)
210   {}
211};
212
213}  //namespace detail {
214
215/// @endcond
216
217//!An STL node allocator that uses a segment manager as memory 
218//!source. The internal pointer type will of the same type (raw, smart) as
219//!"typename SegmentManager::void_pointer" type. This allows
220//!placing the allocator in shared memory, memory mapped-files, etc...
221//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated 
222//!at once when the allocator needs runs out of nodes
223template < class T
224         , class SegmentManager
225         , std::size_t NodesPerBlock
226         >
227class private_node_allocator
228   /// @cond
229   :  public detail::private_node_allocator_base
230         < 2
231         , T
232         , SegmentManager
233         , NodesPerBlock
234         >
235   /// @endcond
236{
237
238   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
239   typedef detail::private_node_allocator_base
240         < 2, T, SegmentManager, NodesPerBlock> base_t;
241   public:
242   typedef boost::interprocess::version_type<private_node_allocator, 2>   version;
243
244   template<class T2>
245   struct rebind
246   {  
247      typedef private_node_allocator
248         <T2, SegmentManager, NodesPerBlock>  other;
249   };
250
251   private_node_allocator(SegmentManager *segment_mngr) 
252      : base_t(segment_mngr)
253   {}
254
255   template<class T2>
256   private_node_allocator
257      (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
258      : base_t(other)
259   {}
260
261   #else
262   public:
263   typedef implementation_defined::segment_manager       segment_manager;
264   typedef segment_manager::void_pointer                 void_pointer;
265   typedef implementation_defined::pointer               pointer;
266   typedef implementation_defined::const_pointer         const_pointer;
267   typedef T                                             value_type;
268   typedef typename detail::add_reference
269                     <value_type>::type                  reference;
270   typedef typename detail::add_reference
271                     <const value_type>::type            const_reference;
272   typedef std::size_t                                   size_type;
273   typedef std::ptrdiff_t                                difference_type;
274
275   //!Obtains private_node_allocator from 
276   //!private_node_allocator
277   template<class T2>
278   struct rebind
279   {  
280      typedef private_node_allocator
281         <T2, SegmentManager, NodesPerBlock> other;
282   };
283
284   private:
285   //!Not assignable from
286   //!related private_node_allocator
287   template<class T2, class SegmentManager2, std::size_t N2>
288   private_node_allocator& operator=
289      (const private_node_allocator<T2, SegmentManager2, N2>&);
290
291   //!Not assignable from 
292   //!other private_node_allocator
293   private_node_allocator& operator=(const private_node_allocator&);
294
295   public:
296   //!Constructor from a segment manager. If not present, constructs a node
297   //!pool. Increments the reference count of the associated node pool.
298   //!Can throw boost::interprocess::bad_alloc
299   private_node_allocator(segment_manager *segment_mngr);
300
301   //!Copy constructor from other private_node_allocator. Increments the reference 
302   //!count of the associated node pool. Never throws
303   private_node_allocator(const private_node_allocator &other);
304
305   //!Copy constructor from related private_node_allocator. If not present, constructs
306   //!a node pool. Increments the reference count of the associated node pool.
307   //!Can throw boost::interprocess::bad_alloc
308   template<class T2>
309   private_node_allocator
310      (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
311
312   //!Destructor, removes node_pool_t from memory
313   //!if its reference count reaches to zero. Never throws
314   ~private_node_allocator();
315
316   //!Returns a pointer to the node pool.
317   //!Never throws
318   node_pool_t* get_node_pool() const;
319
320   //!Returns the segment manager.
321   //!Never throws
322   segment_manager* get_segment_manager()const;
323
324   //!Returns the number of elements that could be allocated.
325   //!Never throws
326   size_type max_size() const;
327
328   //!Allocate memory for an array of count elements. 
329   //!Throws boost::interprocess::bad_alloc if there is no enough memory
330   pointer allocate(size_type count, cvoid_pointer hint = 0);
331
332   //!Deallocate allocated memory.
333   //!Never throws
334   void deallocate(const pointer &ptr, size_type count);
335
336   //!Deallocates all free blocks
337   //!of the pool
338   void deallocate_free_blocks();
339
340   //!Swaps allocators. Does not throw. If each allocator is placed in a
341   //!different memory segment, the result is undefined.
342   friend void swap(self_t &alloc1, self_t &alloc2);
343
344   //!Returns address of mutable object.
345   //!Never throws
346   pointer address(reference value) const;
347
348   //!Returns address of non mutable object.
349   //!Never throws
350   const_pointer address(const_reference value) const;
351
352   //!Copy construct an object. 
353   //!Throws if T's copy constructor throws
354   void construct(const pointer &ptr, const_reference v);
355
356   //!Destroys object. Throws if object's
357   //!destructor throws
358   void destroy(const pointer &ptr);
359
360   //!Returns maximum the number of objects the previously allocated memory
361   //!pointed by p can hold. This size only works for memory allocated with
362   //!allocate, allocation_command and allocate_many.
363   size_type size(const pointer &p) const;
364
365   std::pair<pointer, bool>
366      allocation_command(boost::interprocess::allocation_type command,
367                         size_type limit_size, 
368                         size_type preferred_size,
369                         size_type &received_size, const pointer &reuse = 0);
370
371   //!Allocates many elements of size elem_size in a contiguous block
372   //!of memory. The minimum number to be allocated is min_elements,
373   //!the preferred and maximum number is
374   //!preferred_elements. The number of actually allocated elements is
375   //!will be assigned to received_size. The elements must be deallocated
376   //!with deallocate(...)
377   multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
378
379   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
380   //!contiguous block
381   //!of memory. The elements must be deallocated
382   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
383
384   //!Allocates many elements of size elem_size in a contiguous block
385   //!of memory. The minimum number to be allocated is min_elements,
386   //!the preferred and maximum number is
387   //!preferred_elements. The number of actually allocated elements is
388   //!will be assigned to received_size. The elements must be deallocated
389   //!with deallocate(...)
390   void deallocate_many(multiallocation_chain chain);
391
392   //!Allocates just one object. Memory allocated with this function
393   //!must be deallocated only with deallocate_one().
394   //!Throws boost::interprocess::bad_alloc if there is no enough memory
395   pointer allocate_one();
396
397   //!Allocates many elements of size == 1 in a contiguous block
398   //!of memory. The minimum number to be allocated is min_elements,
399   //!the preferred and maximum number is
400   //!preferred_elements. The number of actually allocated elements is
401   //!will be assigned to received_size. Memory allocated with this function
402   //!must be deallocated only with deallocate_one().
403   multiallocation_chain allocate_individual(std::size_t num_elements);
404
405   //!Deallocates memory previously allocated with allocate_one().
406   //!You should never use deallocate_one to deallocate memory allocated
407   //!with other functions different from allocate_one(). Never throws
408   void deallocate_one(const pointer &p);
409
410   //!Allocates many elements of size == 1 in a contiguous block
411   //!of memory. The minimum number to be allocated is min_elements,
412   //!the preferred and maximum number is
413   //!preferred_elements. The number of actually allocated elements is
414   //!will be assigned to received_size. Memory allocated with this function
415   //!must be deallocated only with deallocate_one().
416   void deallocate_individual(multiallocation_chain chain);
417   #endif
418};
419
420#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
421
422//!Equality test for same type
423//!of private_node_allocator
424template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
425bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, 
426                const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
427
428//!Inequality test for same type
429//!of private_node_allocator
430template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
431bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1, 
432                const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
433
434#endif
435
436}  //namespace interprocess {
437}  //namespace boost {
438
439#include <boost/interprocess/detail/config_end.hpp>
440
441#endif   //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
442