From b70405bc62958f1f1334a936a20cd025351816fb Mon Sep 17 00:00:00 2001 From: Patrick Stotko Date: Wed, 13 Sep 2023 15:17:01 +0200 Subject: [PATCH] memory: Add constructor for empty device_unique_object --- src/stdgpu/impl/memory_detail.h | 12 ++++++++++++ src/stdgpu/memory.h | 28 ++++++++++++++++++++++++++++ tests/stdgpu/memory.inc | 28 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/stdgpu/impl/memory_detail.h b/src/stdgpu/impl/memory_detail.h index 3258eefdb..44451526b 100644 --- a/src/stdgpu/impl/memory_detail.h +++ b/src/stdgpu/impl/memory_detail.h @@ -433,6 +433,12 @@ copyDevice2DeviceArray(const T* source_device_array, namespace stdgpu { +template +device_unique_object::device_unique_object(null_object_t /*null_object*/) + : _object(nullptr) +{ +} + template template device_unique_object::device_unique_object(Args&&... args) @@ -484,6 +490,12 @@ device_unique_object::operator*() return *_object; } +template +device_unique_object::operator bool() const +{ + return _object.operator bool(); +} + template template safe_device_allocator::safe_device_allocator([[maybe_unused]] const safe_device_allocator& other) noexcept diff --git a/src/stdgpu/memory.h b/src/stdgpu/memory.h index 77754e30e..d2a85431d 100644 --- a/src/stdgpu/memory.h +++ b/src/stdgpu/memory.h @@ -263,6 +263,23 @@ copyDevice2DeviceArray(const T* source_device_array, namespace stdgpu { +/** + * \ingroup memory + * \brief A type to indicate an uninitialized unique object + */ +struct null_object_t +{ + //! @cond Doxygen_Suppress + constexpr explicit null_object_t(int /* unspecified */) { } + //! @endcond +}; + +/** + * \ingroup memory + * \brief A constant to indicate an uninitialized unique object + */ +inline constexpr null_object_t null_object{ 0 }; + /** * \ingroup memory * \brief A resource wrapper for managing device objects with automatic scope-based object destruction @@ -272,6 +289,11 @@ template class device_unique_object { public: + /** + * \brief Creates an empty unique object + */ + explicit device_unique_object(null_object_t /*null_object*/); + /** * \brief Creates an object on the GPU (device) * \tparam Args The argument types @@ -320,6 +342,12 @@ class device_unique_object T& operator*(); + /** + * \brief Checks whether the unique object is not empty + * \return True if the unique object is not empty, false otherwise + */ + explicit operator bool() const; + private: std::unique_ptr> _object; }; diff --git a/tests/stdgpu/memory.inc b/tests/stdgpu/memory.inc index 50e877e37..d439041ba 100644 --- a/tests/stdgpu/memory.inc +++ b/tests/stdgpu/memory.inc @@ -1296,6 +1296,32 @@ device_allocation_balance() } // namespace +TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object_empty) +{ + using T = TestContainer; + + const stdgpu::index64_t old_balance = device_allocation_balance(); + + const stdgpu::index_t old_standard_signature_used = T::standard_signature_used; + const stdgpu::index_t old_policy_signature_used = T::policy_signature_used; + EXPECT_EQ(T::standard_signature_used % 2, 0); + EXPECT_EQ(T::policy_signature_used % 2, 0); + + { + [[maybe_unused]] auto object = stdgpu::device_unique_object(stdgpu::null_object); + + EXPECT_FALSE(object); + EXPECT_EQ(T::standard_signature_used, old_standard_signature_used); + EXPECT_EQ(T::policy_signature_used, old_policy_signature_used); + } + + const stdgpu::index64_t new_balance = device_allocation_balance(); + EXPECT_EQ(old_balance, new_balance); + + EXPECT_EQ(T::standard_signature_used, old_standard_signature_used); + EXPECT_EQ(T::policy_signature_used, old_policy_signature_used); +} + TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object) { using T = TestContainer; @@ -1310,6 +1336,7 @@ TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object) [[maybe_unused]] auto object = stdgpu::device_unique_object(N); + EXPECT_TRUE(object); EXPECT_EQ(T::standard_signature_used % 2, 1); EXPECT_EQ(T::policy_signature_used, old_policy_signature_used); } @@ -1336,6 +1363,7 @@ TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object_custom_execution_policy) [[maybe_unused]] auto object = stdgpu::device_unique_object(policy, N); + EXPECT_TRUE(object); EXPECT_EQ(T::policy_signature_used % 2, 1); EXPECT_EQ(T::standard_signature_used, old_standard_signature_used); }