16namespace uni20::async::detail
21template <
typename T>
class StorageBuffer {
24 StorageBuffer() =
default;
29 template <
typename... Args>
explicit StorageBuffer(Args&&... args) { this->construct(std::forward<Args>(args)...); }
31 StorageBuffer(StorageBuffer
const&) =
delete;
32 StorageBuffer& operator=(StorageBuffer
const&) =
delete;
34 StorageBuffer(StorageBuffer&&) =
delete;
35 StorageBuffer& operator=(StorageBuffer&&) =
delete;
38 ~StorageBuffer() { this->destroy_if_owned(); }
42 T* get() noexcept {
return value_ptr_cache_.load(std::memory_order_acquire); }
45 T
const* get() const noexcept {
return value_ptr_cache_.load(std::memory_order_acquire); }
49 bool constructed() const noexcept {
return constructed_.load(std::memory_order_acquire); }
55 template <
typename... Args> T* construct(Args&&... args)
57 this->destroy_if_owned();
58 external_owner_.reset();
59 auto* ptr = this->storage_ptr();
60 std::construct_at(ptr, std::forward<Args>(args)...);
62 constructed_.store(
true, std::memory_order_release);
63 value_ptr_cache_.store(ptr, std::memory_order_release);
71 if (
auto* cached = this->get())
return cached;
73 if constexpr (!std::is_default_constructible_v<T>)
79 std::call_once(default_once_, [
this]() { this->construct(); });
88 T* reset_external_pointer(T* ptr, std::shared_ptr<void> owner = {})
noexcept
90 this->destroy_if_owned();
91 external_owner_ = std::move(owner);
92 owns_storage_ =
false;
93 constructed_.store(
true, std::memory_order_release);
94 value_ptr_cache_.store(ptr, std::memory_order_release);
100 void set_external_owner(std::shared_ptr<void> owner)
noexcept { external_owner_ = std::move(owner); }
104 std::shared_ptr<void>
const& external_owner() const noexcept {
return external_owner_; }
109 T* storage_ptr() noexcept {
return std::launder(
reinterpret_cast<T*
>(storage_)); }
112 T
const* storage_ptr() const noexcept {
return std::launder(
reinterpret_cast<T const*
>(storage_)); }
115 void destroy_if_owned() noexcept
117 if (constructed_.load(std::memory_order_acquire) && owns_storage_)
119 std::destroy_at(this->storage_ptr());
121 constructed_.store(
false, std::memory_order_release);
122 value_ptr_cache_.store(
nullptr, std::memory_order_release);
125 alignas(T) std::byte storage_[
sizeof(T)]{};
126 std::atomic<T*> value_ptr_cache_{
nullptr};
127 std::atomic<bool> constructed_{
false};
128 bool owns_storage_{
false};
129 std::once_flag default_once_{};
130 std::shared_ptr<void> external_owner_{};