Files
project_6/cccl_upstream/libcudacxx/include/cuda/__container/buffer.h
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

1204 lines
53 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of libcu++, the C++ Standard Library for your entire system,
// under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//
#ifndef _CUDA___CONTAINER_BUFFER_H
#define _CUDA___CONTAINER_BUFFER_H
#include <cuda/std/detail/__config>
#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
#if _CCCL_HAS_CTK()
# if _CCCL_CUDA_COMPILATION()
# include <cub/device/device_transform.cuh>
# endif // _CCCL_CUDA_COMPILATION()
# include <cuda/__container/heterogeneous_iterator.h>
# include <cuda/__container/uninitialized_async_buffer.h>
# include <cuda/__functional/call_or.h>
# include <cuda/__launch/host_launch.h>
# include <cuda/__memory_resource/allocation_alignment.h>
# include <cuda/__memory_resource/any_resource.h>
# include <cuda/__memory_resource/get_memory_resource.h>
# include <cuda/__memory_resource/properties.h>
# include <cuda/__memory_resource/synchronous_resource_adapter.h>
# include <cuda/__runtime/ensure_current_context.h>
# include <cuda/__stream/get_stream.h>
# include <cuda/__type_traits/is_trivially_copyable.h>
# include <cuda/std/__exception/cuda_error.h>
# include <cuda/std/__exception/exception_macros.h>
# include <cuda/std/__execution/env.h>
# include <cuda/std/__iterator/concepts.h>
# include <cuda/std/__iterator/distance.h>
# include <cuda/std/__iterator/reverse_iterator.h>
# include <cuda/std/__memory/uninitialized_algorithms.h>
# include <cuda/std/__ranges/access.h>
# include <cuda/std/__ranges/concepts.h>
# include <cuda/std/__ranges/size.h>
# include <cuda/std/__ranges/unwrap_end.h>
# include <cuda/std/__type_traits/decay.h>
# include <cuda/std/__utility/forward.h>
# include <cuda/std/__utility/move.h>
# include <cuda/std/cstdint>
# include <cuda/std/initializer_list>
# include <cuda/std/__cccl/prologue.h>
//! @file
//! @brief The \c buffer class provides a container of contiguous memory
_CCCL_BEGIN_NAMESPACE_CUDA
template <class _Env>
inline constexpr bool __buffer_compatible_env =
::cuda::std::is_same_v<::cuda::std::decay_t<_Env>, ::cuda::std::execution::env<>>
|| ::cuda::std::execution::__queryable_with<const _Env&, allocation_alignment_t>;
_CCCL_BEGIN_NAMESPACE_ABI_VER4_BUMP
//! @rst
//! .. _libcudacxx-containers-buffer:
//!
//! buffer
//! -------------
//!
//! ``buffer`` is a container that provides resizable typed storage allocated
//! from a given :ref:`memory resource
//! <libcudacxx-extended-api-memory-resources-resource>`. It handles alignment,
//! release and growth of the allocation. The elements are initialized during
//! construction, which may require a kernel launch.
//!
//! In addition to being type-safe, ``buffer`` also takes a set of
//! :ref:`properties <libcudacxx-extended-api-memory-resources-properties>` to
//! ensure that e.g. execution space constraints are checked at compile time.
//! However, only stateless properties can be forwarded. To use a stateful
//! property, implement :ref:`get_property(const buffer&, Property)
//! <libcudacxx-extended-api-memory-resources-properties>`.
//!
//! @endrst
//! @tparam _Tp the type to be stored in the buffer
//! @tparam _Properties... The properties the allocated memory satisfies
template <class _Tp, class... _Properties>
class buffer
{
public:
using value_type = _Tp;
using reference = _Tp&;
using const_reference = const _Tp&;
using pointer = _Tp*;
using const_pointer = const _Tp*;
using iterator = ::cuda::heterogeneous_iterator<_Tp, _Properties...>;
using const_iterator = ::cuda::heterogeneous_iterator<const _Tp, _Properties...>;
using reverse_iterator = ::cuda::std::reverse_iterator<iterator>;
using const_reverse_iterator = ::cuda::std::reverse_iterator<const_iterator>;
using size_type = ::cuda::std::size_t;
using difference_type = ::cuda::std::ptrdiff_t;
using properties_list = ::cuda::mr::properties_list<_Properties...>;
using __buffer_t = ::cuda::__uninitialized_async_buffer<_Tp, _Properties...>;
using __resource_t = ::cuda::mr::any_resource<_Properties...>;
using __resource_ref_t = ::cuda::mr::resource_ref<_Properties...>;
template <class, class...>
friend class buffer;
// For now we require trivially copyable type to simplify the implementation
static_assert(::cuda::is_trivially_copyable_v<_Tp>, "cuda::buffer requires T to be trivially copyable.");
// At least one of the properties must signal an execution space
static_assert(::cuda::mr::__contains_execution_space_property<_Properties...>,
"The properties of cuda::buffer must contain at "
"least one execution space property!");
private:
__buffer_t __buf_;
# ifndef _CCCL_DOXYGEN_INVOKED
_CCCL_HOST_API explicit buffer(__buffer_t&& __buf) noexcept
: __buf_(::cuda::std::move(__buf))
{}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Helper to check container is compatible with this buffer
template <class _Range>
[[nodiscard]] static constexpr bool __compatible_range() noexcept
{
return ::cuda::std::ranges::__container_compatible_range<_Range, _Tp>;
}
//! @brief Helper to check whether a different buffer still satisfies all
//! properties of this one
template <class... _OtherProperties>
[[nodiscard]] static constexpr bool __properties_match() noexcept
{
return ::cuda::std::__type_set_contains_v<::cuda::std::__make_type_set<_OtherProperties...>, _Properties...>;
}
//! @brief Helper to return an resource_ref to the currently used resource.
//! Used to grow the buffer
__resource_ref_t __borrow_resource() const noexcept
{
return const_cast<__resource_t&>(__buf_.memory_resource());
}
template <class _Env>
static size_t __alignment_from_env(const _Env& __env)
{
const auto __align = ::cuda::__call_or(::cuda::allocation_alignment, alignof(_Tp), __env);
::cuda::__validate_allocation_alignment(__align, alignof(_Tp));
return __align;
}
//! @brief Copies \p __count elements from `[__first, __last)` to \p __dest,
//! where \p __first and \p __dest reside in the different memory spaces
//! @param __first Pointer to the start of the input segment.
//! @param __last Pointer to the end of the input segment.
//! @param __dest Pointer to the start of the output segment.
//! @param __count The number of elements to be copied.
//! @note This function is inherently asynchronous. We need to ensure that the
//! memory pointed to by \p __first and
//! \p __last lives long enough
template <class _Iter>
_CCCL_HOST_API void __copy_cross(_Iter __first, [[maybe_unused]] _Iter __last, pointer __dest, size_type __count)
{
if (__count == 0)
{
return;
}
static_assert(::cuda::std::contiguous_iterator<_Iter>, "Non contiguous iterators are not supported");
// TODO use batched memcpy for non-contiguous iterators, it allows to
// specify stream ordered access
::cuda::__ensure_current_context __guard(__buf_.stream());
::cuda::__driver::__memcpyAsync(
__dest, ::cuda::std::to_address(__first), sizeof(_Tp) * __count, __buf_.stream().get());
}
public:
//! @brief Copy-constructs from a buffer
//! @param __other The other buffer.
_CCCL_HOST_API explicit buffer(const buffer& __other)
: __buf_(__other.memory_resource(), __other.stream(), __other.size(), __other.__buf_.alignment())
{
this->__copy_cross<const_pointer>(
__other.__unwrapped_begin(), __other.__unwrapped_end(), __unwrapped_begin(), __other.size());
}
//! @brief Move-constructs from a buffer
//! @param __other The other buffer. After move construction, the other buffer
//! can only be assigned to or destroyed.
_CCCL_HOST_API buffer(buffer&& __other) noexcept
: __buf_(::cuda::std::move(__other.__buf_))
{}
//! @brief Copy-constructs from a buffer with matching properties
//! @param __other The other buffer.
_CCCL_TEMPLATE(class... _OtherProperties)
_CCCL_REQUIRES((__properties_match<_OtherProperties...>()))
_CCCL_HOST_API explicit buffer(const buffer<_Tp, _OtherProperties...>& __other)
: __buf_(__other.memory_resource(), __other.stream(), __other.size(), __other.__buf_.alignment())
{
this->__copy_cross<const_pointer>(
__other.__unwrapped_begin(), __other.__unwrapped_end(), __unwrapped_begin(), __other.size());
}
//! @brief Move-constructs from a buffer with matching properties
//! @param __other The other buffer. After move construction, the other buffer
//! can only be assigned to or destroyed.
_CCCL_TEMPLATE(class... _OtherProperties)
_CCCL_REQUIRES((__properties_match<_OtherProperties...>()))
_CCCL_HOST_API buffer(buffer<_Tp, _OtherProperties...>&& __other) noexcept
: __buf_(::cuda::std::move(__other.__buf_))
{}
//! @brief Constructs an empty buffer using an environment
//! @param __stream The stream used for allocations.
//! @param __resource The memory resource used for allocations.
//! @param __env The environment providing the needed information
//! @note No memory is allocated.
_CCCL_TEMPLATE(class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND __buffer_compatible_env<_Env>)
_CCCL_HOST_API buffer(::cuda::stream_ref __stream, _Resource&& __resource, [[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
0,
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
}
//! @brief Constructs a buffer of size \p __size using a memory and leaves all
//! elements uninitialized
//! @param __stream The stream used for allocations.
//! @param __resource The memory resource used for allocations.
//! @param __env The environment used to query the memory resource.
//! @param __size The size of the buffer.
//! @warning This constructor does *NOT* initialize any elements. It is the
//! user's responsibility to ensure that the elements within `[vec.begin(),
//! vec.end())` are properly initialized, e.g with
//! `cuda::std::uninitialized_copy`. At the destruction of the \c buffer all
//! elements in the range `[vec.begin(), vec.end())` will be destroyed.
_CCCL_TEMPLATE(class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND __buffer_compatible_env<_Env>)
_CCCL_HOST_API explicit buffer(
::cuda::stream_ref __stream,
_Resource&& __resource,
const size_type __size,
::cuda::no_init_t,
[[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
__size,
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
}
//! @brief Constructs a buffer using a memory resource and copy-constructs all
//! elements from the forward range
//! ``[__first, __last)``
//! @param __stream The stream used for allocations.
//! @param __resource The memory resource used for allocations.
//! @param __env The environment used to query the memory resource.
//! @param __first The start of the input sequence.
//! @param __last The end of the input sequence.
//! @note If `__first == __last` then no memory is allocated
_CCCL_TEMPLATE(class _Iter, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::std::__has_forward_traversal<_Iter>)
_CCCL_HOST_API
buffer(::cuda::stream_ref __stream,
_Resource&& __resource,
_Iter __first,
_Iter __last,
[[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
static_cast<size_type>(::cuda::std::distance(__first, __last)),
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
this->__copy_cross<_Iter>(__first, __last, __unwrapped_begin(), __buf_.size());
}
//! @brief Constructs a buffer using a memory resource and copy-constructs all
//! elements from \p __ilist
//! @param __stream The stream used for allocations.
//! @param __resource The memory resource used for allocations.
//! @param __env The environment used to query the memory resource.
//! @param __ilist The initializer_list being copied into the buffer.
//! @note If `__ilist.size() == 0` then no memory is allocated
_CCCL_TEMPLATE(class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND __buffer_compatible_env<_Env>)
_CCCL_HOST_API buffer(::cuda::stream_ref __stream,
_Resource&& __resource,
::cuda::std::initializer_list<_Tp> __ilist,
[[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
__ilist.size(),
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
this->__copy_cross(__ilist.begin(), __ilist.end(), __unwrapped_begin(), __buf_.size());
}
//! @brief Constructs a buffer using a memory resource and an input range
//! @param __stream The stream used for allocations.
//! @param __resource The memory resource used for allocations.
//! @param __env The environment used to query the memory resource.
//! @param __range The input range to be moved into the buffer.
//! @note If `__range.size() == 0` then no memory is allocated.
_CCCL_TEMPLATE(class _Range, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND(__compatible_range<_Range>())
_CCCL_AND ::cuda::std::ranges::forward_range<_Range> _CCCL_AND ::cuda::std::ranges::sized_range<_Range>)
_CCCL_HOST_API
buffer(::cuda::stream_ref __stream, _Resource&& __resource, _Range&& __range, [[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
static_cast<size_type>(::cuda::std::ranges::__size_cpo{}(__range)),
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
using _Iter = ::cuda::std::ranges::iterator_t<_Range>;
this->__copy_cross<_Iter>(
::cuda::std::ranges::__begin_cpo{}(__range),
::cuda::std::ranges::__unwrap_end(__range),
__unwrapped_begin(),
__buf_.size());
}
# ifndef _CCCL_DOXYGEN_INVOKED // doxygen conflates the overloads
_CCCL_TEMPLATE(class _Range, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND(__compatible_range<_Range>())
_CCCL_AND ::cuda::std::ranges::forward_range<_Range> _CCCL_AND(!::cuda::std::ranges::sized_range<_Range>))
_CCCL_HOST_API
buffer(::cuda::stream_ref __stream, _Resource&& __resource, _Range&& __range, [[maybe_unused]] const _Env& __env = {})
: __buf_(::cuda::mr::__adapt_if_synchronous(::cuda::std::forward<_Resource>(__resource)),
__stream,
static_cast<size_type>(::cuda::std::ranges::__distance_cpo{}(
::cuda::std::ranges::__begin_cpo{}(__range), ::cuda::std::ranges::__end_cpo{}(__range))),
__alignment_from_env(__env))
{
static_assert(::cuda::std::is_copy_constructible_v<::cuda::std::decay_t<_Resource>>,
"Buffer owns a copy of the memory resource, which means it must be copy constructible. "
"cuda::mr::shared_resource can be used to attach shared ownership to a resource type.");
using _Iter = ::cuda::std::ranges::iterator_t<_Range>;
this->__copy_cross<_Iter>(
::cuda::std::ranges::__begin_cpo{}(__range),
::cuda::std::ranges::__unwrap_end(__range),
__unwrapped_begin(),
__buf_.size());
}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Returns an iterator to the first element of the buffer. If the
//! buffer is empty, the returned iterator will be equal to end().
[[nodiscard]] _CCCL_HOST_API iterator begin() noexcept
{
return iterator{__buf_.data()};
}
//! @brief Returns an immutable iterator to the first element of the buffer.
//! If the buffer is empty, the returned iterator will be equal to end().
[[nodiscard]] _CCCL_HOST_API const_iterator begin() const noexcept
{
return const_iterator{__buf_.data()};
}
//! @brief Returns an immutable iterator to the first element of the buffer.
//! If the buffer is empty, the returned iterator will be equal to end().
[[nodiscard]] _CCCL_HOST_API const_iterator cbegin() const noexcept
{
return const_iterator{__buf_.data()};
}
//! @brief Returns an iterator to the element following the last element of
//! the buffer. This element acts as a placeholder; attempting to access it
//! results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API iterator end() noexcept
{
return iterator{__buf_.data() + __buf_.size()};
}
//! @brief Returns an immutable iterator to the element following the last
//! element of the buffer. This element acts as a placeholder; attempting to
//! access it results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API const_iterator end() const noexcept
{
return const_iterator{__buf_.data() + __buf_.size()};
}
//! @brief Returns an immutable iterator to the element following the last
//! element of the buffer. This element acts as a placeholder; attempting to
//! access it results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API const_iterator cend() const noexcept
{
return const_iterator{__buf_.data() + __buf_.size()};
}
//! @brief Returns a reverse iterator to the first element of the reversed
//! buffer. It corresponds to the last element of the non-reversed buffer. If
//! the buffer is empty, the returned iterator is equal to rend().
[[nodiscard]] _CCCL_HOST_API reverse_iterator rbegin() noexcept
{
return reverse_iterator{end()};
}
//! @brief Returns an immutable reverse iterator to the first element of the
//! reversed buffer. It corresponds to the last element of the non-reversed
//! buffer. If the buffer is empty, the returned iterator is equal to rend().
[[nodiscard]] _CCCL_HOST_API const_reverse_iterator rbegin() const noexcept
{
return const_reverse_iterator{end()};
}
//! @brief Returns an immutable reverse iterator to the first element of the
//! reversed buffer. It corresponds to the last element of the non-reversed
//! buffer. If the buffer is empty, the returned iterator is equal to rend().
[[nodiscard]] _CCCL_HOST_API const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator{end()};
}
//! @brief Returns a reverse iterator to the element following the last
//! element of the reversed buffer. It corresponds to the element preceding
//! the first element of the non-reversed buffer. This element acts as a
//! placeholder, attempting to access it results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API reverse_iterator rend() noexcept
{
return reverse_iterator{begin()};
}
//! @brief Returns an immutable reverse iterator to the element following the
//! last element of the reversed buffer. It corresponds to the element
//! preceding the first element of the non-reversed buffer. This element acts
//! as a placeholder, attempting to access it results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API const_reverse_iterator rend() const noexcept
{
return const_reverse_iterator{begin()};
}
//! @brief Returns an immutable reverse iterator to the element following the
//! last element of the reversed buffer. It corresponds to the element
//! preceding the first element of the non-reversed buffer. This element acts
//! as a placeholder, attempting to access it results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator{begin()};
}
//! @brief Returns a pointer to the first element of the buffer. If the buffer
//! has not allocated memory the pointer will be null.
[[nodiscard]] _CCCL_HOST_API pointer data() noexcept
{
return __buf_.data();
}
//! @brief Returns a pointer to the first element of the buffer. If the buffer
//! has not allocated memory the pointer will be null.
[[nodiscard]] _CCCL_HOST_API const_pointer data() const noexcept
{
return __buf_.data();
}
//! @brief Gets a reference to the element at index `__i`. Requires ``cuda::host_accessible`` property.
//! @throw std::out_of_range if `__i < size()`.
//! @since CCCL 3.4, CUDA Toolkit 13.4.
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API _Tp& at(size_type __i)
{
if (__i >= size())
{
_CCCL_THROW(::std::out_of_range, "__i must be less than size()");
}
return data()[__i];
}
//! @overload
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API const _Tp& at(size_type __i) const
{
if (__i >= size())
{
_CCCL_THROW(::std::out_of_range, "__i must be less than size()");
}
return data()[__i];
}
//! @brief Gets a reference to the element at index `__i`. Requires ``cuda::host_accessible`` property.
//! @pre `__i < size()`.
//! @since CCCL 3.4, CUDA Toolkit 13.4.
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API _Tp& operator[](size_type __i) noexcept
{
_CCCL_ASSERT(__i < size(), "__i must be less than size()");
return data()[__i];
}
//! @overload
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API const _Tp& operator[](size_type __i) const noexcept
{
_CCCL_ASSERT(__i < size(), "__i must be less than size()");
return data()[__i];
}
//! @brief Gets a reference to the first element. Requires ``cuda::host_accessible`` property.
//! @pre `!empty()`.
//! @since CCCL 3.4, CUDA Toolkit 13.4.
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API _Tp& front() noexcept
{
_CCCL_ASSERT(!empty(), "the buffer must not be empty");
return data()[0];
}
//! @overload
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API const _Tp& front() const noexcept
{
_CCCL_ASSERT(!empty(), "the buffer must not be empty");
return data()[0];
}
//! @brief Gets a reference to the last element. Requires ``cuda::host_accessible`` property.
//! @pre `!empty()`.
//! @since CCCL 3.4, CUDA Toolkit 13.4.
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API _Tp& back() noexcept
{
_CCCL_ASSERT(!empty(), "the buffer must not be empty");
return data()[size() - 1];
}
//! @overload
_CCCL_TEMPLATE(bool _IsHostAccessible = ::cuda::mr::__is_host_accessible<_Properties...>)
_CCCL_REQUIRES(_IsHostAccessible)
[[nodiscard]] _CCCL_HOST_API const _Tp& back() const noexcept
{
_CCCL_ASSERT(!empty(), "the buffer must not be empty");
return data()[size() - 1];
}
//! @brief Returns a span over the first \p __count elements.
//! @param __count Number of elements in the returned span.
//! @pre `__count <= size()`
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<_Tp> first(size_type __count) noexcept
{
_CCCL_ASSERT(__count <= size(), "cuda::buffer::first(count): count out of range");
return {data(), __count};
}
//! @overload
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<const _Tp> first(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "cuda::buffer::first(count): count out of range");
return {data(), __count};
}
//! @brief Returns a span over the last \p __count elements.
//! @param __count Number of elements in the returned span.
//! @pre `__count <= size()`
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<_Tp> last(size_type __count) noexcept
{
_CCCL_ASSERT(__count <= size(), "cuda::buffer::last(count): count out of range");
return {data() + size() - __count, __count};
}
//! @overload
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<const _Tp> last(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "cuda::buffer::last(count): count out of range");
return {data() + size() - __count, __count};
}
//! @brief Returns a span over a subset of the buffer.
//! @param __offset Index of the first element in the returned span.
//! @param __count Number of elements. Defaults to `dynamic_extent`, meaning
//! all elements from \p __offset to the end.
//! @pre `__offset <= size()`
//! @pre `__count <= size() - __offset || __count == dynamic_extent`
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<_Tp>
subspan(size_type __offset, size_type __count = ::cuda::std::dynamic_extent) noexcept
{
_CCCL_ASSERT(__offset <= size(), "cuda::buffer::subspan(offset, count): offset out of range");
if (__count == ::cuda::std::dynamic_extent)
{
return {data() + __offset, size() - __offset};
}
_CCCL_ASSERT(__count <= size() - __offset, "cuda::buffer::subspan(offset, count): count out of range");
return {data() + __offset, __count};
}
//! @overload
[[nodiscard]] _CCCL_HOST_API ::cuda::std::span<const _Tp>
subspan(size_type __offset, size_type __count = ::cuda::std::dynamic_extent) const noexcept
{
_CCCL_ASSERT(__offset <= size(), "cuda::buffer::subspan(offset, count): offset out of range");
if (__count == ::cuda::std::dynamic_extent)
{
return {data() + __offset, size() - __offset};
}
_CCCL_ASSERT(__count <= size() - __offset, "cuda::buffer::subspan(offset, count): count out of range");
return {data() + __offset, __count};
}
# ifndef _CCCL_DOXYGEN_INVOKED
//! @brief Returns a pointer to the first element of the buffer. If the buffer
//! is empty, the returned pointer will be null.
[[nodiscard]] _CCCL_HOST_API pointer __unwrapped_begin() noexcept
{
return __buf_.data();
}
//! @brief Returns a const pointer to the first element of the buffer. If the
//! buffer is empty, the returned pointer will be null.
[[nodiscard]] _CCCL_HOST_API const_pointer __unwrapped_begin() const noexcept
{
return __buf_.data();
}
//! @brief Returns a pointer to the element following the last element of the
//! buffer. This element acts as a placeholder; attempting to access it
//! results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API pointer __unwrapped_end() noexcept
{
return __buf_.data() + __buf_.size();
}
//! @brief Returns a const pointer to the element following the last element
//! of the buffer. This element acts as a placeholder; attempting to access it
//! results in undefined behavior.
[[nodiscard]] _CCCL_HOST_API const_pointer __unwrapped_end() const noexcept
{
return __buf_.data() + __buf_.size();
}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Returns a reference to the \p __n 'th element of the async_vector
//! @param __n The index of the element we want to access
//! @note Does not synchronize with the stored stream
[[nodiscard]] _CCCL_HOST_API reference get_unsynchronized(const size_type __n) noexcept
{
_CCCL_ASSERT(__n < __buf_.size(), "cuda::buffer::get_unsynchronized out of range!");
return __unwrapped_begin()[__n];
}
//! @brief Returns a reference to the \p __n 'th element of the async_vector
//! @param __n The index of the element we want to access
//! @note Does not synchronize with the stored stream
[[nodiscard]] _CCCL_HOST_API const_reference get_unsynchronized(const size_type __n) const noexcept
{
_CCCL_ASSERT(__n < __buf_.size(), "cuda::buffer::get_unsynchronized out of range!");
return __unwrapped_begin()[__n];
}
//! @brief Returns the current number of elements stored in the buffer.
[[nodiscard]] _CCCL_HOST_API size_type size() const noexcept
{
return __buf_.size();
}
//! @brief Returns true if the buffer is empty.
[[nodiscard]] _CCCL_HOST_API bool empty() const noexcept
{
return __buf_.size() == 0;
}
//! @brief Returns the alignment used for the allocation.
[[nodiscard]] _CCCL_HOST_API constexpr size_type alignment() const noexcept
{
return __buf_.alignment();
}
//! @rst
//! Returns a \c const reference to the :ref:`any_resource <libcudacxx-memory-resource-any-resource>` that holds the
//! memory resource used to allocate the buffer
//! @endrst
[[nodiscard]] _CCCL_HOST_API const __resource_t& memory_resource() const noexcept
{
return __buf_.memory_resource();
}
//! @brief Returns the stored stream
//! @note Stream used to allocate the buffer is initially stored in the
//! buffer, but can be changed with `set_stream`
[[nodiscard]] _CCCL_HOST_API constexpr stream_ref stream() const noexcept
{
return __buf_.stream();
}
//! @brief Replaces the stored stream
//! @param __new_stream the new stream
//! @note Always synchronizes with the old stream
_CCCL_HOST_API constexpr void set_stream(stream_ref __new_stream)
{
__buf_.set_stream_unsynchronized(__new_stream);
}
//! @brief Move assignment operator
//! @param __other The other buffer. After move assignment, the other buffer
//! can only be assigned to or destroyed.
_CCCL_HOST_API void operator=(buffer&& __other) noexcept
{
__buf_ = ::cuda::std::move(__other.__buf_);
}
//! @brief Swaps the contents of a buffer with those of \p __other
//! @param __other The other buffer.
_CCCL_HOST_API void swap(buffer& __other) noexcept
{
::cuda::std::swap(__buf_, __other.__buf_);
}
//! @brief Swaps the contents of two buffers
//! @param __lhs One buffer.
//! @param __rhs The other buffer.
_CCCL_HOST_API friend void swap(buffer& __lhs, buffer& __rhs) noexcept
{
__lhs.swap(__rhs);
}
//! @brief Destroys the buffer, deallocates the buffer and destroys the memory
//! resource
//! @param __stream The stream to deallocate the buffer on.
//! @warning After this explicit destroy call, the buffer can only be assigned
//! to or destroyed.
_CCCL_HOST_API void destroy(::cuda::stream_ref __stream) noexcept
{
__buf_.destroy(__stream);
}
//! @brief Destroys the buffer, deallocates the buffer and destroys the memory
//! resource
//! @note Uses the stored stream to deallocate the buffer, equivalent to
//! calling buffer.destroy(buffer.stream())
//! @warning After this explicit destroy call, the buffer can only be assigned
//! to or destroyed.
_CCCL_HOST_API void destroy() noexcept
{
__buf_.destroy();
}
# ifndef _CCCL_DOXYGEN_INVOKED
_CCCL_HOST_API constexpr void __set_size_unsynchronized(size_type __size) noexcept
{
__buf_.__set_size(__size);
}
_CCCL_HOST_API buffer __replace_allocation(::cuda::stream_ref __stream, size_type __capacity)
{
return buffer{__buf_.__replace_allocation(__stream, __capacity)};
}
_CCCL_HOST_API void
__replace_allocation_discard(::cuda::stream_ref __stream, size_type __capacity, size_type __old_capacity)
{
__buf_.__replace_allocation_discard(__stream, __capacity, __old_capacity);
}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Causes the buffer to be treated as a span when passed to
//! cuda::launch.
//! @pre The buffer must have the cuda::mr::device_accessible property.
template <class _DeviceAccessible = ::cuda::mr::device_accessible>
[[nodiscard]] _CCCL_HOST_API friend auto transform_launch_argument(::cuda::stream_ref, buffer& __self) noexcept
_CCCL_TRAILING_REQUIRES(::cuda::std::span<_Tp>)(::cuda::std::__is_included_in_v<_DeviceAccessible, _Properties...>)
{
return {__self.__unwrapped_begin(), __self.size()};
}
//! @brief Causes the buffer to be treated as a span when passed to
//! cuda::launch
//! @pre The buffer must have the cuda::mr::device_accessible property.
template <class _DeviceAccessible = ::cuda::mr::device_accessible>
[[nodiscard]] _CCCL_HOST_API friend auto transform_launch_argument(::cuda::stream_ref, const buffer& __self) noexcept
_CCCL_TRAILING_REQUIRES(::cuda::std::span<const _Tp>)(
::cuda::std::__is_included_in_v<_DeviceAccessible, _Properties...>)
{
return {__self.__unwrapped_begin(), __self.size()};
}
//! @brief Forwards the passed properties
_CCCL_TEMPLATE(class _Property)
_CCCL_REQUIRES((!property_with_value<_Property>) _CCCL_AND ::cuda::std::__is_included_in_v<_Property, _Properties...>)
_CCCL_HOST_API friend void get_property(const buffer&, _Property) noexcept {}
};
_CCCL_END_NAMESPACE_ABI_VER4_BUMP
template <class _Tp>
using device_buffer = buffer<_Tp, ::cuda::mr::device_accessible>;
template <class _Tp>
using host_buffer = buffer<_Tp, ::cuda::mr::host_accessible>;
template <class _Tp, class _PropsList>
using __buffer_type_for_props = typename ::cuda::std::remove_reference_t<_PropsList>::template rebind<buffer, _Tp>;
template <typename _BufferTo, typename _BufferFrom>
_CCCL_HOST_API void __copy_cross_buffers(
stream_ref __stream, _BufferTo& __to, const _BufferFrom& __from, typename _BufferFrom::size_type __count)
{
::cuda::__ensure_current_context __guard(__stream);
__stream.wait(__from.stream());
::cuda::__driver::__memcpyAsync(
__to.__unwrapped_begin(),
__from.__unwrapped_begin(),
sizeof(typename _BufferTo::value_type) * __count,
__stream.get());
}
template <typename _BufferTo, typename _BufferFrom>
_CCCL_HOST_API void __copy_cross_buffers(stream_ref __stream, _BufferTo& __to, const _BufferFrom& __from)
{
::cuda::__copy_cross_buffers(__stream, __to, __from, __from.size());
}
_CCCL_BEGIN_NAMESPACE_ARCH_DEPENDENT
//! @brief Copy-constructs elements in the range `[__first, __first + __count)`.
//! @param __first Pointer to the first element to be initialized.
//! @param __count The number of elements to be initialized.
template <typename _Tp, mr::__memory_accessibility _Accessability>
_CCCL_HOST_API void __fill_n(cuda::stream_ref __stream, _Tp* __first, ::cuda::std::size_t __count, const _Tp& __value)
{
if (__count == 0)
{
return;
}
// We don't know what to do with both device and host accessible buffers, so
// we need to check the attributes
if constexpr (_Accessability == mr::__memory_accessibility ::__host_device)
{
__driver::__pointer_attribute_value_type_t<CU_POINTER_ATTRIBUTE_MEMORY_TYPE> __type;
bool __is_managed{};
auto __status1 = ::cuda::__driver::__pointerGetAttributeNoThrow<CU_POINTER_ATTRIBUTE_MEMORY_TYPE>(__type, __first);
auto __status2 =
::cuda::__driver::__pointerGetAttributeNoThrow<CU_POINTER_ATTRIBUTE_IS_MANAGED>(__is_managed, __first);
if (__status1 != ::cudaSuccess || __status2 != ::cudaSuccess)
{
_CCCL_THROW(::cuda::cuda_error, __status1, "Failed to get buffer memory attributes");
}
if (__type == ::CU_MEMORYTYPE_HOST && !__is_managed)
{
__fill_n<_Tp, mr::__memory_accessibility ::__host>(__stream, __first, __count, __value);
}
else
{
__fill_n<_Tp, mr::__memory_accessibility ::__device>(__stream, __first, __count, __value);
}
}
else if constexpr (_Accessability == mr::__memory_accessibility ::__host)
{
::cuda::host_launch(
__stream, ::cuda::std::uninitialized_fill_n<_Tp*, ::cuda::std::size_t, _Tp>, __first, __count, __value);
}
else if constexpr (::cuda::__driver::__cu_driver_memsetable<_Tp>)
{
::cuda::__driver::__memsetAsync(__first, __value, __count, __stream.get());
}
else
{
# if _CCCL_CUDA_COMPILATION()
::cuda::__ensure_current_context __guard(__stream);
CUB_NS_QUALIFIER::DeviceTransform::Fill(__first, __count, __value, __stream.get());
# else // ^^^ _CCCL_CUDA_COMPILATION() ^^^ / vvv !_CCCL_CUDA_COMPILATION() vvv
static_assert(::cuda::__driver::__cu_driver_memsetable<_Tp>,
"CUDA compiler is required to initialize an async_buffer with elements unable to be initialized "
"with cuMemSet");
# endif // ^^^ !_CCCL_CUDA_COMPILATION() ^^^
}
}
_CCCL_END_NAMESPACE_ARCH_DEPENDENT
// Require at least one explicit property on the source, so it doesn't look applicable for initializer list inputs
_CCCL_TEMPLATE(class _Tp,
class _FirstProperty,
class... _RestProperties,
class _Resource,
class _FirstSourceProperty,
class... _RestSourceProperties,
class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env>)
_CCCL_HOST_API buffer<_Tp, _FirstProperty, _RestProperties...> make_buffer(
stream_ref __stream,
_Resource&& __mr,
const buffer<_Tp, _FirstSourceProperty, _RestSourceProperties...>& __source,
const _Env& __env = {})
{
buffer<_Tp, _FirstProperty, _RestProperties...> __res{
__stream, ::cuda::std::forward<_Resource>(__mr), __source.size(), no_init, __env};
__copy_cross_buffers(__stream, __res, __source);
return __res;
}
//! @brief Creates a buffer by copying from \p __source, using the default properties of \p __mr
//! @param __stream The stream used for allocation and copy.
//! @param __mr The memory resource used for allocation.
//! @param __source The source buffer to copy from.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp,
class _Resource,
class _FirstSourceProperty,
class... _RestSourceProperties,
class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto make_buffer(
stream_ref __stream,
_Resource&& __mr,
const buffer<_Tp, _FirstSourceProperty, _RestSourceProperties...>& __source,
const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp,
class _Resource,
class _FirstSourceProperty,
class... _RestSourceProperties,
class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<::cuda::std::decay_t<_Resource>>)
_CCCL_HOST_API auto make_buffer(
stream_ref __stream,
_Resource&& __mr,
const buffer<_Tp, _FirstSourceProperty, _RestSourceProperties...>& __source,
const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
auto __res = __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __source.size(), no_init, __env};
__copy_cross_buffers(__stream, __res, __source);
return __res;
}
# endif // _CCCL_DOXYGEN_INVOKED
// Empty buffer make function
_CCCL_TEMPLATE(
class _Tp, class _FirstProperty, class... _RestProperties, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env>)
buffer<_Tp, _FirstProperty, _RestProperties...>
make_buffer(stream_ref __stream, _Resource&& __mr, const _Env& __env = {})
{
return buffer<_Tp, _FirstProperty, _RestProperties...>{__stream, ::cuda::std::forward<_Resource>(__mr), __env};
}
//! @brief Creates an empty buffer using the default properties of \p __mr
//! @param __stream The stream used for allocation.
//! @param __mr The memory resource used for allocation.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto make_buffer(stream_ref __stream, _Resource&& __mr, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<::cuda::std::decay_t<_Resource>> _CCCL_AND
__buffer_compatible_env<_Env>)
_CCCL_HOST_API auto make_buffer(stream_ref __stream, _Resource&& __mr, const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
return __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __env};
}
# endif // _CCCL_DOXYGEN_INVOKED
_CCCL_BEGIN_NAMESPACE_ARCH_DEPENDENT
// Size and value make function
_CCCL_TEMPLATE(
class _Tp, class _FirstProperty, class... _RestProperties, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env>)
_CCCL_HOST_API buffer<_Tp, _FirstProperty, _RestProperties...> make_buffer(
stream_ref __stream, _Resource&& __mr, size_t __size, const _Tp& __value, [[maybe_unused]] const _Env& __env = {})
{
auto __res =
buffer<_Tp, _FirstProperty, _RestProperties...>{__stream, ::cuda::std::forward<_Resource>(__mr), __size, no_init};
__fill_n<_Tp, mr::__memory_accessibility_from_properties<_FirstProperty, _RestProperties...>::value>(
__stream, __res.__unwrapped_begin(), __size, __value);
return __res;
}
//! @brief Creates a buffer of \p __size elements initialized to \p __value, using the default properties of \p __mr
//! @param __stream The stream used for allocation and initialization.
//! @param __mr The memory resource used for allocation.
//! @param __size The number of elements.
//! @param __value The value to initialize elements with.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, size_t __size, const _Tp& __value, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<::cuda::std::decay_t<_Resource>>)
_CCCL_HOST_API auto make_buffer(
stream_ref __stream, _Resource&& __mr, size_t __size, const _Tp& __value, [[maybe_unused]] const _Env& __env = {})
{
using __default_queries = typename ::cuda::std::decay_t<_Resource>::default_queries;
using __buffer_type = __buffer_type_for_props<_Tp, __default_queries>;
auto __res = __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __size, no_init};
__fill_n<_Tp, __default_queries::template rebind<mr::__memory_accessibility_from_properties>::value>(
__stream, __res.__unwrapped_begin(), __size, __value);
return __res;
}
# endif // _CCCL_DOXYGEN_INVOKED
_CCCL_END_NAMESPACE_ARCH_DEPENDENT
// Size with no initialization make function
_CCCL_TEMPLATE(
class _Tp, class _FirstProperty, class... _RestProperties, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env>)
buffer<_Tp, _FirstProperty, _RestProperties...>
make_buffer(stream_ref __stream, _Resource&& __mr, size_t __size, ::cuda::no_init_t, const _Env& __env = {})
{
return buffer<_Tp, _FirstProperty, _RestProperties...>{
__stream, ::cuda::std::forward<_Resource>(__mr), __size, ::cuda::no_init, __env};
}
//! @brief Creates a buffer of \p __size uninitialized elements, using the default properties of \p __mr
//! @param __stream The stream used for allocation.
//! @param __mr The memory resource used for allocation.
//! @param __size The number of elements.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, size_t __size, ::cuda::no_init_t, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<_Resource>)
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, size_t __size, ::cuda::no_init_t, const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
return __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __size, ::cuda::no_init, __env};
}
# endif // _CCCL_DOXYGEN_INVOKED
// Iterator range make function
_CCCL_TEMPLATE(class _Tp,
class _FirstProperty,
class... _RestProperties,
class _Resource,
class _Iter,
class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env> _CCCL_AND ::cuda::std::__has_forward_traversal<_Iter>)
buffer<_Tp, _FirstProperty, _RestProperties...>
make_buffer(stream_ref __stream, _Resource&& __mr, _Iter __first, _Iter __last, const _Env& __env = {})
{
return buffer<_Tp, _FirstProperty, _RestProperties...>{
__stream, ::cuda::std::forward<_Resource>(__mr), __first, __last, __env};
}
//! @brief Creates a buffer from the iterator range `[__first, __last)`, using the default properties of \p __mr
//! @param __stream The stream used for allocation and copy.
//! @param __mr The memory resource used for allocation.
//! @param __first The start of the input sequence.
//! @param __last The end of the input sequence.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Iter, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, _Iter __first, _Iter __last, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Iter, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<_Resource> _CCCL_AND ::cuda::std::__has_forward_traversal<_Iter>)
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, _Iter __first, _Iter __last, const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
return __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __first, __last, __env};
}
# endif // _CCCL_DOXYGEN_INVOKED
// Initializer list make function
_CCCL_TEMPLATE(
class _Tp, class _FirstProperty, class... _RestProperties, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env>)
buffer<_Tp, _FirstProperty, _RestProperties...>
make_buffer(stream_ref __stream, _Resource&& __mr, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {})
{
return buffer<_Tp, _FirstProperty, _RestProperties...>{
__stream, ::cuda::std::forward<_Resource>(__mr), __ilist, __env};
}
//! @brief Creates a buffer from \p __ilist, using the default properties of \p __mr
//! @param __stream The stream used for allocation and copy.
//! @param __mr The memory resource used for allocation.
//! @param __ilist The initializer_list being copied into the buffer.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>>
_CCCL_AND ::cuda::mr::__has_default_queries<::cuda::std::decay_t<_Resource>>)
_CCCL_HOST_API auto
make_buffer(stream_ref __stream, _Resource&& __mr, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
return __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), __ilist, __env};
}
# endif // _CCCL_DOXYGEN_INVOKED
// Range make function for ranges
_CCCL_TEMPLATE(class _Tp,
class _FirstProperty,
class... _RestProperties,
class _Resource,
class _Range,
class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource_with<::cuda::std::decay_t<_Resource>, _FirstProperty, _RestProperties...> _CCCL_AND
__buffer_compatible_env<_Env> _CCCL_AND ::cuda::std::ranges::forward_range<_Range>)
buffer<_Tp, _FirstProperty, _RestProperties...>
make_buffer(stream_ref __stream, _Resource&& __mr, _Range&& __range, const _Env& __env = {})
{
return buffer<_Tp, _FirstProperty, _RestProperties...>{
__stream, ::cuda::std::forward<_Resource>(__mr), ::cuda::std::forward<_Range>(__range), __env};
}
//! @brief Creates a buffer from \p __range, using the default properties of \p __mr
//! @param __stream The stream used for allocation and copy.
//! @param __mr The memory resource used for allocation.
//! @param __range The input range to be copied into the buffer.
//! @param __env The environment providing additional configuration.
# ifdef _CCCL_DOXYGEN_INVOKED
template <class _Tp, class _Resource, class _Range, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto make_buffer(stream_ref __stream, _Resource&& __mr, _Range&& __range, const _Env& __env = {});
# else // ^^^ _CCCL_DOXYGEN_INVOKED ^^^ / vvv !_CCCL_DOXYGEN_INVOKED vvv
_CCCL_TEMPLATE(class _Tp, class _Resource, class _Range, class _Env = ::cuda::std::execution::env<>)
_CCCL_REQUIRES(
::cuda::mr::synchronous_resource<::cuda::std::decay_t<_Resource>> _CCCL_AND ::cuda::mr::__has_default_queries<
::cuda::std::decay_t<_Resource>> _CCCL_AND ::cuda::std::ranges::forward_range<_Range>)
_CCCL_HOST_API auto make_buffer(stream_ref __stream, _Resource&& __mr, _Range&& __range, const _Env& __env = {})
{
using __buffer_type = __buffer_type_for_props<_Tp, typename ::cuda::std::decay_t<_Resource>::default_queries>;
return __buffer_type{__stream, ::cuda::std::forward<_Resource>(__mr), ::cuda::std::forward<_Range>(__range), __env};
}
# endif // _CCCL_DOXYGEN_INVOKED
_CCCL_END_NAMESPACE_CUDA
# include <cuda/std/__cccl/epilogue.h>
#endif // _CCCL_HAS_CTK()
#endif //_CUDA___CONTAINER_BUFFER_H