1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifndef __TBB_tbb_allocator_H
18#define __TBB_tbb_allocator_H
19
20#include "tbb_stddef.h"
21#include <new>
22#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
23 #include <utility> // std::forward
24#endif
25#include <cstring>
26
27namespace tbb {
28
29//! @cond INTERNAL
30namespace internal {
31
32 //! Deallocates memory using FreeHandler
33 /** The function uses scalable_free if scalable allocator is available and free if not*/
34 void __TBB_EXPORTED_FUNC deallocate_via_handler_v3( void *p );
35
36 //! Allocates memory using MallocHandler
37 /** The function uses scalable_malloc if scalable allocator is available and malloc if not*/
38 void* __TBB_EXPORTED_FUNC allocate_via_handler_v3( size_t n );
39
40 //! Returns true if standard malloc/free are used to work with memory.
41 bool __TBB_EXPORTED_FUNC is_malloc_used_v3();
42}
43//! @endcond
44
45#if _MSC_VER && !defined(__INTEL_COMPILER)
46 // Workaround for erroneous "unreferenced parameter" warning in method destroy.
47 #pragma warning (push)
48 #pragma warning (disable: 4100)
49#endif
50
51//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
52/** The class selects the best memory allocation mechanism available
53 from scalable_malloc and standard malloc.
54 The members are ordered the same way they are in section 20.4.1
55 of the ISO C++ standard.
56 @ingroup memory_allocation */
57template<typename T>
58class tbb_allocator {
59public:
60 typedef typename internal::allocator_type<T>::value_type value_type;
61 typedef value_type* pointer;
62 typedef const value_type* const_pointer;
63 typedef value_type& reference;
64 typedef const value_type& const_reference;
65 typedef size_t size_type;
66 typedef ptrdiff_t difference_type;
67 template<typename U> struct rebind {
68 typedef tbb_allocator<U> other;
69 };
70
71 //! Specifies current allocator
72 enum malloc_type {
73 scalable,
74 standard
75 };
76
77 tbb_allocator() throw() {}
78 tbb_allocator( const tbb_allocator& ) throw() {}
79 template<typename U> tbb_allocator(const tbb_allocator<U>&) throw() {}
80
81 pointer address(reference x) const {return &x;}
82 const_pointer address(const_reference x) const {return &x;}
83
84 //! Allocate space for n objects.
85 pointer allocate( size_type n, const void* /*hint*/ = 0) {
86 return pointer(internal::allocate_via_handler_v3( n * sizeof(value_type) ));
87 }
88
89 //! Free previously allocated block of memory.
90 void deallocate( pointer p, size_type ) {
91 internal::deallocate_via_handler_v3(p);
92 }
93
94 //! Largest value for which method allocate might succeed.
95 size_type max_size() const throw() {
96 size_type max = static_cast<size_type>(-1) / sizeof (value_type);
97 return (max > 0 ? max : 1);
98 }
99
100 //! Copy-construct value at location pointed to by p.
101#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
102 template<typename U, typename... Args>
103 void construct(U *p, Args&&... args)
104 { ::new((void *)p) U(std::forward<Args>(args)...); }
105#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
106#if __TBB_CPP11_RVALUE_REF_PRESENT
107 void construct( pointer p, value_type&& value ) {::new((void*)(p)) value_type(std::move(value));}
108#endif
109 void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
110#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
111
112 //! Destroy value at location pointed to by p.
113 void destroy( pointer p ) {p->~value_type();}
114
115 //! Returns current allocator
116 static malloc_type allocator_type() {
117 return internal::is_malloc_used_v3() ? standard : scalable;
118 }
119};
120
121#if _MSC_VER && !defined(__INTEL_COMPILER)
122 #pragma warning (pop)
123#endif // warning 4100 is back
124
125//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
126/** @ingroup memory_allocation */
127template<>
128class tbb_allocator<void> {
129public:
130 typedef void* pointer;
131 typedef const void* const_pointer;
132 typedef void value_type;
133 template<typename U> struct rebind {
134 typedef tbb_allocator<U> other;
135 };
136};
137
138template<typename T, typename U>
139inline bool operator==( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return true;}
140
141template<typename T, typename U>
142inline bool operator!=( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return false;}
143
144//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
145/** The class is an adapter over an actual allocator that fills the allocation
146 using memset function with template argument C as the value.
147 The members are ordered the same way they are in section 20.4.1
148 of the ISO C++ standard.
149 @ingroup memory_allocation */
150template <typename T, template<typename X> class Allocator = tbb_allocator>
151class zero_allocator : public Allocator<T>
152{
153public:
154 typedef Allocator<T> base_allocator_type;
155 typedef typename base_allocator_type::value_type value_type;
156 typedef typename base_allocator_type::pointer pointer;
157 typedef typename base_allocator_type::const_pointer const_pointer;
158 typedef typename base_allocator_type::reference reference;
159 typedef typename base_allocator_type::const_reference const_reference;
160 typedef typename base_allocator_type::size_type size_type;
161 typedef typename base_allocator_type::difference_type difference_type;
162 template<typename U> struct rebind {
163 typedef zero_allocator<U, Allocator> other;
164 };
165
166 zero_allocator() throw() { }
167 zero_allocator(const zero_allocator &a) throw() : base_allocator_type( a ) { }
168 template<typename U>
169 zero_allocator(const zero_allocator<U> &a) throw() : base_allocator_type( Allocator<U>( a ) ) { }
170
171 pointer allocate(const size_type n, const void *hint = 0 ) {
172 pointer ptr = base_allocator_type::allocate( n, hint );
173 std::memset( static_cast<void*>(ptr), 0, n * sizeof(value_type) );
174 return ptr;
175 }
176};
177
178//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
179/** @ingroup memory_allocation */
180template<template<typename T> class Allocator>
181class zero_allocator<void, Allocator> : public Allocator<void> {
182public:
183 typedef Allocator<void> base_allocator_type;
184 typedef typename base_allocator_type::value_type value_type;
185 typedef typename base_allocator_type::pointer pointer;
186 typedef typename base_allocator_type::const_pointer const_pointer;
187 template<typename U> struct rebind {
188 typedef zero_allocator<U, Allocator> other;
189 };
190};
191
192template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
193inline bool operator==( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
194 return static_cast< B1<T1> >(a) == static_cast< B2<T2> >(b);
195}
196template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
197inline bool operator!=( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
198 return static_cast< B1<T1> >(a) != static_cast< B2<T2> >(b);
199}
200
201} // namespace tbb
202
203#endif /* __TBB_tbb_allocator_H */
204