xref: /oneTBB/test/common/containers_common.h (revision 478de5b1)
1 /*
2     Copyright (c) 2005-2021 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_test_common_containers_common_H
18 #define __TBB_test_common_containers_common_H
19 
20 #include "config.h"
21 #include "custom_allocators.h"
22 
23 template <typename ContainerType>
test_allocator_traits()24 void test_allocator_traits() {
25     using allocator_type = typename ContainerType::allocator_type;
26     using allocator_traits_type = std::allocator_traits<allocator_type>;
27     using pocca_type = typename allocator_traits_type::propagate_on_container_copy_assignment;
28     using pocma_type = typename allocator_traits_type::propagate_on_container_move_assignment;
29     using pocs_type = typename allocator_traits_type::propagate_on_container_swap;
30 
31     bool propagated_on_copy = false;
32     bool propagated_on_move = false;
33     bool propagated_on_swap = false;
34     bool selected_on_copy = false;
35 
36     allocator_type alloc(propagated_on_copy, propagated_on_move, propagated_on_swap, selected_on_copy);
37 
38     ContainerType c1(alloc), c2(c1);
39     REQUIRE_MESSAGE(selected_on_copy, "select_on_container_copy_construction function was not called");
40 
41     c1 = c2;
42     REQUIRE_MESSAGE(propagated_on_copy == pocca_type::value, "Unexpected allocator propagation on copy assignment");
43 
44     c2 = std::move(c1);
45     REQUIRE_MESSAGE(propagated_on_move == pocma_type::value, "Unexpected allocator propagation on move assignment");
46 
47     c1.swap(c2);
48     REQUIRE_MESSAGE(propagated_on_swap == pocs_type::value, "Unexpected allocator propagation on swap");
49 
50     propagated_on_move = false;
51     propagated_on_swap = false;
52     using std::swap;
53     swap(c1, c2);
54     REQUIRE_MESSAGE(propagated_on_move == false, "Unexpected allocator propagation on non-member swap");
55     REQUIRE_MESSAGE(propagated_on_swap == pocs_type::value, "Unexpected allocator propagation on non-member swap");
56 }
57 
58 struct NonMovableObject {
59     NonMovableObject() = default;
60     NonMovableObject( const NonMovableObject& ) = delete;
61     NonMovableObject( NonMovableObject&& ) = delete;
62     NonMovableObject& operator=( const NonMovableObject& ) = delete;
63     NonMovableObject& operator=( NonMovableObject&& ) = delete;
64 };
65 
66 namespace std {
67 template <>
68 struct hash<NonMovableObject> {
69     std::size_t operator()( const NonMovableObject& ) { return 1; }
70 };
71 }
72 
73 template <typename ContainerType>
74 void test_allocator_traits_with_non_movable_value_type() {
75     // Check that if pocma is true, container allows move assignment without per-element move
76     using allocator_type = typename ContainerType::allocator_type;
77     using allocator_traits_type = std::allocator_traits<allocator_type>;
78     using pocma_type = typename allocator_traits_type::propagate_on_container_move_assignment;
79     REQUIRE_MESSAGE(pocma_type::value, "Allocator POCMA should be true for this test");
80     allocator_type alloc;
81     ContainerType container1(alloc), container2(alloc);
82     container1 = std::move(container2);
83 }
84 
85 template <typename ContainerType>
86 void test_is_always_equal() {
87     using allocator_type = typename ContainerType::allocator_type;
88     allocator_type alloc;
89 
90     ContainerType container1(alloc), container2(std::move(container1), alloc);
91 
92     container1 = std::move(container2);
93 
94     container1.swap(container2);
95 
96     using std::swap;
97     swap(container1, container2);
98 }
99 
100 template <typename ContainerTraits>
101 void test_allocator_traits_support() {
102     using container_value_type = typename ContainerTraits::template container_value_type<int>;
103 
104     using always_propagating_allocator_type = AlwaysPropagatingAllocator<container_value_type>;
105     using never_propagating_allocator_type = NeverPropagatingAllocator<container_value_type>;
106     using pocma_allocator_type = PocmaAllocator<container_value_type>;
107     using pocca_allocator_type = PoccaAllocator<container_value_type>;
108     using pocs_allocator_type = PocsAllocator<container_value_type>;
109     using always_equal_allocator_type = AlwaysEqualAllocator<container_value_type>;
110 
111     using always_container_type = typename ContainerTraits::template container_type<int, always_propagating_allocator_type>;
112     using never_container_type = typename ContainerTraits::template container_type<int, never_propagating_allocator_type>;
113     using pocma_container_type = typename ContainerTraits::template container_type<int, pocma_allocator_type>;
114     using pocca_container_type = typename ContainerTraits::template container_type<int, pocca_allocator_type>;
115     using pocs_container_type = typename ContainerTraits::template container_type<int, pocs_allocator_type>;
116     using always_equal_container_type = typename ContainerTraits::template container_type<int, always_equal_allocator_type>;
117 
118     test_allocator_traits<always_container_type>();
119     test_allocator_traits<never_container_type>();
120     test_allocator_traits<pocma_container_type>();
121     test_allocator_traits<pocca_container_type>();
122     test_allocator_traits<pocs_container_type>();
123 
124     using container_non_movable_value_type = typename ContainerTraits::template container_value_type<NonMovableObject>;
125     using pocma_allocator_non_movable_value_type = PocmaAllocator<container_non_movable_value_type>;
126     using pocma_container_non_movable_value_type = typename ContainerTraits::template
127                                                    container_type<NonMovableObject, pocma_allocator_non_movable_value_type>;
128     test_allocator_traits_with_non_movable_value_type<pocma_container_non_movable_value_type>();
129     test_is_always_equal<always_equal_container_type>();
130 }
131 
132 #if TBB_USE_EXCEPTIONS
133 struct ThrowOnCopy {
134     static int error_code() { return 8; };
135     static bool is_active;
136     ThrowOnCopy() = default;
137     ThrowOnCopy( const ThrowOnCopy& ) {
138         if (is_active) {
139             throw error_code();
140         }
141     }
142     static void activate() { is_active = true; }
143     static void deactivate() { is_active = false; }
144 
145     bool operator<( const ThrowOnCopy& ) const { return true; }
146     bool operator==( const ThrowOnCopy& ) const { return true; }
147 }; // struct ThrowOnCopy
148 
149 bool ThrowOnCopy::is_active = false;
150 
151 #endif
152 
153 namespace std {
154 template <typename T>
155 struct hash<std::reference_wrapper<T>> {
156     std::size_t operator()( const std::reference_wrapper<T>& wr ) const {
157         using type = typename std::remove_const<typename std::remove_const<T>::type>::type;
158         return std::hash<type>()(wr.get());
159     }
160 };
161 
162 template <typename T>
163 struct hash<std::weak_ptr<T>> {
164     std::size_t operator()( const std::weak_ptr<T>& wr ) const {
165         return std::hash<T>()(*wr.lock().get());
166     }
167 };
168 
169 #if TBB_USE_EXCEPTIONS
170 template <>
171 struct hash<ThrowOnCopy> {
172     std::size_t operator()( const ThrowOnCopy& ) const {
173         return 1;
174     }
175 };
176 #endif
177 
178 template <typename T>
179 struct equal_to<std::weak_ptr<T>> {
180     std::size_t operator()( const std::weak_ptr<T>& rhs, const std::weak_ptr<T>& lhs ) const {
181         return *rhs.lock().get() == *lhs.lock().get();
182     }
183 };
184 
185 } // namespace std
186 
187 #endif // __TBB_test_common_containers_common_H
188