| 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_cache_aligned_allocator_H |
| 30 | #define __TBB_cache_aligned_allocator_H |
| 31 | |
| 32 | #include <new> |
| 33 | #include "tbb_stddef.h" |
| 34 | #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN |
| 35 | #include <utility> // std::forward |
| 36 | #endif |
| 37 | |
| 38 | namespace tbb { |
| 39 | |
| 40 | //! @cond INTERNAL |
| 41 | namespace internal { |
| 42 | //! Cache/sector line size. |
| 43 | /** @ingroup memory_allocation */ |
| 44 | size_t __TBB_EXPORTED_FUNC NFS_GetLineSize(); |
| 45 | |
| 46 | //! Allocate memory on cache/sector line boundary. |
| 47 | /** @ingroup memory_allocation */ |
| 48 | void* __TBB_EXPORTED_FUNC NFS_Allocate( size_t n_element, size_t element_size, void* hint ); |
| 49 | |
| 50 | //! Free memory allocated by NFS_Allocate. |
| 51 | /** Freeing a NULL pointer is allowed, but has no effect. |
| 52 | @ingroup memory_allocation */ |
| 53 | void __TBB_EXPORTED_FUNC NFS_Free( void* ); |
| 54 | } |
| 55 | //! @endcond |
| 56 | |
| 57 | #if _MSC_VER && !defined(__INTEL_COMPILER) |
| 58 | // Workaround for erroneous "unreferenced parameter" warning in method destroy. |
| 59 | #pragma warning (push) |
| 60 | #pragma warning (disable: 4100) |
| 61 | #endif |
| 62 | |
| 63 | //! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 |
| 64 | /** The members are ordered the same way they are in section 20.4.1 |
| 65 | of the ISO C++ standard. |
| 66 | @ingroup memory_allocation */ |
| 67 | template<typename T> |
| 68 | class cache_aligned_allocator { |
| 69 | public: |
| 70 | typedef typename internal::allocator_type<T>::value_type value_type; |
| 71 | typedef value_type* pointer; |
| 72 | typedef const value_type* const_pointer; |
| 73 | typedef value_type& reference; |
| 74 | typedef const value_type& const_reference; |
| 75 | typedef size_t size_type; |
| 76 | typedef ptrdiff_t difference_type; |
| 77 | template<typename U> struct rebind { |
| 78 | typedef cache_aligned_allocator<U> other; |
| 79 | }; |
| 80 | |
| 81 | cache_aligned_allocator() throw() {} |
| 82 | cache_aligned_allocator( const cache_aligned_allocator& ) throw() {} |
| 83 | template<typename U> cache_aligned_allocator(const cache_aligned_allocator<U>&) throw() {} |
| 84 | |
| 85 | pointer address(reference x) const {return &x;} |
| 86 | const_pointer address(const_reference x) const {return &x;} |
| 87 | |
| 88 | //! Allocate space for n objects, starting on a cache/sector line. |
| 89 | pointer allocate( size_type n, const void* hint=0 ) { |
| 90 | // The "hint" argument is always ignored in NFS_Allocate thus const_cast shouldn't hurt |
| 91 | return pointer(internal::NFS_Allocate( n, sizeof(value_type), const_cast<void*>(hint) )); |
| 92 | } |
| 93 | |
| 94 | //! Free block of memory that starts on a cache line |
| 95 | void deallocate( pointer p, size_type ) { |
| 96 | internal::NFS_Free(p); |
| 97 | } |
| 98 | |
| 99 | //! Largest value for which method allocate might succeed. |
| 100 | size_type max_size() const throw() { |
| 101 | return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type); |
| 102 | } |
| 103 | |
| 104 | //! Copy-construct value at location pointed to by p. |
| 105 | #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT |
| 106 | template<typename U, typename... Args> |
| 107 | void construct(U *p, Args&&... args) |
| 108 | #if __TBB_CPP11_STD_FORWARD_BROKEN |
| 109 | { ::new((void *)p) U((args)...); } |
| 110 | #else |
| 111 | { ::new((void *)p) U(std::forward<Args>(args)...); } |
| 112 | #endif |
| 113 | #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT |
| 114 | void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} |
| 115 | #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT |
| 116 | |
| 117 | //! Destroy value at location pointed to by p. |
| 118 | void destroy( pointer p ) {p->~value_type();} |
| 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 */ |
| 127 | template<> |
| 128 | class cache_aligned_allocator<void> { |
| 129 | public: |
| 130 | typedef void* pointer; |
| 131 | typedef const void* const_pointer; |
| 132 | typedef void value_type; |
| 133 | template<typename U> struct rebind { |
| 134 | typedef cache_aligned_allocator<U> other; |
| 135 | }; |
| 136 | }; |
| 137 | |
| 138 | template<typename T, typename U> |
| 139 | inline bool operator==( const cache_aligned_allocator<T>&, const cache_aligned_allocator<U>& ) {return true;} |
| 140 | |
| 141 | template<typename T, typename U> |
| 142 | inline bool operator!=( const cache_aligned_allocator<T>&, const cache_aligned_allocator<U>& ) {return false;} |
| 143 | |
| 144 | } // namespace tbb |
| 145 | |
| 146 | #endif /* __TBB_cache_aligned_allocator_H */ |
| 147 | |