Iros
 
Loading...
Searching...
No Matches
arc.h
Go to the documentation of this file.
1#pragma once
2
8#include "di/sync/atomic.h"
9#include "di/util/immovable.h"
10#include "di/util/std_new.h"
16
17namespace di::vocab {
18struct ArcTag {};
19
20template<typename T>
22
23template<typename T>
25private:
26 template<typename>
27 friend struct MakeArcFunction;
28
29public:
30 template<typename = void>
31 constexpr auto arc_from_this() {
32 return Arc<T>(static_cast<T*>(this), adopt_object);
33 }
34
35protected:
36 IntrusiveRefCount() = default;
37
38private:
40 auto* base = static_cast<IntrusiveRefCount*>(pointer);
41 base->m_ref_count.fetch_add(1, sync::MemoryOrder::Relaxed);
42 }
43
45 auto* base = static_cast<IntrusiveRefCount*>(pointer);
46 if (base->m_ref_count.fetch_sub(1, sync::MemoryOrder::AcquireRelease) == 1) {
47 delete pointer;
48 }
49 }
50
51 template<typename... Args, typename R = meta::AllocatorResult<platform::DefaultAllocator, T*>>
52 constexpr static auto make(Args&&... args) -> R
53 requires(requires { new (std::nothrow) T(util::forward<Args>(args)...); })
54 {
55 if consteval {
56 return new T(util::forward<Args>(args)...);
57 }
58 auto* result = new (std::nothrow) T(util::forward<Args>(args)...);
59 if constexpr (concepts::FallibleAllocator<platform::DefaultAllocator>) {
60 if (!result) {
61 return vocab::Unexpected(platform::BasicError::NotEnoughMemory);
62 }
63 } else {
64 DI_ASSERT(result);
65 }
66 return result;
67 }
68
69 sync::Atomic<usize> m_ref_count { 1 };
70};
71
72template<typename T>
74 template<typename... Args>
75 constexpr auto operator()(Args&&... args) const
76 requires(requires { IntrusiveRefCount<T>::make(util::forward<Args>(args)...); })
77 {
78 return vocab::as_fallible(IntrusiveRefCount<T>::make(util::forward<Args>(args)...)) % [](T* pointer) {
79 return Arc<T>(pointer, retain_object);
81 }
82};
83
84template<detail::IntrusivePtrValid<ArcTag> T>
85constexpr inline auto make_arc = MakeArcFunction<T> {};
86}
87
88namespace di {
89using vocab::Arc;
90using vocab::IntrusiveRefCount;
91using vocab::make_arc;
92}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition intrusive_ptr.h:25
meta::LikeExpected< decltype(di::allocate(util::declval< Alloc & >(), 0, 0)), T > AllocatorResult
Definition allocator.h:25
@ Relaxed
Definition memory_order.h:7
@ AcquireRelease
Definition memory_order.h:11
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition lazy.h:165
constexpr auto adopt_object
Definition intrusive_ptr.h:22
constexpr auto make_arc
Definition arc.h:85
constexpr auto as_fallible
Definition as_fallible.h:26
constexpr auto try_infallible
Definition try_infallible.h:31
IntrusivePtr< T, ArcTag > Arc
Definition arc.h:21
Unexpected(E &&) -> Unexpected< meta::UnwrapRefDecay< E > >
constexpr auto retain_object
Definition intrusive_ptr.h:17
Definition zstring_parser.h:9
Definition in_place_type.h:5
Definition immovable.h:4
Definition arc.h:18
constexpr friend void tag_invoke(types::Tag< intrusive_ptr_decrement >, InPlaceType< ArcTag >, T *pointer)
Definition arc.h:44
constexpr friend void tag_invoke(types::Tag< intrusive_ptr_increment >, InPlaceType< ArcTag >, T *pointer)
Definition arc.h:39
friend struct MakeArcFunction
Definition arc.h:27
constexpr auto arc_from_this()
Definition arc.h:31
Definition arc.h:73
constexpr auto operator()(Args &&... args) const
Definition arc.h:75