1/*
2 Copyright 2005-2013 Intel Corporation. All Rights Reserved.
3
4 This file is part of Threading Building Blocks.
5
6 Threading Building Blocks is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
9
10 Threading Building Blocks is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Threading Building Blocks; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 As a special exception, you may use this file as part of a free software
20 library without restriction. Specifically, if other files instantiate
21 templates or use macros or inline functions from this file, or you compile
22 this file and link it with other files to produce an executable, this
23 file does not by itself cause the resulting executable to be covered by
24 the GNU General Public License. This exception does not however
25 invalidate any other reasons why the executable file might be covered by
26 the GNU General Public License.
27*/
28
29#ifndef __TBB_tbb_allocator_H
30#define __TBB_tbb_allocator_H
31
32#include "tbb_stddef.h"
33#include <new>
34#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
35 #include <utility> // std::forward
36#endif
37
38#if !TBB_USE_EXCEPTIONS && _MSC_VER
39 // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
40 #pragma warning (push)
41 #pragma warning (disable: 4530)
42#endif
43
44#include <cstring>
45
46#if !TBB_USE_EXCEPTIONS && _MSC_VER
47 #pragma warning (pop)
48#endif
49
50namespace tbb {
51
52//! @cond INTERNAL
53namespace internal {
54
55 //! Deallocates memory using FreeHandler
56 /** The function uses scalable_free if scalable allocator is available and free if not*/
57 void __TBB_EXPORTED_FUNC deallocate_via_handler_v3( void *p );
58
59 //! Allocates memory using MallocHandler
60 /** The function uses scalable_malloc if scalable allocator is available and malloc if not*/
61 void* __TBB_EXPORTED_FUNC allocate_via_handler_v3( size_t n );
62
63 //! Returns true if standard malloc/free are used to work with memory.
64 bool __TBB_EXPORTED_FUNC is_malloc_used_v3();
65}
66//! @endcond
67
68#if _MSC_VER && !defined(__INTEL_COMPILER)
69 // Workaround for erroneous "unreferenced parameter" warning in method destroy.
70 #pragma warning (push)
71 #pragma warning (disable: 4100)
72#endif
73
74//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
75/** The class selects the best memory allocation mechanism available
76 from scalable_malloc and standard malloc.
77 The members are ordered the same way they are in section 20.4.1
78 of the ISO C++ standard.
79 @ingroup memory_allocation */
80template<typename T>
81class tbb_allocator {
82public:
83 typedef typename internal::allocator_type<T>::value_type value_type;
84 typedef value_type* pointer;
85 typedef const value_type* const_pointer;
86 typedef value_type& reference;
87 typedef const value_type& const_reference;
88 typedef size_t size_type;
89 typedef ptrdiff_t difference_type;
90 template<typename U> struct rebind {
91 typedef tbb_allocator<U> other;
92 };
93
94 //! Specifies current allocator
95 enum malloc_type {
96 scalable,
97 standard
98 };
99
100 tbb_allocator() throw() {}
101 tbb_allocator( const tbb_allocator& ) throw() {}
102 template<typename U> tbb_allocator(const tbb_allocator<U>&) throw() {}
103
104 pointer address(reference x) const {return &x;}
105 const_pointer address(const_reference x) const {return &x;}
106
107 //! Allocate space for n objects.
108 pointer allocate( size_type n, const void* /*hint*/ = 0) {
109 return pointer(internal::allocate_via_handler_v3( n * sizeof(value_type) ));
110 }
111
112 //! Free previously allocated block of memory.
113 void deallocate( pointer p, size_type ) {
114 internal::deallocate_via_handler_v3(p);
115 }
116
117 //! Largest value for which method allocate might succeed.
118 size_type max_size() const throw() {
119 size_type max = static_cast<size_type>(-1) / sizeof (value_type);
120 return (max > 0 ? max : 1);
121 }
122
123 //! Copy-construct value at location pointed to by p.
124#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
125 template<typename U, typename... Args>
126 void construct(U *p, Args&&... args)
127 #if __TBB_CPP11_STD_FORWARD_BROKEN
128 { ::new((void *)p) U((args)...); }
129 #else
130 { ::new((void *)p) U(std::forward<Args>(args)...); }
131 #endif
132#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
133 void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
134#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
135
136 //! Destroy value at location pointed to by p.
137 void destroy( pointer p ) {p->~value_type();}
138
139 //! Returns current allocator
140 static malloc_type allocator_type() {
141 return internal::is_malloc_used_v3() ? standard : scalable;
142 }
143};
144
145#if _MSC_VER && !defined(__INTEL_COMPILER)
146 #pragma warning (pop)
147#endif // warning 4100 is back
148
149//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
150/** @ingroup memory_allocation */
151template<>
152class tbb_allocator<void> {
153public:
154 typedef void* pointer;
155 typedef const void* const_pointer;
156 typedef void value_type;
157 template<typename U> struct rebind {
158 typedef tbb_allocator<U> other;
159 };
160};
161
162template<typename T, typename U>
163inline bool operator==( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return true;}
164
165template<typename T, typename U>
166inline bool operator!=( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return false;}
167
168//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
169/** The class is an adapter over an actual allocator that fills the allocation
170 using memset function with template argument C as the value.
171 The members are ordered the same way they are in section 20.4.1
172 of the ISO C++ standard.
173 @ingroup memory_allocation */
174template <typename T, template<typename X> class Allocator = tbb_allocator>
175class zero_allocator : public Allocator<T>
176{
177public:
178 typedef Allocator<T> base_allocator_type;
179 typedef typename base_allocator_type::value_type value_type;
180 typedef typename base_allocator_type::pointer pointer;
181 typedef typename base_allocator_type::const_pointer const_pointer;
182 typedef typename base_allocator_type::reference reference;
183 typedef typename base_allocator_type::const_reference const_reference;
184 typedef typename base_allocator_type::size_type size_type;
185 typedef typename base_allocator_type::difference_type difference_type;
186 template<typename U> struct rebind {
187 typedef zero_allocator<U, Allocator> other;
188 };
189
190 zero_allocator() throw() { }
191 zero_allocator(const zero_allocator &a) throw() : base_allocator_type( a ) { }
192 template<typename U>
193 zero_allocator(const zero_allocator<U> &a) throw() : base_allocator_type( Allocator<U>( a ) ) { }
194
195 pointer allocate(const size_type n, const void *hint = 0 ) {
196 pointer ptr = base_allocator_type::allocate( n, hint );
197 std::memset( ptr, 0, n * sizeof(value_type) );
198 return ptr;
199 }
200};
201
202//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
203/** @ingroup memory_allocation */
204template<template<typename T> class Allocator>
205class zero_allocator<void, Allocator> : public Allocator<void> {
206public:
207 typedef Allocator<void> base_allocator_type;
208 typedef typename base_allocator_type::value_type value_type;
209 typedef typename base_allocator_type::pointer pointer;
210 typedef typename base_allocator_type::const_pointer const_pointer;
211 template<typename U> struct rebind {
212 typedef zero_allocator<U, Allocator> other;
213 };
214};
215
216template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
217inline bool operator==( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
218 return static_cast< B1<T1> >(a) == static_cast< B2<T2> >(b);
219}
220template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
221inline bool operator!=( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
222 return static_cast< B1<T1> >(a) != static_cast< B2<T2> >(b);
223}
224
225} // namespace tbb
226
227#endif /* __TBB_tbb_allocator_H */
228