From f4194736b62a00dddadadc7e3aa73840a36ccb26 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 8 Dec 2022 10:20:32 +0100 Subject: [PATCH] Move properties out of namespace mr and add `forward_property` helper --- .../get_property/forward_property.pass.cpp | 75 +++++++++++++++ .../has_property.pass.cpp | 28 +++--- .../async_resource_ref.construction.pass.cpp | 4 +- .../async_resource_ref.conversion.pass.cpp | 4 +- .../async_resource_ref.equality.fail.cpp | 4 +- .../async_resource_ref.equality.pass.cpp | 4 +- .../async_resource_ref.inheritance.pass.cpp | 4 +- .../async_resource_ref.properties.pass.cpp | 26 ++--- .../resource_ref.construction.pass.cpp | 4 +- .../resource_ref.conversion.pass.cpp | 4 +- .../resource_ref.equality.fail.cpp | 4 +- .../resource_ref.equality.pass.cpp | 4 +- .../resource_ref.inheritance.pass.cpp | 4 +- .../resource_ref.properties.pass.cpp | 26 ++--- include/cuda/memory_resource | 96 ++++++++++++------- 15 files changed, 195 insertions(+), 96 deletions(-) create mode 100644 .upstream-tests/test/cuda/memory_resource/get_property/forward_property.pass.cpp rename .upstream-tests/test/cuda/memory_resource/{memory_resource.concepts => get_property}/has_property.pass.cpp (58%) diff --git a/.upstream-tests/test/cuda/memory_resource/get_property/forward_property.pass.cpp b/.upstream-tests/test/cuda/memory_resource/get_property/forward_property.pass.cpp new file mode 100644 index 0000000000..c6f8597f19 --- /dev/null +++ b/.upstream-tests/test/cuda/memory_resource/get_property/forward_property.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, 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 +// SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 + +// cuda::forward_property +#include +#include + +struct prop_with_value { + using value_type = int; +}; +struct prop {}; + +template +struct derived_plain : public cuda::forward_property, Upstream> +{ + __host__ __device__ constexpr Upstream upstream_resource() const noexcept { return Upstream{}; } +}; + +struct upstream_with_valueless_property { + __host__ __device__ friend constexpr void get_property(const upstream_with_valueless_property&, prop) {} +}; +static_assert( cuda::has_property, prop>, ""); +static_assert(!cuda::has_property, prop_with_value>, ""); + +struct upstream_with_stateful_property { + __host__ __device__ friend constexpr int get_property(const upstream_with_stateful_property&, prop_with_value) { + return 42; + } +}; +static_assert(!cuda::has_property, prop>, ""); +static_assert( cuda::has_property, prop_with_value>, ""); + +struct upstream_with_both_properties { + __host__ __device__ friend constexpr void get_property(const upstream_with_both_properties&, prop) {} + __host__ __device__ friend constexpr int get_property(const upstream_with_both_properties&, prop_with_value) { + return 42; + } +}; +static_assert( cuda::has_property, prop>, ""); +static_assert( cuda::has_property, prop_with_value>, ""); + +struct derived_override : public cuda::forward_property +{ + __host__ __device__ constexpr upstream_with_both_properties upstream_resource() const noexcept { + return upstream_with_both_properties{}; + } + __host__ __device__ friend constexpr int get_property(const derived_override&, prop_with_value) { + return 1337; + } +}; + +__host__ __device__ constexpr bool test_stateful() { + using derived_no_override = derived_plain; + const derived_no_override without_override{}; + assert(get_property(without_override, prop_with_value{}) == 42); + + const derived_override with_override{}; + assert(get_property(with_override, prop_with_value{}) == 1337); + + return true; +} + +int main(int, char**) { + test_stateful(); + static_assert(test_stateful(), ""); + return 0; +} diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.concepts/has_property.pass.cpp b/.upstream-tests/test/cuda/memory_resource/get_property/has_property.pass.cpp similarity index 58% rename from .upstream-tests/test/cuda/memory_resource/memory_resource.concepts/has_property.pass.cpp rename to .upstream-tests/test/cuda/memory_resource/get_property/has_property.pass.cpp index 9a727de082..6090c88f35 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.concepts/has_property.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/get_property/has_property.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11 -// cuda::mr::has_property, cuda::mr::has_property_with +// cuda::has_property, cuda::has_property_with #include struct prop_with_value { @@ -17,15 +17,15 @@ struct prop_with_value { }; struct prop {}; -static_assert(cuda::mr::property_with_value); -static_assert(!cuda::mr::property_with_value); +static_assert(cuda::property_with_value); +static_assert(!cuda::property_with_value); struct valid_property { friend void get_property(const valid_property&, prop) {} }; -static_assert(!cuda::mr::has_property, ""); -static_assert(cuda::mr::has_property, ""); -static_assert(!cuda::mr::has_property_with, ""); +static_assert(!cuda::has_property, ""); +static_assert(cuda::has_property, ""); +static_assert(!cuda::has_property_with, ""); struct valid_property_with_value { friend int get_property(const valid_property_with_value&, prop_with_value) { @@ -33,12 +33,12 @@ struct valid_property_with_value { } }; static_assert( - cuda::mr::has_property, ""); -static_assert(!cuda::mr::has_property, ""); -static_assert(cuda::mr::has_property_with, ""); +static_assert(!cuda::has_property, ""); +static_assert(cuda::has_property_with, ""); -static_assert(!cuda::mr::has_property_with, ""); @@ -47,13 +47,13 @@ struct derived_from_property : public valid_property { return 42; } }; -static_assert(cuda::mr::has_property, +static_assert(cuda::has_property, ""); -static_assert(cuda::mr::has_property, ""); +static_assert(cuda::has_property, ""); static_assert( - cuda::mr::has_property_with, + cuda::has_property_with, ""); -static_assert(!cuda::mr::has_property_with, ""); diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.construction.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.construction.pass.cpp index e3dd1feb6f..7d773f0377 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.construction.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.construction.pass.cpp @@ -47,12 +47,12 @@ struct async_resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const async_resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const async_resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.conversion.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.conversion.pass.cpp index 392272e6b3..c1da2c5a09 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.conversion.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.conversion.pass.cpp @@ -52,12 +52,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.fail.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.fail.cpp index b8d9ac5fc9..77b39d0cb7 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.fail.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.fail.cpp @@ -49,12 +49,12 @@ struct async_resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const async_resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const async_resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.pass.cpp index 8991aeb2da..e5ef35e98f 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.equality.pass.cpp @@ -49,12 +49,12 @@ struct async_resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const async_resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const async_resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.inheritance.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.inheritance.pass.cpp index 6d3966baec..4ecbda80b8 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.inheritance.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.inheritance.pass.cpp @@ -38,12 +38,12 @@ struct async_resource_base { bool operator!=(const async_resource_base& other) const { return false; } _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const async_resource_base&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const async_resource_base& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.properties.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.properties.pass.cpp index 9d637db781..d1c24b7267 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.properties.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.async_resource_ref/async_resource_ref.properties.pass.cpp @@ -25,13 +25,13 @@ template struct property_without_value {}; namespace properties_test { -static_assert(cuda::mr::property_with_value >, ""); +static_assert(cuda::property_with_value >, ""); static_assert( - cuda::mr::property_with_value >, ""); + cuda::property_with_value >, ""); -static_assert(!cuda::mr::property_with_value >, ""); +static_assert(!cuda::property_with_value >, ""); static_assert( - !cuda::mr::property_with_value >, + !cuda::property_with_value >, ""); } // namespace properties_test @@ -56,12 +56,12 @@ struct async_resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const async_resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const async_resource& res, Property) noexcept { @@ -86,25 +86,25 @@ static_assert( (2 * sizeof(void*))); _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires !cuda::mr::property_with_value) // +(requires !cuda::property_with_value) // int InvokeIfWithValue(const Ref& ref) { return -1; } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires cuda::mr::property_with_value) // +(requires cuda::property_with_value) // typename Property::value_type InvokeIfWithValue(const Ref& ref) { return get_property(ref, Property{}); } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires cuda::mr::property_with_value) // +(requires cuda::property_with_value) // int InvokeIfWithoutValue(const Ref& ref) { return -1; } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires !cuda::mr::property_with_value) // +(requires !cuda::property_with_value) // int InvokeIfWithoutValue(const Ref& ref) { get_property(ref, Property{}); return 1; @@ -119,7 +119,7 @@ void test_async_resource_ref() { // Check all the potentially stateful properties const int properties_with_value[] = {InvokeIfWithValue(ref)...}; const int expected_with_value[] = { - ((cuda::mr::property_with_value) ? expected_initially + ((cuda::property_with_value) ? expected_initially : -1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_with_value[i] == expected_with_value[i]); @@ -128,7 +128,7 @@ void test_async_resource_ref() { const int properties_without_value[] = { InvokeIfWithoutValue(ref)...}; const int expected_without_value[] = { - ((cuda::mr::property_with_value) ? -1 : 1)...}; + ((cuda::property_with_value) ? -1 : 1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_without_value[i] == expected_without_value[i]); } @@ -139,7 +139,7 @@ void test_async_resource_ref() { // Check whether we truly get the right value const int properties_with_value2[] = {InvokeIfWithValue(ref)...}; const int expected_with_value2[] = { - ((cuda::mr::property_with_value) ? expected_after_change + ((cuda::property_with_value) ? expected_after_change : -1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_with_value2[i] == expected_with_value2[i]); diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.construction.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.construction.pass.cpp index 774973a397..20e2b6e4a5 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.construction.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.construction.pass.cpp @@ -37,12 +37,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.conversion.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.conversion.pass.cpp index eb633032e2..75dff8f2d5 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.conversion.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.conversion.pass.cpp @@ -52,12 +52,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.fail.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.fail.cpp index af9be2f75c..0cf95c89be 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.fail.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.fail.cpp @@ -38,12 +38,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.pass.cpp index f32f1abbb3..6049a90e62 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.equality.pass.cpp @@ -38,12 +38,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.inheritance.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.inheritance.pass.cpp index e398ad313a..dd598d662b 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.inheritance.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.inheritance.pass.cpp @@ -33,12 +33,12 @@ struct resource_base { bool operator!=(const resource_base& other) const { return false; } _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource_base&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource_base& res, Property) noexcept { diff --git a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.properties.pass.cpp b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.properties.pass.cpp index 759b1ed1c8..26fddacf8a 100644 --- a/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.properties.pass.cpp +++ b/.upstream-tests/test/cuda/memory_resource/memory_resource.resource_ref/resource_ref.properties.pass.cpp @@ -24,13 +24,13 @@ template struct property_without_value {}; namespace properties_test { -static_assert(cuda::mr::property_with_value >, ""); +static_assert(cuda::property_with_value >, ""); static_assert( - cuda::mr::property_with_value >, ""); + cuda::property_with_value >, ""); -static_assert(!cuda::mr::property_with_value >, ""); +static_assert(!cuda::property_with_value >, ""); static_assert( - !cuda::mr::property_with_value >, + !cuda::property_with_value >, ""); } // namespace properties_test @@ -47,12 +47,12 @@ struct resource { int _val = 0; _LIBCUDACXX_TEMPLATE(class Property) - (requires !cuda::mr::property_with_value && + (requires !cuda::property_with_value && _CUDA_VSTD::_One_of) // friend void get_property(const resource&, Property) noexcept {} _LIBCUDACXX_TEMPLATE(class Property) - (requires cuda::mr::property_with_value&& + (requires cuda::property_with_value&& _CUDA_VSTD::_One_of) // friend typename Property::value_type get_property(const resource& res, Property) noexcept { @@ -75,25 +75,25 @@ static_assert(sizeof(cuda::mr::resource_ref, (2 * sizeof(void*))); _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires !cuda::mr::property_with_value) // +(requires !cuda::property_with_value) // int InvokeIfWithValue(const Ref& ref) { return -1; } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires cuda::mr::property_with_value) // +(requires cuda::property_with_value) // typename Property::value_type InvokeIfWithValue(const Ref& ref) { return get_property(ref, Property{}); } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires cuda::mr::property_with_value) // +(requires cuda::property_with_value) // int InvokeIfWithoutValue(const Ref& ref) { return -1; } _LIBCUDACXX_TEMPLATE(class Property, class Ref) -(requires !cuda::mr::property_with_value) // +(requires !cuda::property_with_value) // int InvokeIfWithoutValue(const Ref& ref) { get_property(ref, Property{}); return 1; @@ -108,7 +108,7 @@ void test_resource_ref() { // Check all the potentially stateful properties const int properties_with_value[] = {InvokeIfWithValue(ref)...}; const int expected_with_value[] = { - ((cuda::mr::property_with_value) ? expected_initially + ((cuda::property_with_value) ? expected_initially : -1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_with_value[i] == expected_with_value[i]); @@ -117,7 +117,7 @@ void test_resource_ref() { const int properties_without_value[] = { InvokeIfWithoutValue(ref)...}; const int expected_without_value[] = { - ((cuda::mr::property_with_value) ? -1 : 1)...}; + ((cuda::property_with_value) ? -1 : 1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_without_value[i] == expected_without_value[i]); } @@ -128,7 +128,7 @@ void test_resource_ref() { // Check whether we truly get the right value const int properties_with_value2[] = {InvokeIfWithValue(ref)...}; const int expected_with_value2[] = { - ((cuda::mr::property_with_value) ? expected_after_change + ((cuda::property_with_value) ? expected_after_change : -1)...}; for (std::size_t i = 0; i < sizeof...(Properties); ++i) { assert(properties_with_value2[i] == expected_with_value2[i]); diff --git a/include/cuda/memory_resource b/include/cuda/memory_resource index 45a6a1cfc8..af480f22f5 100644 --- a/include/cuda/memory_resource +++ b/include/cuda/memory_resource @@ -89,40 +89,9 @@ class resource_ref { #if _LIBCUDACXX_STD_VER > 11 _LIBCUDACXX_BEGIN_NAMESPACE_CUDA -namespace mr -{ /////////////////////////////////////////////////////////////////////////////// -// memory_resource - -/// \concept resource -/// \brief The \c resource concept -template -_LIBCUDACXX_CONCEPT_FRAGMENT( - __resource_, - requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment) ( - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::equality_comparable<_Resource>) - )); - -template -_LIBCUDACXX_CONCEPT resource = _LIBCUDACXX_FRAGMENT(__resource_, _Resource); - -/// \concept async_resource -/// \brief The \c async_resource concept -template -_LIBCUDACXX_CONCEPT_FRAGMENT( - __async_resource_, - requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment, cuda::stream_ref __stream) ( - requires(resource<_Resource>), - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::equality_comparable<_Resource>) - )); - -template -_LIBCUDACXX_CONCEPT async_resource = _LIBCUDACXX_FRAGMENT(__async_resource_, _Resource); +// properties /// \concept has_property /// \brief The \c has_property concept @@ -137,11 +106,14 @@ _LIBCUDACXX_CONCEPT has_property = _LIBCUDACXX_FRAGMENT(__has_property_, _Resour /// \concept property_with_value /// \brief The \c property_with_value concept +template +using __property_value_t = typename _Property::value_type; + template _LIBCUDACXX_CONCEPT_FRAGMENT( __property_with_value_, requires()( - typename(typename _Property::value_type) + typename(__property_value_t<_Property>) )); template _LIBCUDACXX_CONCEPT property_with_value = _LIBCUDACXX_FRAGMENT(__property_with_value_, _Property); @@ -158,6 +130,58 @@ _LIBCUDACXX_CONCEPT_FRAGMENT( template _LIBCUDACXX_CONCEPT has_property_with = _LIBCUDACXX_FRAGMENT(__has_property_with_, _Resource, _Property, _Return); +/// class forward_property +/// \brief The \c forward_property crtp temaplate simplifies the user facing side of forwarding properties +/// We can always tell people to just derive from it to properly forward all properties +template +struct forward_property { + _LIBCUDACXX_TEMPLATE(class _Property) + (requires (!property_with_value<_Property>) _LIBCUDACXX_AND has_property<_Upstream, _Property>) + _LIBCUDACXX_INLINE_VISIBILITY friend constexpr void get_property(const _Derived&, _Property) noexcept {} + + _LIBCUDACXX_TEMPLATE(class _Property) + (requires (property_with_value<_Property>) _LIBCUDACXX_AND has_property<_Upstream, _Property>) + _LIBCUDACXX_INLINE_VISIBILITY friend constexpr __property_value_t<_Property> get_property( + const _Derived& __res, _Property __prop) { + return get_property(__res.upstream_resource(), __prop); + } +}; + +namespace mr +{ + +/////////////////////////////////////////////////////////////////////////////// +// memory_resource + +/// \concept resource +/// \brief The \c resource concept +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __resource_, + requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment) ( + requires(_CUDA_VSTD::same_as), + requires(_CUDA_VSTD::same_as), + requires(_CUDA_VSTD::equality_comparable<_Resource>) + )); + +template +_LIBCUDACXX_CONCEPT resource = _LIBCUDACXX_FRAGMENT(__resource_, _Resource); + +/// \concept async_resource +/// \brief The \c async_resource concept +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __async_resource_, + requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment, cuda::stream_ref __stream) ( + requires(resource<_Resource>), + requires(_CUDA_VSTD::same_as), + requires(_CUDA_VSTD::same_as), + requires(_CUDA_VSTD::equality_comparable<_Resource>) + )); + +template +_LIBCUDACXX_CONCEPT async_resource = _LIBCUDACXX_FRAGMENT(__async_resource_, _Resource); + /// \concept resource_with /// \brief The \c resource_with concept template @@ -228,7 +252,7 @@ struct _Async_alloc_vtable : public _Alloc_vtable struct _Resource_vtable_builder { template - static typename _Property::value_type _Get_property(void* __res) noexcept { + static __property_value_t<_Property> _Get_property(void* __res) noexcept { return get_property(*static_cast(__res), _Property{}); } @@ -282,7 +306,7 @@ struct _Resource_vtable_builder template struct _Property_vtable { - using _PropertyFn = typename _Property::value_type (*)(void*); + using _PropertyFn = __property_value_t<_Property> (*)(void*); _PropertyFn __property_fn = nullptr; constexpr _Property_vtable(_PropertyFn __property_fn_) noexcept @@ -516,7 +540,7 @@ public: _LIBCUDACXX_TEMPLATE(class _Property) (requires property_with_value<_Property> &&_CUDA_VSTD::_One_of<_Property, _Properties...>) // - friend typename _Property::value_type get_property( + friend __property_value_t<_Property> get_property( const basic_resource_ref &__res, _Property) noexcept { return __res._Property_vtable<_Property>::__property_fn(__res.__object); }