diff --git a/libcudacxx/include/cuda/__container/buffer.h b/libcudacxx/include/cuda/__container/buffer.h index 5e2f48c592b..9437f61ac70 100644 --- a/libcudacxx/include/cuda/__container/buffer.h +++ b/libcudacxx/include/cuda/__container/buffer.h @@ -655,7 +655,7 @@ _CCCL_BEGIN_NAMESPACE_ARCH_DEPENDENT //! @brief Copy-constructs elements in the range `[__first, __first + __count)`. //! @param __first Pointer to the first element to be initialized. //! @param __count The number of elements to be initialized. -template +template _CCCL_HOST_API void __fill_n(cuda::stream_ref __stream, _Tp* __first, ::cuda::std::size_t __count, const _Tp& __value) { if (__count == 0) @@ -665,7 +665,7 @@ _CCCL_HOST_API void __fill_n(cuda::stream_ref __stream, _Tp* __first, ::cuda::st // We don't know what to do with both device and host accessible buffers, so // we need to check the attributes - if constexpr (_Accessability == mr::__memory_accessability::__host_device) + if constexpr (_Accessability == mr::__memory_accessibility ::__host_device) { __driver::__pointer_attribute_value_type_t __type; bool __is_managed{}; @@ -678,14 +678,14 @@ _CCCL_HOST_API void __fill_n(cuda::stream_ref __stream, _Tp* __first, ::cuda::st } if (__type == ::CU_MEMORYTYPE_HOST && !__is_managed) { - __fill_n<_Tp, mr::__memory_accessability::__host>(__stream, __first, __count, __value); + __fill_n<_Tp, mr::__memory_accessibility ::__host>(__stream, __first, __count, __value); } else { - __fill_n<_Tp, mr::__memory_accessability::__device>(__stream, __first, __count, __value); + __fill_n<_Tp, mr::__memory_accessibility ::__device>(__stream, __first, __count, __value); } } - else if constexpr (_Accessability == mr::__memory_accessability::__host) + else if constexpr (_Accessability == mr::__memory_accessibility ::__host) { ::cuda::host_launch( __stream, ::cuda::std::uninitialized_fill_n<_Tp*, ::cuda::std::size_t, _Tp>, __first, __count, __value); @@ -780,7 +780,7 @@ buffer<_Tp, _FirstProperty, _RestProperties...> make_buffer( { auto __res = buffer<_Tp, _FirstProperty, _RestProperties...>{__stream, ::cuda::std::forward<_Resource>(__mr), __size, no_init}; - __fill_n<_Tp, mr::__memory_accessability_from_properties<_FirstProperty, _RestProperties...>::value>( + __fill_n<_Tp, mr::__memory_accessibility_from_properties<_FirstProperty, _RestProperties...>::value>( __stream, __res.__unwrapped_begin(), __size, __value); return __res; } @@ -794,7 +794,7 @@ auto make_buffer( using __default_queries = typename ::cuda::std::decay_t<_Resource>::default_queries; using __buffer_type = __buffer_type_for_props<_Tp, __default_queries>; auto __res = __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __size, no_init}; - __fill_n<_Tp, __default_queries::template rebind::value>( + __fill_n<_Tp, __default_queries::template rebind::value>( __stream, __res.__unwrapped_begin(), __size, __value); return __res; } diff --git a/libcudacxx/include/cuda/__container/heterogeneous_iterator.h b/libcudacxx/include/cuda/__container/heterogeneous_iterator.h index e5f84ce2d33..2aa2d9cb411 100644 --- a/libcudacxx/include/cuda/__container/heterogeneous_iterator.h +++ b/libcudacxx/include/cuda/__container/heterogeneous_iterator.h @@ -61,11 +61,11 @@ template class heterogeneous_iterator; // We restrict all accessors of the iterator based on the execution space -template +template class __heterogeneous_iterator_access; template -class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessability::__host> +class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__host> { public: using iterator_concept = ::cuda::std::contiguous_iterator_tag; @@ -111,7 +111,7 @@ class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_access }; template -class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessability::__device> +class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__device> { public: using iterator_concept = ::cuda::std::contiguous_iterator_tag; @@ -157,7 +157,7 @@ class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_access }; template -class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessability::__host_device> +class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__host_device> { public: using iterator_concept = ::cuda::std::contiguous_iterator_tag; @@ -207,12 +207,12 @@ class heterogeneous_iterator : public __heterogeneous_iterator_access< ::cuda::std::remove_const_t<_CvTp>, ::cuda::std::is_const_v<_CvTp> ? __is_heterogeneous_const_iter::__yes : __is_heterogeneous_const_iter::__no, - ::cuda::mr::__memory_accessability_from_properties<_Properties...>::value> + ::cuda::mr::__memory_accessibility_from_properties<_Properties...>::value> { using __base = __heterogeneous_iterator_access< ::cuda::std::remove_const_t<_CvTp>, ::cuda::std::is_const_v<_CvTp> ? __is_heterogeneous_const_iter::__yes : __is_heterogeneous_const_iter::__no, - ::cuda::mr::__memory_accessability_from_properties<_Properties...>::value>; + ::cuda::mr::__memory_accessibility_from_properties<_Properties...>::value>; public: using iterator_concept = ::cuda::std::contiguous_iterator_tag; diff --git a/libcudacxx/include/cuda/__memory_resource/any_resource.h b/libcudacxx/include/cuda/__memory_resource/any_resource.h index cf470cf4392..9a0ee66ff3e 100644 --- a/libcudacxx/include/cuda/__memory_resource/any_resource.h +++ b/libcudacxx/include/cuda/__memory_resource/any_resource.h @@ -88,7 +88,8 @@ template using __iproperty = typename __with_property<_Property>::template __iproperty<>; template -using __iproperty_set = ::cuda::__iset<__iproperty<_Properties>...>; +using __iproperty_set = + ::cuda::__iset<__iproperty<_Properties>..., __iproperty<::cuda::mr::dynamic_accessibility_property>>; // Wrap the calls of the allocate and deallocate member functions // because of NVBUG#4967486 @@ -359,6 +360,15 @@ struct _CCCL_DECLSPEC_EMPTY_BASES resource_ref } }; +template +inline constexpr bool __disable_default_dynamic_accessibility_property> = true; +template +inline constexpr bool __disable_default_dynamic_accessibility_property> = true; +template +inline constexpr bool __disable_default_dynamic_accessibility_property> = true; +template +inline constexpr bool __disable_default_dynamic_accessibility_property> = true; + _CCCL_TEMPLATE(class... _Properties, class _Resource) _CCCL_REQUIRES(mr::synchronous_resource_with<_Resource, _Properties...>) synchronous_resource_ref<_Properties...> __as_resource_ref(_Resource& __mr) noexcept diff --git a/libcudacxx/include/cuda/__memory_resource/get_property.h b/libcudacxx/include/cuda/__memory_resource/get_property.h index 75f9552f4b1..8ab78e65891 100644 --- a/libcudacxx/include/cuda/__memory_resource/get_property.h +++ b/libcudacxx/include/cuda/__memory_resource/get_property.h @@ -23,6 +23,7 @@ #if _CCCL_HAS_CTK() +# include # include # include # include @@ -93,23 +94,21 @@ _CCCL_CONCEPT property_with_value = _CCCL_REQUIRES_EXPR((_Property))(typename(__ //! @endrst # ifndef _CCCL_DOXYGEN_INVOKED // Doxygen chokes here template -_CCCL_CONCEPT_FRAGMENT(__has_property_with_, - requires(const _Resource& __res)( - requires(property_with_value<_Property>), - requires(::cuda::std::same_as<_Return, decltype(get_property(__res, _Property{}))>))); -# endif // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ -template -_CCCL_CONCEPT has_property_with = _CCCL_FRAGMENT(__has_property_with_, _Resource, _Property, _Return); +_CCCL_CONCEPT has_property_with = _CCCL_REQUIRES_EXPR((_Resource, _Property, _Return), const _Resource& __res)( + requires(property_with_value<_Property>), _Same_as(_Return) get_property(__res, _Property{})); -# ifndef _CCCL_DOXYGEN_INVOKED // Doxygen chokes here template -_CCCL_CONCEPT_FRAGMENT( - __has_upstream_resource_, - requires(const _Resource& __res)( - requires(::cuda::std::same_as<::cuda::std::__remove_const_ref_t, _Upstream>))); +_CCCL_CONCEPT __has_upstream_resource = _CCCL_REQUIRES_EXPR((_Resource, _Upstream), const _Resource& __res)( + requires(::cuda::std::same_as<::cuda::std::__remove_const_ref_t, _Upstream>)); + +template +_CCCL_CONCEPT __has_get_resource = _CCCL_REQUIRES_EXPR((_Resource, _Upstream), const _Resource& __res)( + requires(::cuda::std::same_as<::cuda::std::__remove_const_ref_t, _Upstream>)); # endif // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ + template -_CCCL_CONCEPT __has_upstream_resource = _CCCL_FRAGMENT(__has_upstream_resource_, _Resource, _Upstream); +_CCCL_CONCEPT __has_forwarded_resource = + __has_upstream_resource<_Resource, _Upstream> || __has_get_resource<_Resource, _Upstream>; _CCCL_BEGIN_NAMESPACE_CPO(__forward_property) template @@ -120,14 +119,35 @@ struct __fn _CCCL_REQUIRES((!property_with_value<_Property>) _CCCL_AND has_property<_Upstream, _Property>) _CCCL_API friend constexpr void get_property(const _Derived&, _Property) noexcept {} + _CCCL_EXEC_CHECK_DISABLE + _CCCL_API friend constexpr auto + get_property(const _Derived& __res, ::cuda::mr::dynamic_accessibility_property __prop) noexcept + { + if constexpr (__has_upstream_resource<_Derived, _Upstream>) + { + return get_property(__res.upstream_resource(), __prop); + } + else + { + return get_property(__res.get(), __prop); + } + } + // The indirection is needed, otherwise the compiler might believe that _Derived is an incomplete type _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Property, class _Derived2 = _Derived) _CCCL_REQUIRES(property_with_value<_Property> _CCCL_AND has_property<_Upstream, _Property> _CCCL_AND - __has_upstream_resource<_Derived2, _Upstream>) + __has_forwarded_resource<_Derived2, _Upstream>) _CCCL_API friend constexpr __property_value_t<_Property> get_property(const _Derived& __res, _Property __prop) { - return get_property(__res.upstream_resource(), __prop); + if constexpr (__has_upstream_resource<_Derived, _Upstream>) + { + return get_property(__res.upstream_resource(), __prop); + } + else + { + return get_property(__res.get(), __prop); + } } }; _CCCL_END_NAMESPACE_CPO @@ -145,8 +165,9 @@ _CCCL_END_NAMESPACE_CPO //! //! .. note:: //! -//! In order to forward stateful properties, a type needs do implement an `upstream_resource()` method that returns -//! an instance of the upstream. +//! In order to forward stateful properties, a type needs to implement either: +//! - an `upstream_resource()` method returning the upstream resource, or +//! - a `get()` method returning the upstream resource. //! //! @endrst template @@ -154,6 +175,26 @@ using forward_property = __forward_property::__fn<_Derived, _Upstream>; _CCCL_END_NAMESPACE_CUDA +_CCCL_BEGIN_NAMESPACE_CUDA_MR + +template +inline constexpr bool __disable_default_dynamic_accessibility_property = false; + +//! Default implementation: infer from has_property and +//! has_property. Resources can override by providing +//! their own get_property(..., dynamic_accessibility_property). +//! Excluded for type-erased wrappers (any_resource, resource_ref, etc.) so that +//! get_property dispatches via their interface to the stored concrete resource. +_CCCL_TEMPLATE(class _Resource) +_CCCL_REQUIRES((!__disable_default_dynamic_accessibility_property<_Resource>) ) +_CCCL_API constexpr __memory_accessibility +get_property([[maybe_unused]] const _Resource& __res, dynamic_accessibility_property) noexcept +{ + return __memory_accessibility_from_static_properties<::cuda::has_property<_Resource, host_accessible>, + ::cuda::has_property<_Resource, device_accessible>>(); +} +_CCCL_END_NAMESPACE_CUDA_MR + # include #endif // _CCCL_HAS_CTK() diff --git a/libcudacxx/include/cuda/__memory_resource/properties.h b/libcudacxx/include/cuda/__memory_resource/properties.h index 6eac8634755..d6fd3e399dd 100644 --- a/libcudacxx/include/cuda/__memory_resource/properties.h +++ b/libcudacxx/include/cuda/__memory_resource/properties.h @@ -108,21 +108,37 @@ template struct __copy_default_queries<_Resource, false> {}; -enum class __memory_accessability +enum class __memory_accessibility { + __unknown, __host, __device, __host_device, }; +//! @brief The dynamic_accessibility_property reports the resource's memory accessibility at runtime. +//! Compared to the static properties, it can be used to query the memory accessibility of a resource that is not known +//! at compile time. +struct dynamic_accessibility_property +{ + using value_type = __memory_accessibility; +}; + +template +_CCCL_API constexpr __memory_accessibility __memory_accessibility_from_static_properties() noexcept +{ + return _HostAccessible && _DeviceAccessible ? __memory_accessibility ::__host_device + : _DeviceAccessible ? __memory_accessibility ::__device + : _HostAccessible ? __memory_accessibility ::__host + : __memory_accessibility ::__unknown; +} + template -struct __memory_accessability_from_properties +struct __memory_accessibility_from_properties { - static constexpr __memory_accessability value = - ::cuda::mr::__is_host_device_accessible<_Properties...> ? __memory_accessability::__host_device - : ::cuda::mr::__is_device_accessible<_Properties...> - ? __memory_accessability::__device - : __memory_accessability::__host; + static constexpr __memory_accessibility value = + __memory_accessibility_from_static_properties<::cuda::mr::__is_host_accessible<_Properties...>, + ::cuda::mr::__is_device_accessible<_Properties...>>(); }; _CCCL_END_NAMESPACE_CUDA_MR diff --git a/libcudacxx/include/cuda/__memory_resource/shared_resource.h b/libcudacxx/include/cuda/__memory_resource/shared_resource.h index ef80e3b8c2f..88fdb63ec69 100644 --- a/libcudacxx/include/cuda/__memory_resource/shared_resource.h +++ b/libcudacxx/include/cuda/__memory_resource/shared_resource.h @@ -50,7 +50,9 @@ _CCCL_BEGIN_NAMESPACE_CUDA_MR //! @tparam _Resource The resource type to hold. //! @endrst template -struct shared_resource : ::cuda::mr::__copy_default_queries<_Resource> +struct shared_resource + : ::cuda::mr::__copy_default_queries<_Resource> + , ::cuda::forward_property, _Resource> { static_assert(::cuda::mr::synchronous_resource<_Resource>, ""); @@ -255,19 +257,6 @@ struct shared_resource : ::cuda::mr::__copy_default_queries<_Resource> return !(__lhs == __rhs); } - //! @brief Forwards the stateless properties - _CCCL_TEMPLATE(class _Property) - _CCCL_REQUIRES((!property_with_value<_Property>) _CCCL_AND(has_property<_Resource, _Property>)) - friend void get_property(const shared_resource&, _Property) noexcept {} - - //! @brief Forwards the stateful properties - _CCCL_TEMPLATE(class _Property) - _CCCL_REQUIRES(property_with_value<_Property> _CCCL_AND(has_property<_Resource, _Property>)) - [[nodiscard]] friend __property_value_t<_Property> get_property(const shared_resource& __self, _Property) noexcept - { - return get_property(__self.__control_block->__resource, _Property{}); - } - private: // Use a custom shared_ptr implementation because (a) we don't need to support weak_ptr so we only // need one pointer, not two, and (b) this implementation can work on device also. diff --git a/libcudacxx/include/cuda/__utility/__basic_any/iset.h b/libcudacxx/include/cuda/__utility/__basic_any/iset.h index 2e59f59e8f7..73a7d5aa14b 100644 --- a/libcudacxx/include/cuda/__utility/__basic_any/iset.h +++ b/libcudacxx/include/cuda/__utility/__basic_any/iset.h @@ -60,10 +60,49 @@ using __iset_flatten _CCCL_NODEBUG_ALIAS = ::cuda::std::__as_type_list< // using __iset _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_call< // ::cuda::std::__type_unique<::cuda::std::__type_sort<::cuda::std::__type_concat<__iset_flatten<_Interfaces>...>>>, // ::cuda::std::__type_quote<__iset_>>; +// GCC 7 had a problem with the original implementation, so we use a workaround. +#if _CCCL_COMPILER(GCC, <, 8) +template +struct __iset_cat; + +template +struct __iset_cat<::cuda::std::__type_list<_Lhs...>, ::cuda::std::__type_list<_Rhs...>> +{ + using type = ::cuda::std::__type_list<_Lhs..., _Rhs...>; +}; + +template +struct __iset_flatten_all; + +template <> +struct __iset_flatten_all<> +{ + using type = ::cuda::std::__type_list<>; +}; + +template +struct __iset_flatten_all<__iset_<_Nested...>, _Rest...> +{ + using type = typename __iset_cat::type, + typename __iset_flatten_all<_Rest...>::type>::type; +}; + +template +struct __iset_flatten_all<_Interface, _Rest...> +{ + using type = + typename __iset_cat<::cuda::std::__type_list<_Interface>, typename __iset_flatten_all<_Rest...>::type>::type; +}; + +template +using __iset = ::cuda::std::__type_call<::cuda::std::__type_unique::type>, + ::cuda::std::__type_quote<__iset_>>; +#else // ^^^ _CCCL_COMPILER(GCC, <, 8) ^^^ / vvv _CCCL_COMPILER(GCC, >=, 8) vvv template using __iset = ::cuda::std::__type_call<::cuda::std::__type_unique<::cuda::std::__type_concat<__iset_flatten<_Interfaces>...>>, ::cuda::std::__type_quote<__iset_>>; +#endif // _CCCL_COMPILER(GCC, >=, 8) //! //! Virtual table pointers diff --git a/libcudacxx/test/libcudacxx/cuda/memory_resource/any_resource/any_resource.cu b/libcudacxx/test/libcudacxx/cuda/memory_resource/any_resource/any_resource.cu index 6a830922ddd..d260d394290 100644 --- a/libcudacxx/test/libcudacxx/cuda/memory_resource/any_resource/any_resource.cu +++ b/libcudacxx/test/libcudacxx/cuda/memory_resource/any_resource/any_resource.cu @@ -228,6 +228,34 @@ struct host_device_resource static_assert(cuda::has_property); static_assert(cuda::has_property); +struct explicit_dynamic_resource +{ + void* allocate(cuda::stream_ref, size_t, size_t) + { + return nullptr; + } + void deallocate(cuda::stream_ref, void*, size_t, size_t) noexcept {} + void* allocate_sync(size_t, size_t) + { + return nullptr; + } + void deallocate_sync(void*, size_t, size_t) noexcept {} + friend bool operator==(const explicit_dynamic_resource&, const explicit_dynamic_resource&) noexcept + { + return true; + } + friend bool operator!=(const explicit_dynamic_resource&, const explicit_dynamic_resource&) noexcept + { + return false; + } + friend constexpr void get_property(const explicit_dynamic_resource&, cuda::mr::host_accessible) noexcept {} + friend constexpr cuda::mr::__memory_accessibility + get_property(const explicit_dynamic_resource&, cuda::mr::dynamic_accessibility_property) noexcept + { + return cuda::mr::__memory_accessibility ::__device; + } +}; + void requires_host(cuda::mr::resource_ref) {} void requires_device(cuda::mr::resource_ref) {} @@ -265,6 +293,22 @@ TEST_CASE("resource_ref regression test for cccl#6839", "[container][resource]") CHECK(checks_device_runtime_resource_ref(ref)); // Test that we are device accessible } +TEST_CASE("dynamic_accessibility_property in type-erased wrappers", "[container][resource]") +{ + cuda::mr::any_resource host_device_any{host_device_resource{}}; + CHECK(get_property(host_device_any, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__host_device); + + cuda::mr::any_resource explicit_any{explicit_dynamic_resource{}}; + CHECK(get_property(explicit_any, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__device); + + host_device_resource host_device_mr{}; + cuda::mr::resource_ref host_device_ref{host_device_mr}; + CHECK(get_property(host_device_ref, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__host_device); +} + TEMPLATE_TEST_CASE_METHOD(test_fixture, "Empty property set", "[container][resource]", big_resource, small_resource) { using TestResource = TestType; diff --git a/libcudacxx/test/libcudacxx/cuda/memory_resource/get_property/forward_property.pass.cpp b/libcudacxx/test/libcudacxx/cuda/memory_resource/get_property/forward_property.pass.cpp index 34764b0dc29..a41a9490066 100644 --- a/libcudacxx/test/libcudacxx/cuda/memory_resource/get_property/forward_property.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/memory_resource/get_property/forward_property.pass.cpp @@ -14,7 +14,7 @@ #include #include -namespace has_upstream_resource +namespace has_forwarded_resource { struct Upstream {}; @@ -28,7 +28,7 @@ struct with_reference return upstream; } }; -static_assert(cuda::__has_upstream_resource, ""); +static_assert(cuda::__has_forwarded_resource, ""); struct with_const_reference { @@ -37,7 +37,7 @@ struct with_const_reference return upstream; } }; -static_assert(cuda::__has_upstream_resource, ""); +static_assert(cuda::__has_forwarded_resource, ""); struct with_value { @@ -46,7 +46,7 @@ struct with_value return Upstream{}; } }; -static_assert(cuda::__has_upstream_resource, ""); +static_assert(cuda::__has_forwarded_resource, ""); struct with_const_value { @@ -55,7 +55,7 @@ struct with_const_value return Upstream{}; } }; -static_assert(cuda::__has_upstream_resource, ""); +static_assert(cuda::__has_forwarded_resource, ""); struct Convertible { @@ -72,8 +72,26 @@ struct with_conversion return Convertible{}; } }; -static_assert(!cuda::__has_upstream_resource, ""); -} // namespace has_upstream_resource +static_assert(!cuda::__has_forwarded_resource, ""); + +struct with_get_reference +{ + Upstream& get() const + { + return upstream; + } +}; +static_assert(cuda::__has_forwarded_resource, ""); + +struct with_get_conversion +{ + Convertible get() const + { + return Convertible{}; + } +}; +static_assert(!cuda::__has_forwarded_resource, ""); +} // namespace has_forwarded_resource namespace forward_property { diff --git a/libcudacxx/test/libcudacxx/cuda/memory_resource/properties/properties.pass.cpp b/libcudacxx/test/libcudacxx/cuda/memory_resource/properties/properties.pass.cpp index 086e60afdb9..c88fb3909df 100644 --- a/libcudacxx/test/libcudacxx/cuda/memory_resource/properties/properties.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/memory_resource/properties/properties.pass.cpp @@ -36,6 +36,46 @@ static_assert(!cuda::mr::__is_host_device_accessible, static_assert(!cuda::mr::__is_host_device_accessible, ""); static_assert(cuda::mr::__is_host_device_accessible, ""); +struct host_only_resource +{ + friend constexpr void get_property(const host_only_resource&, cuda::mr::host_accessible) noexcept {} +}; + +struct device_only_resource +{ + friend constexpr void get_property(const device_only_resource&, cuda::mr::device_accessible) noexcept {} +}; + +struct host_device_resource +{ + friend constexpr void get_property(const host_device_resource&, cuda::mr::host_accessible) noexcept {} + friend constexpr void get_property(const host_device_resource&, cuda::mr::device_accessible) noexcept {} +}; + +struct explicit_dynamic_resource +{ + friend constexpr void get_property(const explicit_dynamic_resource&, cuda::mr::host_accessible) noexcept {} + friend constexpr cuda::mr::__memory_accessibility + get_property(const explicit_dynamic_resource&, cuda::mr::dynamic_accessibility_property) noexcept + { + return cuda::mr::__memory_accessibility ::__device; + } +}; + +static_assert(cuda::has_property); +static_assert(cuda::has_property); +static_assert(cuda::has_property); +static_assert(cuda::has_property); + +static_assert(get_property(host_only_resource{}, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__host); +static_assert(get_property(device_only_resource{}, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__device); +static_assert(get_property(host_device_resource{}, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__host_device); +static_assert(get_property(explicit_dynamic_resource{}, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__device); + int main(int, char**) { return 0; diff --git a/libcudacxx/test/libcudacxx/cuda/memory_resource/shared_resource.cu b/libcudacxx/test/libcudacxx/cuda/memory_resource/shared_resource.cu index c26f271d47b..f821714cf29 100644 --- a/libcudacxx/test/libcudacxx/cuda/memory_resource/shared_resource.cu +++ b/libcudacxx/test/libcudacxx/cuda/memory_resource/shared_resource.cu @@ -163,6 +163,12 @@ TEMPLATE_TEST_CASE_METHOD(test_fixture, "shared_resource", "[container][resource CHECK(this->counts == expected); } + SECTION("dynamic_accessibility_property forwards through shared_resource") + { + cuda::mr::shared_resource mr{cuda::std::in_place_type, 42, this}; + CHECK(get_property(mr, cuda::mr::dynamic_accessibility_property{}) == cuda::mr::__memory_accessibility ::__host); + } + // Reset the counters: this->counts = Counts(); diff --git a/libcudacxx/test/libcudacxx/cuda/memory_resource/synchronous_adapter.cu b/libcudacxx/test/libcudacxx/cuda/memory_resource/synchronous_adapter.cu index 4afb7b0c8e5..820dbe28d82 100644 --- a/libcudacxx/test/libcudacxx/cuda/memory_resource/synchronous_adapter.cu +++ b/libcudacxx/test/libcudacxx/cuda/memory_resource/synchronous_adapter.cu @@ -28,7 +28,23 @@ constexpr bool passed_property = template constexpr bool same_properties = passed_property && passed_property - && passed_property && passed_property; + && passed_property && passed_property + && passed_property; + +struct explicit_dynamic_resource +{ + void* allocate_sync(size_t, size_t) + { + return nullptr; + } + void deallocate_sync(void*, size_t, size_t) noexcept {} + friend constexpr void get_property(const explicit_dynamic_resource&, cuda::mr::host_accessible) noexcept {} + friend constexpr cuda::mr::__memory_accessibility + get_property(const explicit_dynamic_resource&, cuda::mr::dynamic_accessibility_property) noexcept + { + return cuda::mr::__memory_accessibility ::__device; + } +}; C2H_CCCLRT_TEST("synchronous_resource_adapter", "[memory_resource]") { @@ -70,4 +86,12 @@ C2H_CCCLRT_TEST("synchronous_resource_adapter", "[memory_resource]") STATIC_CHECK(same_default_queries); STATIC_CHECK(same_default_queries); } + + SECTION("explicit dynamic_accessibility_property overrides template") + { + cuda::mr::synchronous_resource_adapter adapter{explicit_dynamic_resource{}}; + STATIC_CHECK(cuda::has_property); + CHECK(get_property(adapter, cuda::mr::dynamic_accessibility_property{}) + == cuda::mr::__memory_accessibility ::__device); + } }