/* * Copyright 2018 NVIDIA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*! \file * \brief Allocator types usable with \ref Memory Resources. */ #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 THRUST_NAMESPACE_BEGIN namespace mr { /*! \addtogroup allocators Allocators * \ingroup memory_management * \{ */ /*! An \p mr::allocator is a template that fulfills the C++ requirements for Allocators, * allowing to use the NPA-based memory resources where an Allocator is required. Unlike * memory resources, but like other allocators, \p mr::allocator is typed and bound to * allocate object of a specific type, however it can be freely rebound to other types. * * \tparam T the type that will be allocated by this allocator. * \tparam MR the upstream memory resource to use for memory allocation. Must derive from * \p thrust::mr::memory_resource and must be \p final (in C++11 and beyond). */ template class allocator : private validator { public: /*! The pointer to void type of this allocator. */ typedef typename MR::pointer void_pointer; /*! The value type allocated by this allocator. Equivalent to \p T. */ typedef T value_type; /*! The pointer type allocated by this allocator. Equivaled to the pointer type of \p MR rebound to \p T. */ typedef typename thrust::detail::pointer_traits::template rebind::other pointer; /*! The pointer to const type. Equivalent to a pointer type of \p MR rebound to const T. */ typedef typename thrust::detail::pointer_traits::template rebind::other const_pointer; /*! The reference to the type allocated by this allocator. Supports smart references. */ typedef typename thrust::detail::pointer_traits::reference reference; /*! The const reference to the type allocated by this allocator. Supports smart references. */ typedef typename thrust::detail::pointer_traits::reference const_reference; /*! The size type of this allocator. Always \p std::size_t. */ typedef std::size_t size_type; /*! The difference type between pointers allocated by this allocator. */ typedef typename thrust::detail::pointer_traits::difference_type difference_type; /*! Specifies that the allocator shall be propagated on container copy assignment. */ typedef detail::true_type propagate_on_container_copy_assignment; /*! Specifies that the allocator shall be propagated on container move assignment. */ typedef detail::true_type propagate_on_container_move_assignment; /*! Specifies that the allocator shall be propagated on container swap. */ typedef detail::true_type propagate_on_container_swap; /*! The \p rebind metafunction provides the type of an \p allocator instantiated with another type. * * \tparam U the other type to use for instantiation. */ template struct rebind { /*! The typedef \p other gives the type of the rebound \p allocator. */ typedef allocator other; }; /*! Calculates the maximum number of elements allocated by this allocator. * * \return the maximum value of \p std::size_t, divided by the size of \p T. */ _CCCL_EXEC_CHECK_DISABLE _CCCL_HOST_DEVICE size_type max_size() const { return (std::numeric_limits::max)() / sizeof(T); } /*! Constructor. * * \param resource the resource to be used to allocate raw memory. */ _CCCL_HOST_DEVICE allocator(MR* resource) : mem_res(resource) {} /*! Copy constructor. Copies the resource pointer. */ template _CCCL_HOST_DEVICE allocator(const allocator& other) : mem_res(other.resource()) {} /*! Allocates objects of type \p T. * * \param n number of elements to allocate * \return a pointer to the newly allocated storage. */ _CCCL_NODISCARD _CCCL_HOST pointer allocate(size_type n) { return static_cast(mem_res->do_allocate(n * sizeof(T), alignof(T))); } /*! Deallocates objects of type \p T. * * \param p pointer returned by a previous call to \p allocate * \param n number of elements, passed as an argument to the \p allocate call that produced \p p */ _CCCL_HOST void deallocate(pointer p, size_type n) { return mem_res->do_deallocate(p, n * sizeof(T), alignof(T)); } /*! Extracts the memory resource used by this allocator. * * \return the memory resource used by this allocator. */ _CCCL_HOST_DEVICE MR* resource() const { return mem_res; } private: MR* mem_res; }; /*! Compares the allocators for equality by comparing the underlying memory resources. */ template _CCCL_HOST_DEVICE bool operator==(const allocator& lhs, const allocator& rhs) noexcept { return *lhs.resource() == *rhs.resource(); } /*! Compares the allocators for inequality by comparing the underlying memory resources. */ template _CCCL_HOST_DEVICE bool operator!=(const allocator& lhs, const allocator& rhs) noexcept { return !(lhs == rhs); } template using polymorphic_allocator = allocator>; /*! A helper allocator class that uses global instances of a given upstream memory resource. Requires the memory * resource to be default constructible. * * \tparam T the type that will be allocated by this allocator. * \tparam Upstream the upstream memory resource to use for memory allocation. Must derive from * \p thrust::mr::memory_resource and must be \p final (in C++11 and beyond). */ template class stateless_resource_allocator : public thrust::mr::allocator { typedef thrust::mr::allocator base; public: /*! The \p rebind metafunction provides the type of an \p stateless_resource_allocator instantiated with another type. * * \tparam U the other type to use for instantiation. */ template struct rebind { /*! The typedef \p other gives the type of the rebound \p stateless_resource_allocator. */ typedef stateless_resource_allocator other; }; /*! Default constructor. Uses \p get_global_resource to get the global instance of \p Upstream and initializes the * \p allocator base subobject with that resource. */ _CCCL_EXEC_CHECK_DISABLE _CCCL_HOST_DEVICE stateless_resource_allocator() : base(get_global_resource()) {} /*! Copy constructor. Copies the memory resource pointer. */ _CCCL_HOST_DEVICE stateless_resource_allocator(const stateless_resource_allocator& other) : base(other) {} /*! Conversion constructor from an allocator of a different type. Copies the memory resource pointer. */ template _CCCL_HOST_DEVICE stateless_resource_allocator(const stateless_resource_allocator& other) : base(other) {} stateless_resource_allocator& operator=(const stateless_resource_allocator&) = default; /*! Destructor. */ _CCCL_HOST_DEVICE ~stateless_resource_allocator() {} }; /*! \} // allocators */ } // namespace mr THRUST_NAMESPACE_END