Iros
 
Loading...
Searching...
No Matches
hybrid_storage.h
Go to the documentation of this file.
1#pragma once
2
9#include "di/meta/algorithm.h"
10#include "di/meta/core.h"
11#include "di/meta/language.h"
12#include "di/meta/operations.h"
13#include "di/meta/vocab.h"
14#include "di/platform/prelude.h"
15#include "di/types/prelude.h"
16#include "di/util/addressof.h"
18#include "di/util/destroy_at.h"
19#include "di/util/exchange.h"
20#include "di/util/move.h"
23
24namespace di::any {
25namespace detail {
26 template<typename HybridStorage, concepts::Allocator Alloc>
29
30 template<typename T>
31 constexpr void operator()(T&, HybridStorage*, HybridStorage*, Alloc&) const;
32 };
33
34 template<typename HybridStorage, concepts::Allocator Alloc>
36}
37
38template<StorageCategory category = StorageCategory::MoveOnly, size_t inline_size = 2 * sizeof(void*),
39 size_t inline_align = alignof(void*), concepts::Allocator Alloc = platform::DefaultAllocator>
41 static_assert(category == StorageCategory::MoveOnly || category == StorageCategory::Immovable,
42 "HybridStorage only supports MoveOnly and Immovable objects");
43
44public:
47
48 template<typename, concepts::Allocator>
50
51 constexpr static auto storage_category() -> StorageCategory { return category; }
52
53 template<typename T>
54 constexpr static auto creation_is_inline(InPlaceType<T>) -> bool {
55 return sizeof(T) <= inline_size && alignof(T) <= inline_align &&
57 }
58
59 template<typename T>
63
64 template<typename T>
67
68 HybridStorage() = default;
69
70 HybridStorage(HybridStorage const&) = delete;
71 auto operator=(HybridStorage const&) -> HybridStorage& = delete;
72
73 template<typename Any, typename T, typename... Args>
76 Args&&... args) {
77 if consteval {
78 self->m_pointer = ::new T(di::forward<Args>(args)...);
79 return;
80 }
81
82 auto result = di::allocate_one<T>(self->m_allocator);
83 if (!result) {
84 self = vocab::Unexpected(util::move(result).error());
85 return;
86 }
87
88 auto* pointer = *result;
89 util::construct_at(pointer, util::forward<Args>(args)...);
90
91 self->m_pointer = pointer;
92 }
93
94 template<typename T, typename... Args>
95 requires(concepts::ConstructibleFrom<T, Args...>)
96 constexpr static auto init(HybridStorage* self, InPlaceType<T>, Args&&... args) {
97 if consteval {
98 self->m_pointer = ::new T(di::forward<Args>(args)...);
101 } else {
102 return;
103 }
104 }
105 if constexpr (!creation_is_inline(in_place_type<T>)) {
106 return vocab::as_fallible(di::allocate_one<T>(self->m_allocator)) % [&](T* pointer) {
107 util::construct_at(pointer, util::forward<Args>(args)...);
108 self->m_pointer = pointer;
110 } else {
111 util::construct_at(self->down_cast<T>(), util::forward<Args>(args)...);
112 }
113 }
114
115 ~HybridStorage() = default;
116
117 constexpr static void move_construct(concepts::VTableFor<Interface> auto& vtable, HybridStorage* dest,
118 HybridStorage* source)
119 requires(category == StorageCategory::MoveOnly)
120 {
121 if (!vtable.empty()) {
122 auto const fp = vtable[Manage {}];
123 fp(source, dest, source, dest->m_allocator);
124
125 vtable.reset();
126 }
127 }
128
129 template<concepts::VTableFor<Interface> VTable>
130 constexpr static void move_assign(VTable& dest_vtable, HybridStorage* dest, VTable& source_vtable,
131 HybridStorage* source)
132 requires(category == StorageCategory::MoveOnly)
133 {
134 destroy(dest_vtable, dest);
135 dest_vtable = source_vtable;
136 move_construct(source_vtable, dest, source);
137 }
138
139 constexpr static void destroy(concepts::VTableFor<Interface> auto& vtable, HybridStorage* self) {
140 if (!vtable.empty()) {
141 auto const fp = vtable[Manage {}];
142 fp(self, self, nullptr, self->m_allocator);
143
144 vtable.reset();
145 }
146 }
147
148 template<typename T>
149 constexpr auto down_cast() -> T* {
150 if consteval {
151 return static_cast<T*>(m_pointer);
152 }
153 if constexpr (!creation_is_inline(in_place_type<T>)) {
154 return static_cast<T*>(m_pointer);
155 } else {
156 return static_cast<T*>(address());
157 }
158 }
159
160 template<typename T>
161 constexpr auto down_cast() const -> T const* {
162 if consteval {
163 return static_cast<T const*>(m_pointer);
164 }
165 if constexpr (!creation_is_inline(in_place_type<T>)) {
166 return static_cast<T const*>(m_pointer);
167 } else {
168 return static_cast<T const*>(address());
169 }
170 }
171
172private:
173 auto address() -> void* { return static_cast<void*>(util::addressof(m_storage[0])); }
174 auto address() const -> void const* { return static_cast<void const*>(util::addressof(m_storage[0])); }
175
176 union {
177 void* m_pointer { nullptr };
178 alignas(inline_align) byte m_storage[inline_size];
179 };
180 [[no_unique_address]] Alloc m_allocator {};
181};
182
183namespace detail {
184 template<typename HybridStorage, concepts::Allocator Alloc>
185 template<typename T>
187 Alloc& allocator) const {
188 if consteval {
189 if (bs) {
191 // Move from b into a.
192 as->m_pointer = util::exchange(bs->m_pointer, nullptr);
193 } else {
194 DI_ASSERT(!bs);
195 }
196 } else {
197 // Just destroy a.
198 auto* pointer = util::exchange(as->m_pointer, nullptr);
199 auto* a_value = static_cast<T*>(pointer);
200 ::delete a_value;
201 }
202 return;
203 }
205 if (bs) {
207 // Move from b into a.
208 as->m_pointer = util::exchange(bs->m_pointer, nullptr);
209 } else {
210 DI_ASSERT(!bs);
211 }
212 } else {
213 // Just destroy a.
214 auto* pointer = util::exchange(as->m_pointer, nullptr);
215 auto* a_value = static_cast<T*>(pointer);
216 util::destroy_at(a_value);
217 di::deallocate_one<T>(allocator, a_value);
218 }
219 } else {
220 if (bs) {
222 // Move from b into a.
223 auto* b_value = bs->template down_cast<T>();
224 auto* a_value = as->template down_cast<T>();
225 util::construct_at(a_value, util::move(*b_value));
226 util::destroy_at(b_value);
227 } else {
228 DI_ASSERT(!bs);
229 }
230 } else {
231 // Just destroy a.
232 auto* a_value = as->template down_cast<T>();
233 util::destroy_at(a_value);
234 }
235 }
236 }
237}
238}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition allocator.h:9
Definition operations.h:11
Definition allocator.h:20
Definition operations.h:43
Definition vtable_for.h:17
Definition any.h:19
constexpr auto hybrid_storage_manage
Definition hybrid_storage.h:35
Definition any.h:18
StorageCategory
Definition storage_category.h:4
@ Immovable
Definition storage_category.h:8
@ MoveOnly
Definition storage_category.h:9
meta::Type< AnyT< UserInterface, Storage, VTablePolicy > > Any
Definition any.h:294
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
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
container::InfallibleAllocator DefaultAllocator
Definition custom.h:39
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 hybrid_storage.h:40
void * m_pointer
Definition hybrid_storage.h:177
static constexpr void move_construct(concepts::VTableFor< Interface > auto &vtable, HybridStorage *dest, HybridStorage *source)
Definition hybrid_storage.h:117
meta::List< Manage > Interface
Definition hybrid_storage.h:46
meta::Type< detail::HybridStorageManage< HybridStorage, Alloc > > Manage
Definition hybrid_storage.h:45
static constexpr auto creation_is_fallible(InPlaceType< T >) -> bool
Definition hybrid_storage.h:60
constexpr auto down_cast() const -> T const *
Definition hybrid_storage.h:161
static constexpr auto creation_is_inline(InPlaceType< T >) -> bool
Definition hybrid_storage.h:54
meta::Conditional< creation_is_fallible(in_place_type< T >), meta::AllocatorResult< Alloc >, void > CreationResult
Definition hybrid_storage.h:65
static constexpr auto storage_category() -> StorageCategory
Definition hybrid_storage.h:51
static constexpr void move_assign(VTable &dest_vtable, HybridStorage *dest, VTable &source_vtable, HybridStorage *source)
Definition hybrid_storage.h:130
static constexpr void destroy(concepts::VTableFor< Interface > auto &vtable, HybridStorage *self)
Definition hybrid_storage.h:139
static constexpr void create(InPlaceType< Any >, meta::LikeExpected< CreationResult< T >, Any > &self, InPlaceType< T >, Args &&... args)
Definition hybrid_storage.h:75
static constexpr auto init(HybridStorage *self, InPlaceType< T >, Args &&... args)
Definition hybrid_storage.h:96
byte m_storage[inline_size]
Definition hybrid_storage.h:178
auto operator=(HybridStorage const &) -> HybridStorage &=delete
constexpr auto down_cast() -> T *
Definition hybrid_storage.h:149
HybridStorage(HybridStorage const &)=delete
Definition hybrid_storage.h:27
constexpr void operator()(T &, HybridStorage *, HybridStorage *, Alloc &) const
Definition hybrid_storage.h:186
Method< HybridStorageManage, void(This &, HybridStorage *, HybridStorage *, Alloc &)> Type
Definition hybrid_storage.h:28
Definition core.h:5
Definition in_place_type.h:5
Definition method.h:7
Definition this.h:4