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 | |