diff --git a/.upstream-tests/test/cuda/memory_resource/resource_view/basic_resource_view_interface_propagation.pass.cpp b/.upstream-tests/test/cuda/memory_resource/resource_view/basic_resource_view_interface_propagation.pass.cpp index 8dc781a7cd..e0e5a406dd 100644 --- a/.upstream-tests/test/cuda/memory_resource/resource_view/basic_resource_view_interface_propagation.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/resource_view/basic_resource_view_interface_propagation.pass.cpp @@ -16,8 +16,6 @@ #include #include #include -#include "resource_hierarchy.h" - class sync_resource : public cuda::memory_resource { public: diff --git a/.upstream-tests/test/cuda/memory_resource/resource_view/resource_pointer_compatibility.pass.cpp b/.upstream-tests/test/cuda/memory_resource/resource_view/resource_pointer_compatibility.pass.cpp index e262906ad0..742aaa659e 100644 --- a/.upstream-tests/test/cuda/memory_resource/resource_view/resource_pointer_compatibility.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/resource_view/resource_pointer_compatibility.pass.cpp @@ -26,7 +26,7 @@ int main(int argc, char **argv) { static_assert(cuda::detail::is_resource_pointer_convertible*>::value, "A pointer to a derived class should be convertible to a pointer of public a base class"); - static_assert(cuda::detail::is_resource_pointer_convertible::value, + static_assert(cuda::detail::is_resource_pointer_convertible::value, "A pointer to a derived memory resource should be convertible to a pointer to the common base."); static_assert(cuda::detail::is_resource_pointer_convertible::value, @@ -35,7 +35,7 @@ int main(int argc, char **argv) { static_assert(cuda::detail::is_resource_pointer_convertible*>::value, "A pointer to a derived class should be convertible to a pointer of public a base class"); - static_assert(cuda::detail::is_resource_pointer_convertible::value, + static_assert(cuda::detail::is_resource_pointer_convertible::value, "A pointer to a derived memory resource should be convertible to a pointer to the common base."); @@ -51,13 +51,13 @@ int main(int argc, char **argv) { static_assert(!cuda::detail::is_resource_pointer_convertible*>::value, "A pointer to a synchronous resource should not be convertible to a stream ordered one"); - static_assert(!cuda::detail::is_resource_pointer_convertible::value, + static_assert(!cuda::detail::is_resource_pointer_convertible::value, "A pointer to a synchronous resource should not be convertible to a stream ordered one"); - static_assert(!cuda::detail::is_resource_pointer_convertible*>::value, + static_assert(!cuda::detail::is_resource_pointer_convertible*>::value, "A pointer to a commnon base class should not be convertible to a pointer to a kind-qualified resource."); - static_assert(!cuda::detail::is_resource_pointer_convertible*>::value, + static_assert(!cuda::detail::is_resource_pointer_convertible*>::value, "A pointer to a commnon base class should not be convertible to a pointer to a kind-qualified resource."); static_assert(!cuda::detail::is_resource_pointer_convertible< diff --git a/.upstream-tests/test/cuda/memory_resource/resource_view/resource_view_comparison.pass.cpp b/.upstream-tests/test/cuda/memory_resource/resource_view/resource_view_comparison.pass.cpp new file mode 100644 index 0000000000..f650a1183c --- /dev/null +++ b/.upstream-tests/test/cuda/memory_resource/resource_view/resource_view_comparison.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of libcu++, the C++ Standard Library for your entire system, +// under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + + +#include +#include +#include +#include +#include +#include +#include + + +template +class resource : public cuda::memory_resource { +public: + int value = 0; +private: + void *do_allocate(size_t, size_t) override { + return nullptr; + } + + void do_deallocate(void *, size_t, size_t) { + } + +#ifndef _LIBCUDACXX_NO_RTTI + bool do_is_equal(const cuda::memory_resource &other) const noexcept override { + if (auto *other_ptr = dynamic_cast(&other)) { + return value == other_ptr->value; + } else { + return false; + } + } +#endif +}; + + +struct tag1; +struct tag2; + +int main(int argc, char **argv) { +#if !defined(__CUDA_ARCH__) && !defined(_LIBCUDACXX_NO_RTTI) + resource r1, r2, r3; + resource r4; + r1.value = 42; + r2.value = 42; + r3.value = 99; + r4.value = 42; + + assert(view_resource(&r1) == view_resource(&r2)); + assert(view_resource(&r1) != view_resource(&r3)); + assert(view_resource(&r1) == view_resource(&r4)); +#endif + return 0; +} diff --git a/include/cuda/memory_resource b/include/cuda/memory_resource index 8c93977b5b..a6ddc7feaf 100644 --- a/include/cuda/memory_resource +++ b/include/cuda/memory_resource @@ -121,6 +121,7 @@ namespace memory_location { struct host; } +namespace detail { class memory_resource_base { public: @@ -167,8 +168,18 @@ public: do_deallocate(__mem, __bytes, __alignment); } +protected: virtual void *do_allocate(size_t __bytes, size_t __alignment) = 0; virtual void do_deallocate(void *__mem, size_t __bytes, size_t __alignment) = 0; + + virtual bool is_equal_base(const memory_resource_base &other) const noexcept = 0; + + bool is_equal(const memory_resource_base &other) const noexcept { + return is_equal_base(other); + } + + template + friend class basic_resource_view; }; class stream_ordered_memory_resource_base : public virtual memory_resource_base { @@ -280,10 +291,17 @@ public: void deallocate_async(void *__mem, size_t __bytes, size_t __alignment, stream_view __stream) { do_deallocate_async(__mem, __bytes, __alignment, __stream); } + +protected: virtual void *do_allocate_async(size_t __bytes, size_t __alignment, stream_view __stream) = 0; virtual void do_deallocate_async(void *__mem, size_t __bytes, size_t __alignment, stream_view __stream) = 0; + + template + friend class basic_resource_view; }; +} // namespace detail + /*! * \brief Abstract interface for context specific memory allocation. * @@ -292,7 +310,7 @@ public: * without synchronization */ template -class memory_resource : private virtual memory_resource_base, private detail::__get_context_impl<_Context> { +class memory_resource : private virtual detail::memory_resource_base, private detail::__get_context_impl<_Context> { public: using memory_kind = _MemoryKind; using context = _Context; @@ -374,9 +392,21 @@ private: std::size_t __alignment) = 0; // Default to identity comparison - virtual bool do_is_equal(memory_resource const &__other) const noexcept{ + virtual bool do_is_equal(memory_resource const &__other) const noexcept { + return this == &__other; + } + + bool is_equal_base(const detail::memory_resource_base &__other) const noexcept final override { + #if _LIBCUDACXX_NO_RTTI return this == &__other; + #else + if (auto *__other_res = dynamic_cast(&__other)) + return do_is_equal(__other_res); + else + return false; + #endif } + }; #if _LIBCUDACXX_STD_VER > 14 @@ -465,7 +495,7 @@ private: */ template class stream_ordered_memory_resource : public virtual memory_resource<_MemoryKind>, - private virtual stream_ordered_memory_resource_base { + private virtual detail::stream_ordered_memory_resource_base { public: using memory_kind = _MemoryKind; static constexpr _CUDA_VSTD::size_t default_alignment = memory_resource<_MemoryKind>::default_alignment; @@ -687,15 +717,15 @@ struct is_resource_pointer_convertible : _CUDA_VSTD::is_convertible<_FromPointer // Private inheritance from (stream_ordered_)memory_resource_base* requires explicit partial specializations as `is_convertible` will return false template -struct is_resource_pointer_convertible<_FromPointer, memory_resource_base*> +struct is_resource_pointer_convertible<_FromPointer, detail::memory_resource_base*> : _CUDA_VSTD::conjunction<_CUDA_VSTD::is_pointer<_FromPointer>, - _CUDA_VSTD::is_base_of::element_type>> {}; template -struct is_resource_pointer_convertible<_FromPointer, stream_ordered_memory_resource_base*> +struct is_resource_pointer_convertible<_FromPointer, detail::stream_ordered_memory_resource_base*> : _CUDA_VSTD::conjunction<_CUDA_VSTD::is_pointer<_FromPointer>, - _CUDA_VSTD::is_base_of::element_type>> {}; } // namespace detail @@ -719,16 +749,17 @@ struct is_view_convertible< * Resource view is an object that acts as a memory resource pointer, but provides * enhanced implicit conversions. The idea behind this type is that a user of * a memory resource may be interested in many kinds of resources as long as they - * have certain properties - for example, a function may work with any resource - * that can provide host-accessible memory - be it plain host memory, pinned memory - * or managed memory or some future kind of memory, not yet defined. + * have certain properties. For example, a function may work with any resource + * that can provide host-accessible memory, regardless of whether it is plain host + * memory, pinned memory, managed memory, or some,yet-to-be-defined future kind + * of memory. * * A resource view can be created from a memory resource pointer or from another - * resource view, which defines a superset of the target properties. + * resource view that defines a superset of the target properties. * - * The resource view exposes ther underlying resource's interface via `operator->`. + * The resource view exposes the underlying resource's interface via `operator->`. * - * The `basic_resource_view` class can be parameterized with te resource pointer type, + * The `basic_resource_view` class can be parameterized with the resource pointer type, * which can be either one of the base resource classes or a concrete resource type. * * \tparam _ResourcePointer a pointer-like object to the underlying memory resource @@ -738,9 +769,9 @@ template class basic_resource_view { public: static_assert( - _CUDA_VSTD::is_base_of::element_type>::value || - _CUDA_VSTD::is_base_of::element_type>::value, - "ResourcePointer must be a pointer to a memory_resource_base, stream_ordered_memory_resource_base or a derived class"); + _CUDA_VSTD::is_base_of::element_type>::value || + _CUDA_VSTD::is_base_of::element_type>::value, + "ResourcePointer must be a pointer to a memory_resource_base, stream_ordered_memory_resource_base or a derived class"); basic_resource_view() = default; @@ -781,7 +812,23 @@ public: * * \note This method should not be used to obtain the pointer to the memory resource. */ - _ResourcePointer operator->() const { return __pointer; } + _ResourcePointer operator->() const noexcept { return __pointer; } + + + template + bool operator==(const cuda::basic_resource_view<_Ptr2, _Props2...> &__v2) const noexcept { + using __view1_t = basic_resource_view; + using __view2_t = basic_resource_view<_Ptr2, _Props2...>; + static_assert(cuda::is_view_convertible<__view1_t, __view2_t>::value || cuda::is_view_convertible<__view2_t, __view1_t>::value, + "The resource views are not compatible"); + return static_cast(__pointer)->is_equal(__v2.pointer); + } + + template + bool operator!=(const cuda::basic_resource_view<_Ptr2, _Props2...> &__v2) const noexcept { + return !(*this == __v2); + } + private: template @@ -790,16 +837,24 @@ private: _ResourcePointer __pointer{}; }; -template -basic_resource_view<_ResourcePointer, _Properties...> view_resource(_ResourcePointer __rsrc_ptr) { +template +basic_resource_view<_ResourcePointer, _FirstProperty, _Properties...> +view_resource(_ResourcePointer __rsrc_ptr) { + return __rsrc_ptr; +} + + +template +basic_resource_view<_ResourcePointer, is_kind::memory_kind>> +view_resource(_ResourcePointer __rsrc_ptr) { return __rsrc_ptr; } template -using resource_view = basic_resource_view; +using resource_view = basic_resource_view; template -using stream_ordered_resource_view = basic_resource_view; +using stream_ordered_resource_view = basic_resource_view; _LIBCUDACXX_END_NAMESPACE_CUDA