2323
2424#if _CCCL_HAS_CTK()
2525
26+ # include < cuda/__memory_resource/properties.h>
2627# include < cuda/std/__concepts/same_as.h>
2728# include < cuda/std/__type_traits/remove_const_ref.h>
2829# include < cuda/std/__type_traits/void_t.h>
@@ -107,9 +108,19 @@ _CCCL_CONCEPT_FRAGMENT(
107108 __has_upstream_resource_,
108109 requires (const _Resource& __res)(
109110 requires (::cuda::std::same_as<::cuda::std::__remove_const_ref_t <decltype (__res.upstream_resource())>, _Upstream>)));
111+
112+ template <class _Resource , class _Upstream >
113+ _CCCL_CONCEPT_FRAGMENT (__has_get_resource_,
114+ requires (const _Resource& __res)(requires (
115+ ::cuda::std::same_as<::cuda::std::__remove_const_ref_t <decltype (__res.get())>, _Upstream>)));
116+ template <class _Resource , class _Upstream >
117+ _CCCL_CONCEPT __has_get_resource = _CCCL_FRAGMENT(__has_get_resource_, _Resource, _Upstream);
118+
110119# endif // ^^^ _CCCL_DOXYGEN_INVOKED ^^^
111120template <class _Resource , class _Upstream >
112- _CCCL_CONCEPT __has_upstream_resource = _CCCL_FRAGMENT(__has_upstream_resource_, _Resource, _Upstream);
121+ _CCCL_CONCEPT __has_forwarded_resource =
122+ _CCCL_FRAGMENT (__has_upstream_resource_, _Resource, _Upstream)
123+ || _CCCL_FRAGMENT(__has_get_resource_, _Resource, _Upstream);
113124
114125_CCCL_BEGIN_NAMESPACE_CPO (__forward_property)
115126template <class _Derived, class _Upstream>
@@ -120,14 +131,35 @@ struct __fn
120131 _CCCL_REQUIRES ((!property_with_value<_Property>) _CCCL_AND has_property<_Upstream, _Property>)
121132 _CCCL_API friend constexpr void get_property (const _Derived&, _Property) noexcept {}
122133
134+ _CCCL_EXEC_CHECK_DISABLE
135+ _CCCL_API friend constexpr auto
136+ get_property (const _Derived& __res, ::cuda::mr::dynamic_accessibility_property __prop) noexcept
137+ {
138+ if constexpr (_CCCL_FRAGMENT (__has_upstream_resource_, _Derived, _Upstream))
139+ {
140+ return get_property (__res.upstream_resource (), __prop);
141+ }
142+ else
143+ {
144+ return get_property (__res.get (), __prop);
145+ }
146+ }
147+
123148 // The indirection is needed, otherwise the compiler might believe that _Derived is an incomplete type
124149 _CCCL_EXEC_CHECK_DISABLE
125150 _CCCL_TEMPLATE (class _Property , class _Derived2 = _Derived)
126151 _CCCL_REQUIRES (property_with_value<_Property> _CCCL_AND has_property<_Upstream, _Property> _CCCL_AND
127- __has_upstream_resource <_Derived2, _Upstream>)
152+ __has_forwarded_resource <_Derived2, _Upstream>)
128153 _CCCL_API friend constexpr __property_value_t <_Property> get_property (const _Derived& __res, _Property __prop)
129154 {
130- return get_property (__res.upstream_resource (), __prop);
155+ if constexpr (_CCCL_FRAGMENT (__has_upstream_resource_, _Derived, _Upstream))
156+ {
157+ return get_property (__res.upstream_resource (), __prop);
158+ }
159+ else
160+ {
161+ return get_property (__res.get (), __prop);
162+ }
131163 }
132164};
133165_CCCL_END_NAMESPACE_CPO
@@ -145,15 +177,36 @@ _CCCL_END_NAMESPACE_CPO
145177// !
146178// ! .. note::
147179// !
148- // ! In order to forward stateful properties, a type needs do implement an `upstream_resource()` method that returns
149- // ! an instance of the upstream.
180+ // ! In order to forward stateful properties, a type needs to implement either:
181+ // ! - an `upstream_resource()` method returning the upstream resource, or
182+ // ! - a `get()` method returning the upstream resource.
150183// !
151184// ! @endrst
152185template <class _Derived , class _Upstream >
153186using forward_property = __forward_property::__fn<_Derived, _Upstream>;
154187
155188_CCCL_END_NAMESPACE_CUDA
156189
190+ _CCCL_BEGIN_NAMESPACE_CUDA_MR
191+
192+ template <class _Tp >
193+ inline constexpr bool __disable_default_dynamic_accessibility_property = false ;
194+
195+ // ! Default implementation: infer from has_property<Resource, host_accessible> and
196+ // ! has_property<Resource, device_accessible>. Resources can override by providing
197+ // ! their own get_property(..., dynamic_accessibility_property).
198+ // ! Excluded for type-erased wrappers (any_resource, resource_ref, etc.) so that
199+ // ! get_property dispatches via their interface to the stored concrete resource.
200+ _CCCL_TEMPLATE (class _Resource )
201+ _CCCL_REQUIRES((!__disable_default_dynamic_accessibility_property<_Resource>) )
202+ _CCCL_API constexpr __memory_accessability
203+ get_property([[maybe_unused]] const _Resource& __res, dynamic_accessibility_property) noexcept
204+ {
205+ return __memory_accessability_from_static_properties<::cuda::has_property<_Resource, host_accessible>,
206+ ::cuda::has_property<_Resource, device_accessible>>();
207+ }
208+ _CCCL_END_NAMESPACE_CUDA_MR
209+
157210# include < cuda/std/__cccl/epilogue.h>
158211
159212#endif // _CCCL_HAS_CTK()
0 commit comments