AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
SharedPtrTypes.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include <memory>
15#include <functional>
16#include <optional>
17#include <type_traits>
18
19class AObject;
20
21#ifdef AUI_SHARED_PTR_FIND_INSTANCES
22#include <AUI/api.h>
23#include <AUI/Util/APimpl.h>
24#include <map>
25#include <set>
26#include <mutex>
27#include <AUI/Reflect/AClass.h>
28
29class API_AUI_CORE AStacktrace;
30
31namespace aui::impl::shared_ptr {
32 struct InstancesDict {
33 std::recursive_mutex sync;
34 std::map<void*, std::set<void*>> map;
35 };
36
37 API_AUI_CORE InstancesDict& instances() noexcept;
38 API_AUI_CORE void printAllInstancesOf(void* ptrToSharedPtr) noexcept;
39}
40
41#endif
42
43template<typename T>
44class _;
45
50template<typename T>
51struct _weak: public std::weak_ptr<T> {
52private:
53 using super = std::weak_ptr<T>;
54
55public:
56 using super::weak_ptr;
57
58 _weak(const _weak<T>& v) noexcept: std::weak_ptr<T>(v) {}
59 _weak(_weak<T>&& v) noexcept: std::weak_ptr<T>(std::move(v)) {}
60 _weak(const std::weak_ptr<T>& v): std::weak_ptr<T>(v) {}
61 _weak(std::weak_ptr<T>&& v) noexcept: std::weak_ptr<T>(std::move(v)) {}
62
63 _<T> lock() const noexcept {
64 return static_cast<_<T>>(super::lock());
65 }
66
67 _weak& operator=(const std::weak_ptr<T>& v) noexcept {
68 super::weak_ptr::operator=(v);
69 return *this;
70 }
71
72 _weak& operator=(std::weak_ptr<T>&& v) noexcept {
73 super::weak_ptr::operator=(std::move(v));
74 return *this;
75 }
76
77 _weak& operator=(const _weak<T>& v) noexcept {
78 super::weak_ptr::operator=(v);
79 return *this;
80 }
81
82 _weak& operator=(_weak<T>&& v) noexcept {
83 super::weak_ptr::operator=(std::move(v));
84 return *this;
85 }
86
87 _weak& operator=(const std::shared_ptr<T>& v) noexcept {
88 super::weak_ptr::operator=(v);
89 return *this;
90 }
91
92 _weak& operator=(std::shared_ptr<T>&& v) noexcept {
93 super::weak_ptr::operator=(std::move(v));
94 return *this;
95 }
96
97 _weak& operator=(const _<T>& v) noexcept {
98 super::weak_ptr::operator=(v);
99 return *this;
100 }
101
102 _weak& operator=(_<T>&& v) noexcept {
103 super::weak_ptr::operator=(std::move(v));
104 return *this;
105 }
106};
107
108template<typename T, typename Deleter = std::default_delete<T>>
109using _unique = std::unique_ptr<T, Deleter>;
110
111
112namespace aui {
113
114 struct ptr {
124 template<typename T, typename Deleter = std::default_delete<T>>
125 static _unique<T, Deleter> make_unique_with_deleter(T* ptr, Deleter deleter = Deleter{}) {
126 return { ptr, std::move(deleter) };
127 }
128
135 template<typename T>
136 static _<T> manage(T* raw);
137
146 template<typename T, typename Deleter>
147 static _<T> manage(T* raw, Deleter deleter);
148
155 template<typename T>
156 static _unique<T> unique(T* raw);
157
165 template<typename T>
166 static _<T> fake(T* raw);
167 };
168}
169
170
176template<typename T>
177class _ : public std::shared_ptr<T>
178{
179 friend struct aui::ptr;
180private:
181 using super = std::shared_ptr<T>;
182
183 _(T* raw, std::nullopt_t): std::shared_ptr<T>(raw) {
184
185 }
186
187#ifdef AUI_SHARED_PTR_FIND_INSTANCES
188 friend API_AUI_CORE void aui::impl::shared_ptr::printAllInstancesOf(void* ptrToSharedPtr) noexcept;
189 struct InstanceDescriber;
190
191 static AStacktrace makeStacktrace();
192
193 struct InstanceDescriber {
194 aui::fast_pimpl<AStacktrace, sizeof(std::vector<int>) + 8, alignof(std::vector<int>)> stacktrace;
195 _<T>* self;
196 T* pointingTo;
197
198 InstanceDescriber(_<T>* self): stacktrace(_<T>::makeStacktrace()), self(self), pointingTo(self->get()) {
199 if (pointingTo == nullptr) return;
200 std::unique_lock lock(aui::impl::shared_ptr::instances().sync);
201 aui::impl::shared_ptr::instances().map[pointingTo].insert(self);
202 //std::printf("[AUI_SHARED_PTR_FIND_INSTANCES] %s << %p\n", AClass<T>::name().toStdString().c_str(), pointingTo);
203 }
204
205 InstanceDescriber(const InstanceDescriber&) = delete;
206 InstanceDescriber(InstanceDescriber&&) = delete;
207
208 ~InstanceDescriber() {
209 if (pointingTo == nullptr) return;
210 auto& inst = aui::impl::shared_ptr::instances();
211 std::unique_lock lock(inst.sync);
212 if (auto mapIt = inst.map.find(pointingTo); mapIt != inst.map.end()) {
213 auto setIt = mapIt->second.find(self);
214 AUI_ASSERT(setIt != mapIt->second.end());
215 mapIt->second.erase(setIt);
216 if (mapIt->second.empty()) {
217 //inst.map.erase(it);
218 }
219 }
220 //std::printf("[AUI_SHARED_PTR_FIND_INSTANCES] %s >> %p\n", AClass<T>::name().toStdString().c_str(), pointingTo);
221 }
222 } mInstanceDescriber = this;
223
224#endif
225
226public:
227 using stored_t = T;
228
229
230#ifdef AUI_SHARED_PTR_FIND_INSTANCES
231 void printAllInstances() {
232 aui::impl::shared_ptr::printAllInstancesOf(this);
233 }
234 void printAllInstances() const {
235 const_cast<_<T>&>(*this).printAllInstances();
236 }
237#endif
238
239 using std::shared_ptr<T>::shared_ptr;
240
241 _(const std::shared_ptr<T>& v): std::shared_ptr<T>(v) {}
242 _(std::shared_ptr<T>&& v) noexcept: std::shared_ptr<T>(std::move(v)) {}
243 _(const _& v): std::shared_ptr<T>(v) {}
244 _(_&& v) noexcept: std::shared_ptr<T>(std::move(v)) {}
245 _(const std::weak_ptr<T>& v): std::shared_ptr<T>(v) {}
246 _(const _weak<T>& v): std::shared_ptr<T>(v) {}
247
248 _& operator=(const _& rhs) noexcept {
249 std::shared_ptr<T>::operator=(rhs);
250 return *this;
251 }
252
253 _& operator=(_&& rhs) noexcept {
254 std::shared_ptr<T>::operator=(std::forward<_>(rhs));
255 return *this;
256 }
257
263 _(T* v) = delete;
264
268 [[nodiscard]]
269 _weak<T> weak() const {
270 return _weak<T>(*this);
271 }
272
273 template<typename SignalField, typename Object, typename Function>
274 inline _<T>& connect(SignalField signalField, Object object, Function&& function);
275
276 template<typename SignalField, typename Function>
277 inline _<T>& connect(SignalField signalField, Function&& function);
278
279
280 template <typename Functor>
281 inline _<T>& operator^(Functor&& functor) {
282 functor(*this);
283 return *this;
284 }
285 // forward ranged-for loops
286 auto begin() const {
287 return super::operator->()->begin();
288 }
289 auto end() const {
290 return super::operator->()->end();
291 }
292 auto begin() {
293 return super::operator->()->begin();
294 }
295 auto end() {
296 return super::operator->()->end();
297 }
298
299 // operators
300
301 template<typename Arg>
302 const _<T>& operator<<(Arg&& value) const {
303 (*super::get()) << std::forward<Arg>(value);
304 return *this;
305 }
306
307 template<typename Arg>
308 _<T>& operator<<(Arg&& value) {
309 (*super::get()) << std::forward<Arg>(value);
310 return *this;
311 }
312
313 template<typename... Arg>
314 auto operator()(Arg&&... value) const requires std::is_invocable_v<T, Arg...> {
315 return (*super::get())(std::forward<Arg>(value)...);
316 }
317
318 template<typename Arg>
319 const _<T>& operator+(Arg&& value) const {
320 (*super::get()) + std::forward<Arg>(value);
321 return *this;
322 }
323
324 template<typename Arg>
325 _<T>& operator+(Arg&& value) {
326 (*super::get()) + std::forward<Arg>(value);
327 return *this;
328 }
329
330 template<typename Arg>
331 const _<T>& operator*(Arg&& value) {
332 (*super::get()) * std::forward<Arg>(value);
333 return *this;
334 }
335
336 [[nodiscard]]
337 std::add_lvalue_reference_t<T> operator*() const noexcept {
338 return super::operator*();
339 }
340
341 template<typename Arg>
342 const _<T>& operator-(Arg&& value) const {
343 (*super::get()) - std::forward<Arg>(value);
344 return *this;
345 }
346
347 template<typename Arg>
348 _<T>& operator-(Arg&& value) {
349 (*super::get()) - std::forward<Arg>(value);
350 return *this;
351 }
352 template<typename Arg>
353 _<T>& operator>>(Arg&& value) {
354 (*super::get()) >> std::forward<Arg>(value);
355 return *this;
356 }
357
358 template<typename...Args>
359 _<T>& operator()(const Args&... value) {
360 (*super::get())(value...);
361 return *this;
362 }
363 template<typename...Args>
364 auto operator()(Args&&... value) {
365 return (*super::get())(std::forward<Args>(value)...);
366 }
367};
368
369
370namespace aui {
371 template<typename T>
373 return _<T>(raw, std::nullopt);
374 }
375
376 template<typename T>
377 _<T> ptr::fake(T* raw) {
378 return _<T>(std::shared_ptr<void>{}, raw);
379 }
380
381 template<typename T, typename Deleter>
382 _<T> ptr::manage(T* raw, Deleter deleter) {
383 return _<T>(raw, deleter);
384 }
385 template<typename T>
386 _unique<T> ptr::unique(T* raw) {
387 return _unique<T>(raw);
388 }
389}
390
391template<typename TO, typename FROM>
392inline TO* _cast(const _unique<FROM>& object)
393{
394 return dynamic_cast<TO*>(object.get());
395}
396
397template<typename TO, typename FROM>
398inline _<TO> _cast(const _<FROM>& object)
399{
400 return std::dynamic_pointer_cast<TO, FROM>(object);
401}
402
403template<typename TO, typename FROM>
404inline _<TO> _cast(_<FROM>&& object)
405{
406 return std::dynamic_pointer_cast<TO, FROM>(std::move(object));
407}
408
409template<typename TO, typename FROM>
410inline _<TO> _cast(const std::shared_ptr<FROM>& object)
411{
412 return std::dynamic_pointer_cast<TO, FROM>(object);
413}
414
415
416template<typename TO, typename FROM>
417inline _<TO> _cast(std::shared_ptr<FROM>&& object)
418{
419 return std::dynamic_pointer_cast<TO, FROM>(std::move(object));
420}
421
422
423
465#define AUI_NULLSAFE(s) if(decltype(auto) _tmp = (s))_tmp
A base object class.
Definition AObject.h:39
Stacktrace consisting of a collection of stack function frames.
Definition AStacktrace.h:28
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:178
_(T *v)=delete
_weak< T > weak() const
Definition SharedPtrTypes.h:269
ParentSubSelector< L, R > operator>>(L l, R r)
Makes indirect parent subselector.
Definition ParentSelector.h:89
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:51
Utility wrapper implementing the stack-allocated (fast) pimpl idiom.
Definition APimpl.h:31
Definition SharedPtrTypes.h:114
static _unique< T > unique(T *raw)
Delegates memory management of the raw pointer T* raw to the unique pointer, which is returned.
Definition SharedPtrTypes.h:386
static _unique< T, Deleter > make_unique_with_deleter(T *ptr, Deleter deleter=Deleter{})
Creates unique_ptr from raw pointer and a deleter.
Definition SharedPtrTypes.h:125
static _< T > manage(T *raw)
Delegates memory management of the raw pointer T* raw to the shared pointer, which is returned.
Definition SharedPtrTypes.h:372
static _< T > fake(T *raw)
Creates fake shared pointer to T* raw with empty destructor, which does nothing. It's useful when som...
Definition SharedPtrTypes.h:377