| 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 |  | 
| 50 | namespace tbb { | 
| 51 |  | 
| 52 | //! @cond INTERNAL | 
| 53 | namespace 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 */ | 
| 80 | template<typename T> | 
| 81 | class tbb_allocator { | 
| 82 | public: | 
| 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 */ | 
| 151 | template<>  | 
| 152 | class tbb_allocator<void> { | 
| 153 | public: | 
| 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 |  | 
| 162 | template<typename T, typename U> | 
| 163 | inline bool operator==( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return true;} | 
| 164 |  | 
| 165 | template<typename T, typename U> | 
| 166 | inline 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 */ | 
| 174 | template <typename T, template<typename X> class Allocator = tbb_allocator> | 
| 175 | class zero_allocator : public Allocator<T> | 
| 176 | { | 
| 177 | public: | 
| 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 */ | 
| 204 | template<template<typename T> class Allocator>  | 
| 205 | class zero_allocator<void, Allocator> : public Allocator<void> { | 
| 206 | public: | 
| 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 |  | 
| 216 | template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2> | 
| 217 | inline 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 | } | 
| 220 | template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2> | 
| 221 | inline 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 |  |