Skip to content

Commit

Permalink
memory: Add constructor for empty device_unique_object
Browse files Browse the repository at this point in the history
  • Loading branch information
stotko committed Sep 13, 2023
1 parent 50530de commit ae6ead0
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/stdgpu/impl/memory_detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,12 @@ copyDevice2DeviceArray(const T* source_device_array,
namespace stdgpu
{

template <typename T>
device_unique_object<T>::device_unique_object(null_object_t /*null_object*/)
: _object(nullptr)
{
}

template <typename T>
template <typename... Args>
device_unique_object<T>::device_unique_object(Args&&... args)
Expand Down Expand Up @@ -484,6 +490,12 @@ device_unique_object<T>::operator*()
return *_object;
}

template <typename T>
device_unique_object<T>::operator bool() const
{
return _object.operator bool();
}

template <typename T>
template <typename U>
safe_device_allocator<T>::safe_device_allocator([[maybe_unused]] const safe_device_allocator<U>& other) noexcept
Expand Down
29 changes: 29 additions & 0 deletions src/stdgpu/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -272,6 +289,11 @@ template <typename T>
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
Expand Down Expand Up @@ -320,6 +342,13 @@ 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<T, std::function<void(T*)>> _object;
};
Expand Down
28 changes: 28 additions & 0 deletions tests/stdgpu/memory.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,32 @@ device_allocation_balance()

} // namespace

TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object_empty)
{
using T = TestContainer<float>;

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<T>(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<float>;
Expand All @@ -1310,6 +1336,7 @@ TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object)

[[maybe_unused]] auto object = stdgpu::device_unique_object<T>(N);

EXPECT_TRUE(object);
EXPECT_EQ(T::standard_signature_used % 2, 1);
EXPECT_EQ(T::policy_signature_used, old_policy_signature_used);
}
Expand All @@ -1336,6 +1363,7 @@ TEST_F(STDGPU_MEMORY_TEST_CLASS, device_unique_object_custom_execution_policy)

[[maybe_unused]] auto object = stdgpu::device_unique_object<T>(policy, N);

EXPECT_TRUE(object);
EXPECT_EQ(T::policy_signature_used % 2, 1);
EXPECT_EQ(T::standard_signature_used, old_standard_signature_used);
}
Expand Down

0 comments on commit ae6ead0

Please sign in to comment.