30
30
#include < thrust/detail/execution_policy.h>
31
31
#include < thrust/iterator/detail/normal_iterator.h>
32
32
33
+ #include < cuda/std/utility>
34
+
33
35
THRUST_NAMESPACE_BEGIN
34
36
35
37
namespace detail
@@ -38,6 +40,13 @@ namespace detail
38
40
struct copy_allocator_t
39
41
{};
40
42
43
+ struct allocator_mismatch_on_swap : std::runtime_error
44
+ {
45
+ allocator_mismatch_on_swap ()
46
+ : std::runtime_error(" swap called on containers with allocators that propagate on swap, but compare non-equal" )
47
+ {}
48
+ };
49
+
41
50
// XXX parameter T is redundant with parameter Alloc
42
51
template <typename T, typename Alloc>
43
52
class contiguous_storage
@@ -70,6 +79,8 @@ class contiguous_storage
70
79
_CCCL_EXEC_CHECK_DISABLE
71
80
_CCCL_HOST_DEVICE explicit contiguous_storage (copy_allocator_t , const contiguous_storage& other, size_type n);
72
81
82
+ contiguous_storage& operator =(const contiguous_storage& x) = delete ;
83
+
73
84
_CCCL_EXEC_CHECK_DISABLE
74
85
_CCCL_HOST_DEVICE ~contiguous_storage ();
75
86
@@ -100,7 +111,33 @@ class contiguous_storage
100
111
101
112
_CCCL_HOST_DEVICE void deallocate () noexcept ;
102
113
103
- _CCCL_HOST_DEVICE void swap (contiguous_storage& x);
114
+ _CCCL_EXEC_CHECK_DISABLE
115
+ _CCCL_HOST_DEVICE void swap (contiguous_storage& x) noexcept (
116
+ allocator_traits<Alloc>::propagate_on_container_swap::value || allocator_traits<Alloc>::is_always_equal::value)
117
+ {
118
+ using ::cuda::std::swap;
119
+ swap (m_begin, x.m_begin );
120
+ swap (m_size, x.m_size );
121
+
122
+ // From C++ standard [container.reqmts]
123
+ // If allocator_traits<allocator_type>::propagate_on_container_swap::value is true, then allocator_type
124
+ // shall meet the Cpp17Swappable requirements and the allocators of a and b shall also be exchanged by calling
125
+ // swap as described in [swappable.requirements]. Otherwise, the allocators shall not be swapped, and the behavior
126
+ // is undefined unless a.get_allocator() == b.get_allocator().
127
+ _CCCL_IF_CONSTEXPR (allocator_traits<Alloc>::propagate_on_container_swap::value)
128
+ {
129
+ swap (m_allocator, x.m_allocator );
130
+ }
131
+ else
132
+ {
133
+ _CCCL_IF_CONSTEXPR (!allocator_traits<Alloc>::is_always_equal::value)
134
+ {
135
+ NV_IF_TARGET (NV_IS_DEVICE, (assert (m_allocator == other);), (if (m_allocator != x.m_allocator ) {
136
+ throw allocator_mismatch_on_swap ();
137
+ }));
138
+ }
139
+ }
140
+ }
104
141
105
142
_CCCL_HOST_DEVICE void value_initialize_n (iterator first, size_type n);
106
143
@@ -122,23 +159,42 @@ class contiguous_storage
122
159
123
160
_CCCL_HOST_DEVICE void destroy (iterator first, iterator last) noexcept ;
124
161
125
- _CCCL_HOST_DEVICE void deallocate_on_allocator_mismatch (const contiguous_storage& other) noexcept ;
162
+ _CCCL_HOST_DEVICE void deallocate_on_allocator_mismatch (const contiguous_storage& other) noexcept
163
+ {
164
+ // TODO(bgruber): replace dispatch by if constexpr in C++17
165
+ integral_constant<bool , allocator_traits<Alloc>::propagate_on_container_copy_assignment::value> c;
166
+ deallocate_on_allocator_mismatch_dispatch (c, other);
167
+ }
126
168
127
169
_CCCL_HOST_DEVICE void
128
- destroy_on_allocator_mismatch (const contiguous_storage& other, iterator first, iterator last) noexcept ;
170
+ destroy_on_allocator_mismatch (const contiguous_storage& other, iterator first, iterator last) noexcept
171
+ {
172
+ // TODO(bgruber): replace dispatch by if constexpr in C++17
173
+ integral_constant<bool , allocator_traits<Alloc>::propagate_on_container_copy_assignment::value> c;
174
+ destroy_on_allocator_mismatch_dispatch (c, other, first, last);
175
+ }
129
176
130
177
_CCCL_HOST_DEVICE void set_allocator (const allocator_type& alloc);
131
178
132
- _CCCL_HOST_DEVICE bool is_allocator_not_equal (const allocator_type& alloc) const ;
133
-
134
- _CCCL_HOST_DEVICE bool is_allocator_not_equal (const contiguous_storage& other) const ;
135
-
136
- _CCCL_HOST_DEVICE void propagate_allocator (const contiguous_storage& other);
179
+ _CCCL_EXEC_CHECK_DISABLE
180
+ _CCCL_HOST_DEVICE void propagate_allocator (const contiguous_storage& other)
181
+ {
182
+ _CCCL_IF_CONSTEXPR (allocator_traits<Alloc>::propagate_on_container_copy_assignment::value)
183
+ {
184
+ m_allocator = other.m_allocator ;
185
+ }
186
+ }
137
187
138
- _CCCL_HOST_DEVICE void propagate_allocator (contiguous_storage& other);
188
+ _CCCL_EXEC_CHECK_DISABLE
189
+ _CCCL_HOST_DEVICE void propagate_allocator (contiguous_storage& other)
190
+ {
191
+ _CCCL_IF_CONSTEXPR (allocator_traits<Alloc>::propagate_on_container_move_assignment::value)
192
+ {
193
+ m_allocator = ::cuda::std::move (other.m_allocator );
194
+ }
195
+ }
139
196
140
197
// allow move assignment for a sane implementation of allocator propagation
141
- // on move assignment
142
198
_CCCL_HOST_DEVICE contiguous_storage& operator =(contiguous_storage&& other);
143
199
144
200
_CCCL_SYNTHESIZE_SEQUENCE_ACCESS (contiguous_storage, const_iterator);
@@ -151,34 +207,31 @@ class contiguous_storage
151
207
152
208
size_type m_size;
153
209
154
- // disallow assignment
155
- contiguous_storage& operator =(const contiguous_storage& x);
156
-
157
- _CCCL_HOST_DEVICE void swap_allocators (true_type, const allocator_type&);
158
-
159
- _CCCL_HOST_DEVICE void swap_allocators (false_type, allocator_type&);
160
-
161
- _CCCL_HOST_DEVICE bool is_allocator_not_equal_dispatch (true_type, const allocator_type&) const ;
162
-
163
- _CCCL_HOST_DEVICE bool is_allocator_not_equal_dispatch (false_type, const allocator_type&) const ;
164
-
165
- _CCCL_HOST_DEVICE void deallocate_on_allocator_mismatch_dispatch (true_type, const contiguous_storage& other) noexcept ;
166
-
167
- _CCCL_HOST_DEVICE void deallocate_on_allocator_mismatch_dispatch (false_type, const contiguous_storage& other) noexcept ;
210
+ _CCCL_EXEC_CHECK_DISABLE
211
+ _CCCL_HOST_DEVICE void deallocate_on_allocator_mismatch_dispatch (true_type, const contiguous_storage& other) noexcept
212
+ {
213
+ if (m_allocator != other.m_allocator )
214
+ {
215
+ deallocate ();
216
+ }
217
+ }
168
218
169
- _CCCL_HOST_DEVICE void destroy_on_allocator_mismatch_dispatch (
170
- true_type, const contiguous_storage& other, iterator first, iterator last) noexcept ;
219
+ _CCCL_HOST_DEVICE static void deallocate_on_allocator_mismatch_dispatch (false_type, const contiguous_storage&) noexcept
220
+ {}
171
221
222
+ _CCCL_EXEC_CHECK_DISABLE
172
223
_CCCL_HOST_DEVICE void destroy_on_allocator_mismatch_dispatch (
173
- false_type, const contiguous_storage& other, iterator first, iterator last) noexcept ;
174
-
175
- _CCCL_HOST_DEVICE void propagate_allocator_dispatch (true_type, const contiguous_storage& other);
176
-
177
- _CCCL_HOST_DEVICE void propagate_allocator_dispatch (false_type, const contiguous_storage& other);
178
-
179
- _CCCL_HOST_DEVICE void propagate_allocator_dispatch (true_type, contiguous_storage& other);
180
-
181
- _CCCL_HOST_DEVICE void propagate_allocator_dispatch (false_type, contiguous_storage& other);
224
+ true_type, const contiguous_storage& other, iterator first, iterator last) noexcept
225
+ {
226
+ if (m_allocator != other.m_allocator )
227
+ {
228
+ destroy (first, last);
229
+ }
230
+ } // end contiguous_storage::destroy_on_allocator_mismatch()
231
+
232
+ _CCCL_HOST_DEVICE static void destroy_on_allocator_mismatch_dispatch (
233
+ false_type, const contiguous_storage& other, iterator first, iterator last) noexcept
234
+ {}
182
235
183
236
friend _CCCL_HOST_DEVICE void swap (contiguous_storage& lhs, contiguous_storage& rhs) noexcept (noexcept (lhs.swap(rhs)))
184
237
{
0 commit comments