File indexing completed on 2026-05-03 08:14:07
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___UTILITY_SMALL_BUFFER_H
0010 #define _LIBCPP___UTILITY_SMALL_BUFFER_H
0011
0012 #include <__config>
0013 #include <__cstddef/byte.h>
0014 #include <__cstddef/size_t.h>
0015 #include <__memory/construct_at.h>
0016 #include <__new/allocate.h>
0017 #include <__new/launder.h>
0018 #include <__type_traits/decay.h>
0019 #include <__type_traits/is_trivially_constructible.h>
0020 #include <__type_traits/is_trivially_destructible.h>
0021 #include <__utility/exception_guard.h>
0022 #include <__utility/forward.h>
0023
0024 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0025 # pragma GCC system_header
0026 #endif
0027
0028 #if _LIBCPP_STD_VER >= 23
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 _LIBCPP_BEGIN_NAMESPACE_STD
0039
0040 template <size_t _BufferSize, size_t _BufferAlignment>
0041 requires(_BufferSize > 0 && _BufferAlignment > 0)
0042 class __small_buffer {
0043 public:
0044 template <class _Tp, class _Decayed = decay_t<_Tp>>
0045 static constexpr bool __fits_in_buffer =
0046 is_trivially_move_constructible_v<_Decayed> && is_trivially_destructible_v<_Decayed> &&
0047 sizeof(_Decayed) <= _BufferSize && alignof(_Decayed) <= _BufferAlignment;
0048
0049 _LIBCPP_HIDE_FROM_ABI __small_buffer() = default;
0050 __small_buffer(const __small_buffer&) = delete;
0051 __small_buffer& operator=(const __small_buffer&) = delete;
0052 _LIBCPP_HIDE_FROM_ABI ~__small_buffer() = default;
0053
0054
0055 _LIBCPP_HIDE_FROM_ABI __small_buffer(__small_buffer&&) = default;
0056 _LIBCPP_HIDE_FROM_ABI __small_buffer& operator=(__small_buffer&&) = default;
0057
0058 template <class _Stored>
0059 _LIBCPP_HIDE_FROM_ABI _Stored* __get() {
0060 if constexpr (__fits_in_buffer<_Stored>)
0061 return std::launder(reinterpret_cast<_Stored*>(__buffer_));
0062 else
0063 return *std::launder(reinterpret_cast<_Stored**>(__buffer_));
0064 }
0065
0066 template <class _Stored>
0067 _LIBCPP_HIDE_FROM_ABI _Stored* __alloc() {
0068 if constexpr (__fits_in_buffer<_Stored>) {
0069 return std::launder(reinterpret_cast<_Stored*>(__buffer_));
0070 } else {
0071 byte* __allocation = reinterpret_cast<byte*>(std::__libcpp_allocate<_Stored>(__element_count(1)));
0072 std::construct_at(reinterpret_cast<byte**>(__buffer_), __allocation);
0073 return std::launder(reinterpret_cast<_Stored*>(__allocation));
0074 }
0075 }
0076
0077 template <class _Stored>
0078 _LIBCPP_HIDE_FROM_ABI void __dealloc() noexcept {
0079 if constexpr (!__fits_in_buffer<_Stored>)
0080 std::__libcpp_deallocate<_Stored>(__get<_Stored>(), __element_count(1));
0081 }
0082
0083 template <class _Stored, class... _Args>
0084 _LIBCPP_HIDE_FROM_ABI void __construct(_Args&&... __args) {
0085 _Stored* __buffer = __alloc<_Stored>();
0086 auto __guard = std::__make_exception_guard([&] { __dealloc<_Stored>(); });
0087 std::construct_at(__buffer, std::forward<_Args>(__args)...);
0088 __guard.__complete();
0089 }
0090
0091 private:
0092 alignas(_BufferAlignment) byte __buffer_[_BufferSize];
0093 };
0094
0095 # undef _LIBCPP_SMALL_BUFFER_TRIVIAL_ABI
0096
0097 _LIBCPP_END_NAMESPACE_STD
0098
0099 #endif
0100
0101 #endif