From 91106381c20507a842a4748cf5889640a383453f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 21 Jul 2021 15:12:02 +0200 Subject: [PATCH] Workaround dynamic cast for private bases. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaƂ Zientkiewicz --- .../resource_view_comparison.pass.cpp | 6 +- include/cuda/memory_resource | 89 ++++++++++++++++--- 2 files changed, 82 insertions(+), 13 deletions(-) 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 index dadffff329..f17975e4f1 100644 --- 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 @@ -29,7 +29,7 @@ class resource : public cuda::memory_resource { void do_deallocate(void *, size_t, size_t) { } -#ifndef _LIBCUDACXX_NO_RTTI +#ifdef _LIBCUDACXX_EXT_RTTI_ENABLED bool do_is_equal(const cuda::memory_resource &other) const noexcept override { fprintf(stderr, "Comparison start: %p %p\n", this, &other); if (auto *other_ptr = dynamic_cast(&other)) { @@ -48,7 +48,7 @@ struct tag2; int main(int argc, char **argv) { -#if !defined(__CUDA_ARCH__) && !defined(_LIBCUDACXX_NO_RTTI) +#if !defined(__CUDA_ARCH__) && defined(_LIBCUDACXX_EXT_RTTI_ENABLED) resource r1, r2, r3; resource r4; r1.value = 42; @@ -68,7 +68,7 @@ int main(int argc, char **argv) { assert(v1 == v2); assert(v1 != v3); assert(v1 != v4); - // assert(v2 != v3); - cannot compare + // assert(v2 != v3); - cannot compare - incompatible views assert(v2 != v4); assert(v3 != v4); assert(v4 == v4); diff --git a/include/cuda/memory_resource b/include/cuda/memory_resource index 6999024dae..1811077161 100644 --- a/include/cuda/memory_resource +++ b/include/cuda/memory_resource @@ -19,6 +19,10 @@ #include "std/version" #include "stream_view" +#ifdef _LIBCUDACXX_EXT_RTTI_ENABLED +#include +#endif + #if _LIBCUDACXX_STD_VER > 14 #include #endif // _LIBCUDACXX_STD_VER > 14 @@ -64,6 +68,44 @@ namespace memory_kind { struct any_context{}; namespace detail { + +namespace __fallback_typeid { + +template +struct _LIBCUDACXX_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; }; +template constexpr int __unique_typeinfo<_Tp>::__id; + +template +inline _LIBCUDACXX_INLINE_VISIBILITY +constexpr const void* __get_fallback_typeid() { + return &__unique_typeinfo>::__id; +} + +template +const ::std::type_info *__get_typeid() { +#ifdef _LIBCUDACXX_EXT_RTTI_ENABLED + return &typeid(_Tp); +#else + return nullptr; +#endif +} + +bool __compare_type(const ::std::type_info *__ti1, const void *__fallback_ti1, + const ::std::type_info *__ti2, const void *__fallback_ti2) { +#ifdef _LIBCUDACXX_EXT_RTTI_ENABLED + if (__ti1 && __ti2 && *__ti1 == *__ti2) + return true; +#endif + return __fallback_ti1 == __fallback_ti2; +} + +template +bool __is_type(const ::std::type_info *__ti1, const void *__fallback_ti1) { + return __compare_type(__ti1, __fallback_ti1, __get_typeid<_Tp>(), __get_fallback_typeid<_Tp>()); +} + +} // namespace __fallback_typeid + template class __get_context_impl { protected: @@ -121,6 +163,9 @@ namespace memory_location { struct host; } +template +class memory_resource; + namespace detail { class memory_resource_base { @@ -168,6 +213,26 @@ public: do_deallocate(__mem, __bytes, __alignment); } + /*! + * \brief Tries to cast the resource to a resource of given kind + */ + template + memory_resource<_Kind> *as_kind() noexcept { + return static_cast *>( + __do_as_kind(detail::__fallback_typeid::__get_typeid<_Kind*>(), + detail::__fallback_typeid::__get_fallback_typeid<_Kind*>())); + } + + /*! + * \brief Tries to cast the resource to a resource of given kind + */ + template + const memory_resource<_Kind> *as_kind() const noexcept { + return static_cast *>( + __do_as_kind(detail::__fallback_typeid::__get_typeid<_Kind*>(), + detail::__fallback_typeid::__get_fallback_typeid<_Kind*>())); + } + 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; @@ -180,6 +245,8 @@ protected: template friend class cuda::basic_resource_view; + + virtual void *__do_as_kind(const ::std::type_info *__kind_type_id, const void *__kind_type_fallback_id) const noexcept = 0; }; class stream_ordered_memory_resource_base : public virtual memory_resource_base { @@ -309,12 +376,12 @@ protected: * \tparam _Context The execution context on which the storage may be used * without synchronization */ -template +template class memory_resource : private virtual detail::memory_resource_base, private detail::__get_context_impl<_Context> { public: using memory_kind = _MemoryKind; using context = _Context; - static constexpr _CUDA_VSTD::size_t default_alignment = memory_resource_base::default_alignment; + static constexpr std::size_t default_alignment = memory_resource_base::default_alignment; virtual ~memory_resource() = default; @@ -396,15 +463,17 @@ private: return this == &__other; } + virtual void *__do_as_kind(const ::std::type_info *__kind_type_id, const void *__kind_type_fallback_id) const noexcept { + return detail::__fallback_typeid::__is_type(__kind_type_id, __kind_type_fallback_id) + ? const_cast(this) : nullptr; + } + bool is_equal_base(const detail::memory_resource_base &__other) const noexcept final override { - #ifdef _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 (auto *__other_res = __other.as_kind()) { + return do_is_equal(*__other_res); + } else { + return false; + } } };