// SPDX-FileCopyrightText: Copyright (c) 2008-2013, NVIDIA Corporation. All rights reserved. // SPDX-License-Identifier: Apache-2.0 /*! \file * \brief An allocator which allocates storage with \p device_new. */ #pragma once #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header #include #include #include #include #include #include #include #include THRUST_NAMESPACE_BEGIN /*! \addtogroup allocators Allocators * \ingroup memory_management * \{ */ /*! \p device_new_allocator is a device memory allocator that employs the * \p device_new function for allocation. * * \see device_new * \see device_ptr * \see https://en.cppreference.com/w/cpp/memory/allocator * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ template class device_new_allocator { public: /*! Type of element allocated, \c T. */ using value_type = T; /*! Pointer to allocation, \c device_ptr. */ using pointer = device_ptr; /*! \c const pointer to allocation, \c device_ptr. */ using const_pointer = device_ptr; /*! Reference to allocated element, \c device_reference. */ using reference = device_reference; /*! \c const reference to allocated element, \c device_reference. */ using const_reference = device_reference; /*! Type of allocation size, \c size_t. */ using size_type = ::cuda::std::size_t; /*! Type of allocation difference, \c pointer::difference_type. */ using difference_type = typename pointer::difference_type; /*! The \p rebind metafunction provides the type of a \p device_new_allocator * instantiated with another type. * * \tparam U The other type to use for instantiation. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ template struct rebind { /*! The alias \p other gives the type of the rebound \p device_new_allocator. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ using other = device_new_allocator; }; // end rebind /*! No-argument constructor has no effect. */ _CCCL_HOST_DEVICE inline device_new_allocator() {} /*! No-argument destructor has no effect. */ _CCCL_HOST_DEVICE inline ~device_new_allocator() {} /*! Copy constructor has no effect. */ _CCCL_HOST_DEVICE inline device_new_allocator(device_new_allocator const&) {} /*! Constructor from other \p device_malloc_allocator has no effect. */ template _CCCL_HOST_DEVICE inline device_new_allocator(device_new_allocator const&) {} /*! Returns the address of an allocated object. * \return &r. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST_DEVICE inline pointer address(reference r) { return &r; } /*! Returns the address an allocated object. * \return &r. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST_DEVICE inline const_pointer address(const_reference r) { return &r; } /*! Allocates storage for \p cnt objects. * \param cnt The number of objects to allocate. * \return A \p pointer to uninitialized storage for \p cnt objects. * \note Memory allocated by this function must be deallocated with \p deallocate. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST inline pointer allocate(size_type cnt, const_pointer = const_pointer(static_cast(0))) { if (cnt > this->max_size()) { _CCCL_THROW(::std::bad_alloc); } // end if // use "::operator new" rather than keyword new return pointer(device_new(cnt)); } // end allocate() /*! Deallocates storage for objects allocated with \p allocate. * \param p A \p pointer to the storage to deallocate. * \param cnt The size of the previous allocation. * \note Memory deallocated by this function must previously have been * allocated with \p allocate. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST inline void deallocate(pointer p, [[maybe_unused]] size_type cnt) noexcept { // use "::operator delete" rather than keyword delete device_delete(p); } // end deallocate() /*! Returns the largest value \c n for which allocate(n) might succeed. * \return The largest value \c n for which allocate(n) might succeed. * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST_DEVICE inline size_type max_size() const { return ::cuda::std::numeric_limits::max THRUST_PREVENT_MACRO_SUBSTITUTION() / sizeof(T); } // end max_size() /*! Compares against another \p device_malloc_allocator for equality. * \return \c true * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST_DEVICE inline bool operator==(device_new_allocator const&) { return true; } /*! Compares against another \p device_malloc_allocator for inequality. * \return \c false * * \verbatim embed:rst:leading-asterisk * .. versionadded:: 2.2.0 * \endverbatim */ _CCCL_HOST_DEVICE inline bool operator!=(device_new_allocator const& a) { return !operator==(a); } }; // end device_new_allocator /*! \} // allocators */ THRUST_NAMESPACE_END