3 #ifndef __CDS_DETAILS_ALLOCATOR_H
4 #define __CDS_DETAILS_ALLOCATOR_H
7 Allocator class for the library. Supports allocating and constructing of objects
10 2008.03.08 Maxim.Khiszinsky Created
13 #include <cds/details/defs.h>
14 #include <cds/user_setup/allocator.h>
15 #include <cds/details/std/type_traits.h>
17 #include <boost/type_traits/has_trivial_destructor.hpp>
22 /// Extends \p std::allocator interface to provide semantics like operator \p new and \p delete
24 The class is the wrapper around underlying \p Alloc class.
25 \p Alloc provides the \p std::allocator interface.
27 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR >
29 : public std::conditional<
30 std::is_same< T, typename Alloc::value_type>::value
32 , typename Alloc::template rebind<T>::other
36 /// Underlying allocator type
37 typedef typename std::conditional<
38 std::is_same< T, typename Alloc::value_type>::value
40 , typename Alloc::template rebind<T>::other
41 >::type allocator_type;
46 # ifdef CDS_CXX11_VARIADIC_TEMPLATE_SUPPORT
47 /// Analogue of operator new T(\p src... )
48 template <typename... S>
49 value_type * New( S const&... src )
51 return Construct( allocator_type::allocate(1), src... );
55 /// Analogue of operator new T
58 return Construct( allocator_type::allocate(1) );
61 /// Analogue of operator new T(\p src )
63 value_type * New( S const& src )
65 return Construct( allocator_type::allocate(1), src );
68 /// Analogue of operator new T( \p s1, \p s2 )
69 template <typename S1, typename S2>
70 value_type * New( S1 const& s1, S2 const& s2 )
72 return Construct( allocator_type::allocate(1), s1, s2 );
75 /// Analogue of operator new T( \p s1, \p s2, \p s3 )
76 template <typename S1, typename S2, typename S3>
77 value_type * New( S1 const& s1, S2 const& s2, S3 const& s3 )
79 return Construct( allocator_type::allocate(1), s1, s2, s3 );
84 # ifdef CDS_EMPLACE_SUPPORT
85 /// Analogue of <tt>operator new T( std::forward<Args>(args)... )</tt> (move semantics)
87 This function is available only for compiler that supports
88 variadic template and move semantics
90 template <typename... Args>
91 value_type * MoveNew( Args&&... args )
93 return MoveConstruct( allocator_type::allocate(1), std::forward<Args>(args)... );
98 /// Analogue of operator new T[\p nCount ]
99 value_type * NewArray( size_t nCount )
101 value_type * p = allocator_type::allocate( nCount );
102 for ( size_t i = 0; i < nCount; ++i )
107 /// Analogue of operator new T[\p nCount ].
109 Each item of array of type T is initialized by parameter \p src: T( src )
111 template <typename S>
112 value_type * NewArray( size_t nCount, S const& src )
114 value_type * p = allocator_type::allocate( nCount );
115 for ( size_t i = 0; i < nCount; ++i )
116 Construct( p + i, src );
120 # ifdef CDS_CXX11_VARIADIC_TEMPLATE_SUPPORT
121 # if CDS_COMPILER == CDS_COMPILER_INTEL
123 value_type * NewBlock( size_t nSize )
125 return Construct( heap_alloc( nSize ));
129 /// Allocates block of memory of size at least \p nSize bytes.
131 Internally, the block is allocated as an array of \p void* pointers,
132 then \p Construct() method is called to initialize \p T.
134 Precondition: <tt> nSize >= sizeof(T) </tt>
136 template <typename... S>
137 value_type * NewBlock( size_t nSize, S const&... src )
139 return Construct( heap_alloc( nSize ), src... );
143 value_type * NewBlock( size_t nSize )
145 return Construct( heap_alloc( nSize ));
147 template <typename S>
148 value_type * NewBlock( size_t nSize, S const& arg )
150 return Construct( heap_alloc( nSize ), arg );
152 template <typename S1, typename S2>
153 value_type * NewBlock( size_t nSize, S1 const& arg1, S2 const& arg2 )
155 return Construct( heap_alloc( nSize ), arg1, arg2 );
157 template <typename S1, typename S2, typename S3>
158 value_type * NewBlock( size_t nSize, S1 const& arg1, S2 const& arg2, S3 const& arg3 )
160 return Construct( heap_alloc( nSize ), arg1, arg2, arg3 );
165 /// Analogue of operator delete
166 void Delete( value_type * p )
168 allocator_type::destroy( p );
169 allocator_type::deallocate( p, 1 );
172 /// Analogue of operator delete []
173 void Delete( value_type * p, size_t nCount )
175 for ( size_t i = 0; i < nCount; ++i )
176 allocator_type::destroy( p + i );
177 allocator_type::deallocate( p, nCount );
180 # ifdef CDS_CXX11_VARIADIC_TEMPLATE_SUPPORT
181 # if CDS_COMPILER == CDS_COMPILER_INTEL
183 value_type * Construct( void * p )
185 return new( p ) value_type;
189 /// Analogue of placement operator new( \p p ) T( src... )
190 template <typename... S>
191 value_type * Construct( void * p, S const&... src )
193 return new( p ) value_type( src... );
197 /// Analogue of placement operator new( \p p ) T
198 value_type * Construct( void * p )
200 return new( p ) value_type;
204 /// Analogue of placement operator new( \p p ) T( \p src )
205 template <typename S>
206 value_type * Construct( void * p, S const& src )
208 return new( p ) value_type( src );
211 /// Analogue of placement operator new( \p p ) T( \p s1, \p s2 )
212 template <typename S1, typename S2>
213 value_type * Construct( void * p, S1 const& s1, S2 const& s2 )
215 return new( p ) value_type( s1, s2 );
218 /// Analogue of placement operator new( \p p ) T( \p s1, \p s2, \p s3 )
219 template <typename S1, typename S2, typename S3>
220 value_type * Construct( void * p, S1 const& s1, S2 const& s2, S3 const& s3 )
222 return new( p ) value_type( s1, s2, s3 );
227 # ifdef CDS_EMPLACE_SUPPORT
228 /// Analogue of placement <tt>operator new( p ) T( std::forward<Args>(args)... )</tt>
230 This function is available only for compiler that supports
231 variadic template and move semantics
233 template <typename... Args>
234 value_type * MoveConstruct( void * p, Args&&... args )
236 return new( p ) value_type( std::forward<Args>(args)... );
240 /// Rebinds allocator to other type \p Q instead of \p T
241 template <typename Q>
243 typedef Allocator< Q, typename Alloc::template rebind<Q>::other > other ; ///< Rebinding result
248 void * heap_alloc( size_t nByteSize )
250 assert( nByteSize >= sizeof(value_type));
252 size_t const nPtrSize = ( nByteSize + sizeof(void *) - 1 ) / sizeof(void *);
253 typedef typename allocator_type::template rebind< void * >::other void_allocator;
254 return void_allocator().allocate( nPtrSize );
262 static inline void impl_call_dtor(T* p, boost::false_type const&)
268 static inline void impl_call_dtor(T* p, boost::true_type const&)
273 /// Helper function to call destructor of type T
275 This function is empty for the type T that has trivial destructor.
278 static inline void call_dtor( T* p )
280 impl_call_dtor( p, ::boost::has_trivial_destructor<T>() );
284 /// Deferral removing of the object of type \p T. Helper class
285 template <typename T, typename Alloc = CDS_DEFAULT_ALLOCATOR>
286 struct deferral_deleter {
287 typedef T type ; ///< Type
288 typedef Alloc allocator_type ; ///< Allocator for removing
290 /// Frees the object \p p
292 Caveats: this function uses temporary object of type \ref cds::details::Allocator to free the node \p p.
293 So, the node allocator should be stateless. It is standard requirement for \p std::allocator class objects.
295 Do not use this function directly.
297 static void free( T * p )
299 Allocator<T, Alloc> a;
304 } // namespace details
307 #endif // #ifndef __CDS_DETAILS_ALLOCATOR_H