#include #include #include #include #include struct alloc_id { std::size_t id; std::size_t size; std::size_t alignment; std::size_t offset{}; _CCCL_HOST_DEVICE bool operator==(const alloc_id& other) const { return id == other.id && size == other.size && alignment == other.alignment; } alloc_id operator+(std::size_t size_) const { alloc_id ret; ret.id = id; ret.size = size_; ret.alignment = alignment; ret.offset = size_; return ret; } }; template <> struct cuda::std::pointer_traits { template using rebind = alloc_id; // implemented for the purposes of alignment test in disjoint pool's do_deallocate static void* get(const alloc_id& id) { return reinterpret_cast(id.alignment); // NOLINT(performance-no-int-to-ptr) } [[nodiscard]] static void* to_address(const alloc_id& id) noexcept { return reinterpret_cast(id.alignment); // NOLINT(performance-no-int-to-ptr) } }; class dummy_resource final : public thrust::mr::memory_resource { public: dummy_resource() = default; ~dummy_resource() override // NOLINT(bugprone-exception-escape) { ASSERT_EQUAL(id_to_allocate, 0u); ASSERT_EQUAL(id_to_deallocate, 0u); ASSERT_EQUAL(used_bytes, 0u); ASSERT_EQUAL(allocation_ids.size(), 0u); } void assert_empty_and_reset() { ASSERT_EQUAL(used_bytes, 0u); ASSERT_EQUAL(allocation_ids.size(), 0u); free_bytes = 1ull << 63; id_to_allocate = 0; id_to_deallocate = 0; } alloc_id do_allocate(std::size_t bytes, std::size_t alignment) override { if (bytes > free_bytes) { throw thrust::system::detail::bad_alloc("Dummy allocation failed: insufficient free bytes."); } ASSERT_NOT_EQUAL(id_to_allocate, 0u); // Ensure that the allocation ID is unique ASSERT_EQUAL_QUIET(find(allocation_ids.begin(), allocation_ids.end(), id_to_allocate), allocation_ids.end()); free_bytes -= bytes; used_bytes += bytes; allocation_ids.push_back(id_to_allocate); alloc_id ret; ret.id = id_to_allocate; ret.size = bytes; ret.alignment = alignment; id_to_allocate = 0; return ret; } void do_deallocate(alloc_id p, std::size_t bytes, std::size_t alignment) override { ASSERT_EQUAL(p.size, bytes); ASSERT_EQUAL(p.alignment, alignment); ASSERT_LEQUAL(bytes, used_bytes); // Check that the id has been previously allocated ASSERT_NOT_EQUAL_QUIET(find(allocation_ids.begin(), allocation_ids.end(), p.id), allocation_ids.end()); free_bytes += bytes; used_bytes -= bytes; allocation_ids.erase(find(allocation_ids.begin(), allocation_ids.end(), p.id)); if (id_to_deallocate != 0) { ASSERT_EQUAL(p.id, id_to_deallocate); id_to_deallocate = 0; } } std::size_t free_bytes{1ull << 63}; std::size_t used_bytes{0}; std::vector allocation_ids; std::size_t id_to_allocate{}; std::size_t id_to_deallocate{}; }; template