AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
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);
154 template<typename T>
155 static _unique<T> unique(T* raw);
156
164 template<typename T>
165 static _<T> fake(T* raw);
166 };
167}
168
169
175template<typename T>
176class _ : public std::shared_ptr<T>
177{
178 friend struct aui::ptr;
179private:
180 using super = std::shared_ptr<T>;
181
182 _(T* raw, std::nullopt_t): std::shared_ptr<T>(raw) {
183
184 }
185
186#ifdef AUI_SHARED_PTR_FIND_INSTANCES
187 friend API_AUI_CORE void aui::impl::shared_ptr::printAllInstancesOf(void* ptrToSharedPtr) noexcept;
188 struct InstanceDescriber;
189
190 static AStacktrace makeStacktrace();
191
192 struct InstanceDescriber {
193 aui::fast_pimpl<AStacktrace, sizeof(std::vector<int>) + 8, alignof(std::vector<int>)> stacktrace;
194 _<T>* self;
195 T* pointingTo;
196
197 InstanceDescriber(_<T>* self): stacktrace(_<T>::makeStacktrace()), self(self), pointingTo(self->get()) {
198 if (pointingTo == nullptr) return;
199 std::unique_lock lock(aui::impl::shared_ptr::instances().sync);
200 aui::impl::shared_ptr::instances().map[pointingTo].insert(self);
201 //std::printf("[AUI_SHARED_PTR_FIND_INSTANCES] %s << %p\n", AClass<T>::name().toStdString().c_str(), pointingTo);
202 }
203
204 InstanceDescriber(const InstanceDescriber&) = delete;
205 InstanceDescriber(InstanceDescriber&&) = delete;
206
207 ~InstanceDescriber() {
208 if (pointingTo == nullptr) return;
209 auto& inst = aui::impl::shared_ptr::instances();
210 std::unique_lock lock(inst.sync);
211 if (auto mapIt = inst.map.find(pointingTo); mapIt != inst.map.end()) {
212 auto setIt = mapIt->second.find(self);
213 AUI_ASSERT(setIt != mapIt->second.end());
214 mapIt->second.erase(setIt);
215 if (mapIt->second.empty()) {
216 //inst.map.erase(it);
217 }
218 }
219 //std::printf("[AUI_SHARED_PTR_FIND_INSTANCES] %s >> %p\n", AClass<T>::name().toStdString().c_str(), pointingTo);
220 }
221 } mInstanceDescriber = this;
222
223#endif
224
225public:
226 using stored_t = T;
227
228
229#ifdef AUI_SHARED_PTR_FIND_INSTANCES
230 void printAllInstances() {
231 aui::impl::shared_ptr::printAllInstancesOf(this);
232 }
233 void printAllInstances() const {
234 const_cast<_<T>&>(*this).printAllInstances();
235 }
236#endif
237
238 using std::shared_ptr<T>::shared_ptr;
239
240 _(const std::shared_ptr<T>& v): std::shared_ptr<T>(v) {}
241 _(std::shared_ptr<T>&& v) noexcept: std::shared_ptr<T>(std::move(v)) {}
242 _(const _& v): std::shared_ptr<T>(v) {}
243 _(_&& v) noexcept: std::shared_ptr<T>(std::move(v)) {}
244 _(const std::weak_ptr<T>& v): std::shared_ptr<T>(v) {}
245 _(const _weak<T>& v): std::shared_ptr<T>(v) {}
246
247 _& operator=(const _& rhs) noexcept {
248 std::shared_ptr<T>::operator=(rhs);
249 return *this;
250 }
251
252 _& operator=(_&& rhs) noexcept {
253 std::shared_ptr<T>::operator=(std::forward<_>(rhs));
254 return *this;
255 }
256
262 _(T* v) = delete;
263
267 [[nodiscard]]
268 _weak<T> weak() const {
269 return _weak<T>(*this);
270 }
271
272 template<typename SignalField, typename Object, typename Function>
273 inline _<T>& connect(SignalField signalField, Object object, Function&& function);
274
275 template<typename SignalField, typename Function>
276 inline _<T>& connect(SignalField signalField, Function&& function);
277
278
279 template <typename Functor>
280 inline _<T>& operator^(Functor&& functor) {
281 functor(*this);
282 return *this;
283 }
284 // forward ranged-for loops
285 auto begin() const {
286 return super::operator->()->begin();
287 }
288 auto end() const {
289 return super::operator->()->end();
290 }
291 auto begin() {
292 return super::operator->()->begin();
293 }
294 auto end() {
295 return super::operator->()->end();
296 }
297
298 // operators
299
300 template<typename Arg>
301 const _<T>& operator<<(Arg&& value) const {
302 (*super::get()) << std::forward<Arg>(value);
303 return *this;
304 }
305
306 template<typename Arg>
307 _<T>& operator<<(Arg&& value) {
308 (*super::get()) << std::forward<Arg>(value);
309 return *this;
310 }
311
312 template<typename... Arg>
313 auto operator()(Arg&&... value) const requires std::is_invocable_v<T, Arg...> {
314 return (*super::get())(std::forward<Arg>(value)...);
315 }
316
317 template<typename Arg>
318 const _<T>& operator+(Arg&& value) const {
319 (*super::get()) + std::forward<Arg>(value);
320 return *this;
321 }
322
323 template<typename Arg>
324 _<T>& operator+(Arg&& value) {
325 (*super::get()) + std::forward<Arg>(value);
326 return *this;
327 }
328
329 template<typename Arg>
330 const _<T>& operator*(Arg&& value) {
331 (*super::get()) * std::forward<Arg>(value);
332 return *this;
333 }
334
335 [[nodiscard]]
336 std::add_lvalue_reference_t<T> operator*() const noexcept {
337 return super::operator*();
338 }
339
340 template<typename Arg>
341 const _<T>& operator-(Arg&& value) const {
342 (*super::get()) - std::forward<Arg>(value);
343 return *this;
344 }
345
346 template<typename Arg>
347 _<T>& operator-(Arg&& value) {
348 (*super::get()) - std::forward<Arg>(value);
349 return *this;
350 }
351 template<typename Arg>
352 _<T>& operator>>(Arg&& value) {
353 (*super::get()) >> std::forward<Arg>(value);
354 return *this;
355 }
356
357 template<typename...Args>
358 _<T>& operator()(const Args&... value) {
359 (*super::get())(value...);
360 return *this;
361 }
362 template<typename...Args>
363 auto operator()(Args&&... value) {
364 return (*super::get())(std::forward<Args>(value)...);
365 }
366};
367
368
369namespace aui {
370 template<typename T>
372 return _<T>(raw, std::nullopt);
373 }
374
375 template<typename T>
376 _<T> ptr::fake(T* raw) {
377 return _<T>(std::shared_ptr<void>{}, raw);
378 }
379
380 template<typename T, typename Deleter>
381 _<T> ptr::manage(T* raw, Deleter deleter) {
382 return _<T>(raw, deleter);
383 }
384 template<typename T>
385 _unique<T> ptr::unique(T* raw) {
386 return _unique<T>(raw);
387 }
388}
389
390template<typename TO, typename FROM>
391inline TO* _cast(const _unique<FROM>& object)
392{
393 return dynamic_cast<TO*>(object.get());
394}
395
396template<typename TO, typename FROM>
397inline _<TO> _cast(const _<FROM>& object)
398{
399 return std::dynamic_pointer_cast<TO, FROM>(object);
400}
401
402template<typename TO, typename FROM>
403inline _<TO> _cast(_<FROM>&& object)
404{
405 return std::dynamic_pointer_cast<TO, FROM>(std::move(object));
406}
407
408template<typename TO, typename FROM>
409inline _<TO> _cast(const std::shared_ptr<FROM>& object)
410{
411 return std::dynamic_pointer_cast<TO, FROM>(object);
412}
413
414
415template<typename TO, typename FROM>
416inline _<TO> _cast(std::shared_ptr<FROM>&& object)
417{
418 return std::dynamic_pointer_cast<TO, FROM>(std::move(object));
419}
420
421
422
464#define AUI_NULLSAFE(s) if(decltype(auto) _tmp = (s))_tmp
A base object class.
Definition: AObject.h:49
Stacktrace consisting of a collection of stack function frames.
Definition: AStacktrace.h:28
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
_(T *v)=delete
_weak< T > weak() const
Definition: SharedPtrTypes.h:268
#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)
Definition: SharedPtrTypes.h:385
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)
Definition: SharedPtrTypes.h:371
static _< T > fake(T *raw)
Definition: SharedPtrTypes.h:376