Iros
 
Loading...
Searching...
No Matches
shared_storage.h
Go to the documentation of this file.
1#pragma once
2
11#include "di/meta/algorithm.h"
12#include "di/meta/language.h"
13#include "di/meta/operations.h"
14#include "di/platform/prelude.h"
15#include "di/sync/atomic.h"
16#include "di/types/prelude.h"
17#include "di/util/addressof.h"
19#include "di/util/destroy_at.h"
20#include "di/util/exchange.h"
21#include "di/util/immovable.h"
22#include "di/util/move.h"
23#include "di/util/swap.h"
26
27namespace di::any {
28namespace detail {
34
35 template<typename SharedStorage, concepts::Allocator Alloc>
38
39 template<typename T>
40 constexpr void operator()(T&, SharedStorage*, Alloc&, OpForConsteval) const;
41 };
42
43 template<typename SharedStorage, concepts::Allocator Alloc>
45
49
50 template<typename T>
54
55 template<typename... Args>
56 constexpr ObjectWithRefCount(Args&&... args) : object(util::forward<Args>(args)...) {}
57
58 constexpr auto to_object_pointer() -> T* { return util::addressof(object); }
59
61 };
62}
63
64template<concepts::Allocator Alloc = platform::DefaultAllocator>
66private:
67 template<typename, concepts::Allocator>
69
70public:
73
74 constexpr static auto storage_category() -> StorageCategory { return StorageCategory::Copyable; }
75
76 template<typename T>
77 constexpr static auto creation_is_fallible(InPlaceType<T>) -> bool {
79 }
80
81 template<typename>
83
84 template<typename Any, typename T, typename... Args>
87 Args&&... args) {
89 auto result = di::allocate_one<Store>(self->m_allocator);
90 if (!result) {
91 self = vocab::Unexpected(util::move(result).error());
92 return;
93 }
94
95 auto* pointer = *result;
96 util::construct_at(pointer, util::forward<Args>(args)...);
97
98 self->m_pointer = pointer;
99 }
100
101 template<typename T, typename... Args>
102 requires(concepts::ConstructibleFrom<T, Args...> && alignof(T) <= alignof(usize))
103 constexpr static auto init(SharedStorage* self, InPlaceType<T>, Args&&... args) {
104 using Store = detail::ObjectWithRefCount<T>;
105 return vocab::as_fallible(di::allocate_one<Store>(self->m_allocator)) % [&](Store* pointer) {
106 util::construct_at(pointer, util::forward<Args>(args)...);
107 self->m_pointer = pointer;
109 }
110
111 SharedStorage() = default;
112
113 SharedStorage(SharedStorage const&) = default;
114 auto operator=(SharedStorage const&) -> SharedStorage& = default;
115
116 ~SharedStorage() = default;
117
118 constexpr static void copy_construct(concepts::VTableFor<Interface> auto const& vtable, SharedStorage* dest,
119 SharedStorage const* source) {
120 dest->m_pointer = source->m_pointer;
121 if (dest->m_pointer) {
122 if consteval {
123 auto const fp = vtable[Manage {}];
124 fp(dest, dest, dest->m_allocator, detail::OpForConsteval::RefInc);
125 } else {
126 dest->fetch_add_ref_count();
127 }
128 }
129 }
130
131 constexpr static void move_construct(concepts::VTableFor<Interface> auto& vtable, SharedStorage* dest,
132 SharedStorage* source) {
133 dest->m_pointer = util::exchange(source->m_pointer, nullptr);
134 vtable.reset();
135 }
136
137 template<concepts::VTableFor<Interface> VTable>
138 constexpr static void copy_assign(VTable& dest_vtable, SharedStorage* dest, VTable const& source_vtable,
139 SharedStorage const* source) {
140 destroy(dest_vtable, dest);
141 dest_vtable = source_vtable;
142 copy_construct(source_vtable, dest, source);
143 }
144
145 template<concepts::VTableFor<Interface> VTable>
146 constexpr static void move_assign(VTable& dest_vtable, SharedStorage* dest, VTable& source_vtable,
147 SharedStorage* source) {
148 destroy(dest_vtable, dest);
149 dest_vtable = source_vtable;
150 move_construct(source_vtable, dest, source);
151 }
152
153 constexpr static void destroy(concepts::VTableFor<Interface> auto& vtable, SharedStorage* self) {
154 if (self->m_pointer) {
155 auto const fp = vtable[Manage {}];
156 if consteval {
157 fp(self, self, self->m_allocator, detail::OpForConsteval::RefDec);
158 } else {
159 if (self->fetch_sub_ref_count() == 1) {
160 fp(self, self, self->m_allocator, detail::OpForConsteval::Destroy);
161 }
162 }
163 self->m_pointer = nullptr;
164 }
165 }
166
167 template<typename T>
168 constexpr auto down_cast() -> T* {
169 return static_cast<detail::ObjectWithRefCount<T>*>(m_pointer)->to_object_pointer();
170 }
171
172 template<typename T>
173 constexpr auto down_cast() const -> T const* {
174 return static_cast<detail::ObjectWithRefCount<T> const*>(m_pointer)->to_object_pointer();
175 }
176
177private:
178 constexpr explicit SharedStorage(void* pointer) : m_pointer(pointer) {}
179
180 constexpr auto fetch_sub_ref_count() -> usize {
181 auto& ref_count = static_cast<detail::RefCount*>(m_pointer)->ref_count;
182 return ref_count.fetch_sub(1, sync::MemoryOrder::Relaxed);
183 }
184
185 constexpr auto fetch_add_ref_count() -> usize {
186 auto& ref_count = static_cast<detail::RefCount*>(m_pointer)->ref_count;
187 return ref_count.fetch_add(1, sync::MemoryOrder::AcquireRelease);
188 }
189
190 void* m_pointer { nullptr };
191 [[no_unique_address]] Alloc m_allocator {};
192};
193
194namespace detail {
195 template<typename SharedStorage, concepts::Allocator Alloc>
196 template<typename T>
197 constexpr void SharedStorageManage<SharedStorage, Alloc>::operator()(T&, SharedStorage* storage, Alloc& allocator,
198 OpForConsteval op) const {
199 auto* pointer = static_cast<ObjectWithRefCount<T>*>(storage->m_pointer);
200 if consteval {
201 switch (op) {
203 pointer->ref_count.fetch_add(1);
204 return;
206 if (pointer->ref_count.fetch_sub(1) == 1) {
207 break;
208 }
209 return;
210 default:
211 return;
212 }
213 }
214
215 util::destroy_at(pointer);
217 }
218}
219}
Definition atomic.h:15
Definition operations.h:11
Definition allocator.h:20
Definition vtable_for.h:17
Definition any.h:19
constexpr auto shared_storage_manage
Definition shared_storage.h:44
OpForConsteval
Definition shared_storage.h:29
@ Destroy
Definition shared_storage.h:30
@ RefInc
Definition shared_storage.h:31
@ RefDec
Definition shared_storage.h:32
Definition any.h:18
StorageCategory
Definition storage_category.h:4
@ Copyable
Definition storage_category.h:10
meta::Type< AnyT< UserInterface, Storage, VTablePolicy > > Any
Definition any.h:294
T::Type Type
Definition core.h:26
meta::LikeExpected< decltype(di::allocate(util::declval< Alloc & >(), 0, 0)), T > AllocatorResult
Definition allocator.h:25
Type< detail::LikeExpectedHelper< T, U > > LikeExpected
Definition vocab.h:60
@ Relaxed
Definition memory_order.h:7
@ AcquireRelease
Definition memory_order.h:11
size_t usize
Definition integers.h:33
Definition vocab.h:96
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto construct_at
Definition construct_at.h:27
constexpr auto as_fallible
Definition as_fallible.h:26
constexpr auto try_infallible
Definition try_infallible.h:31
Unexpected(E &&) -> Unexpected< meta::UnwrapRefDecay< E > >
constexpr auto allocate_one
Definition allocate_one.h:29
constexpr auto destroy
Definition destroy.h:35
constexpr auto in_place_type
Definition in_place_type.h:12
constexpr auto deallocate_one
Definition deallocate_one.h:27
Definition shared_storage.h:65
meta::List< Manage > Interface
Definition shared_storage.h:72
static constexpr void copy_construct(concepts::VTableFor< Interface > auto const &vtable, SharedStorage *dest, SharedStorage const *source)
Definition shared_storage.h:118
constexpr auto down_cast() -> T *
Definition shared_storage.h:168
static constexpr void destroy(concepts::VTableFor< Interface > auto &vtable, SharedStorage *self)
Definition shared_storage.h:153
static constexpr auto storage_category() -> StorageCategory
Definition shared_storage.h:74
static constexpr void move_assign(VTable &dest_vtable, SharedStorage *dest, VTable &source_vtable, SharedStorage *source)
Definition shared_storage.h:146
constexpr auto down_cast() const -> T const *
Definition shared_storage.h:173
static constexpr void create(InPlaceType< Any >, meta::LikeExpected< CreationResult< T >, Any > &self, InPlaceType< T >, Args &&... args)
Definition shared_storage.h:86
static constexpr auto init(SharedStorage *self, InPlaceType< T >, Args &&... args)
Definition shared_storage.h:103
static constexpr auto creation_is_fallible(InPlaceType< T >) -> bool
Definition shared_storage.h:77
meta::Type< detail::SharedStorageManage< SharedStorage, Alloc > > Manage
Definition shared_storage.h:71
SharedStorage(SharedStorage const &)=default
auto operator=(SharedStorage const &) -> SharedStorage &=default
meta::AllocatorResult< Alloc > CreationResult
Definition shared_storage.h:82
static constexpr void move_construct(concepts::VTableFor< Interface > auto &vtable, SharedStorage *dest, SharedStorage *source)
Definition shared_storage.h:131
static constexpr void copy_assign(VTable &dest_vtable, SharedStorage *dest, VTable const &source_vtable, SharedStorage const *source)
Definition shared_storage.h:138
Definition shared_storage.h:51
constexpr ObjectWithRefCount(Args &&... args)
Definition shared_storage.h:56
ObjectWithRefCount(ObjectWithRefCount &&)=delete
T object
Definition shared_storage.h:60
constexpr auto to_object_pointer() -> T *
Definition shared_storage.h:58
ObjectWithRefCount(ObjectWithRefCount const &)=delete
Definition shared_storage.h:46
sync::Atomic< usize > ref_count
Definition shared_storage.h:47
Definition shared_storage.h:36
Method< SharedStorageManage, void(This &, SharedStorage *, Alloc &, OpForConsteval)> Type
Definition shared_storage.h:37
constexpr void operator()(T &, SharedStorage *, Alloc &, OpForConsteval) const
Definition shared_storage.h:197
Definition core.h:5
Definition in_place_type.h:5
Definition method.h:7
Definition this.h:4