1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef META_BASE_SHARED_PTR_INTERNALS_H
17 #define META_BASE_SHARED_PTR_INTERNALS_H
18
19 #include <base/containers/unique_ptr.h>
20 #include <base/namespace.h>
21 #include <core/log.h>
22
23 #include <meta/base/atomics.h>
24 #include <meta/base/interface_macros.h>
25 #include <meta/base/interface_traits.h>
26
BASE_BEGIN_NAMESPACE()27 BASE_BEGIN_NAMESPACE()
28 namespace Internals {
29
30 template<typename U, typename T>
31 using EnableIfPointerConvertible = BASE_NS::enable_if_t<BASE_NS::is_convertible_v<U*, T*>>;
32
33 class ControlBlock {
34 public:
35 ControlBlock() = default;
36 virtual ~ControlBlock() = default;
37 META_NO_COPY_MOVE(ControlBlock)
38
39 void AddStrongCopy()
40 {
41 CORE_NS::AtomicIncrement(&strongCount_);
42 }
43
44 void AddWeak()
45 {
46 CORE_NS::AtomicIncrement(&weakCount_);
47 }
48
49 void Release()
50 {
51 if (CORE_NS::AtomicDecrement(&strongCount_) == 0) {
52 Dispose();
53 // The strong references are counted as one weak references to keep the control block alive
54 ReleaseWeak();
55 }
56 }
57
58 void ReleaseWeak()
59 {
60 // The weak count is initialised to 1, so releasing weak pointers does not destroy
61 // the control block unless there is no more strong references
62 if (CORE_NS::AtomicDecrement(&weakCount_) == 0) {
63 Destroy();
64 }
65 }
66
67 bool AddStrongLock()
68 {
69 return CORE_NS::AtomicIncrementIfNotZero(&strongCount_) != 0;
70 }
71
72 int32_t GetStrongCount() const
73 {
74 return CORE_NS::AtomicRead(&strongCount_);
75 }
76
77 virtual void Destroy() = 0;
78 virtual void Dispose() = 0;
79
80 private:
81 // Count of the weak references +1 for the strong references
82 int32_t weakCount_ { 1 };
83 int32_t strongCount_ { 1 };
84 };
85
86 class ptr_base {
87 protected:
88 ptr_base() = default;
89 ~ptr_base() = default;
90 ptr_base(const ptr_base&) = default;
91 ptr_base(ptr_base&&) = default;
92 ptr_base& operator=(const ptr_base&) = default;
93 ptr_base& operator=(ptr_base&&) = default;
94 };
95
96 template<typename Type>
97 class PtrCountedBase : public ptr_base {
98 public:
99 // for compatibility
100 template<typename U>
101 bool Compare(const PtrCountedBase<U>& p) const
102 {
103 return static_cast<const void*>(pointer_) == static_cast<const void*>(p.pointer_);
104 }
105 template<typename U>
106 bool CompareOwner(const PtrCountedBase<U>& p) const
107 {
108 return control_ == p.control_;
109 }
110
111 protected:
112 PtrCountedBase() = default;
113 PtrCountedBase(ControlBlock* c) : control_(c) {}
114 ~PtrCountedBase() = default;
115 PtrCountedBase(const PtrCountedBase&) = default;
116 PtrCountedBase& operator=(const PtrCountedBase&) = default;
117 PtrCountedBase(PtrCountedBase&&) = default;
118 PtrCountedBase& operator=(PtrCountedBase&&) = default;
119
120 void InternalReset()
121 {
122 control_ = nullptr;
123 pointer_ = nullptr;
124 }
125
126 protected:
127 Type* pointer_ {};
128 ControlBlock* control_ {};
129
130 template<typename>
131 friend class PtrCountedBase;
132 };
133
134 template<typename T>
135 using DefaultDeleterType = void (*)(T*);
136
137 template<typename T>
138 class StorageBlock final : public ControlBlock {
139 public:
140 explicit StorageBlock(T* ptr) : ptr_ { ptr }
141 {
142 }
143
144 void Destroy() final
145 {
146 delete this;
147 }
148
149 void Dispose() final
150 {
151 delete ptr_;
152 }
153
154 private:
155 T* ptr_ { nullptr };
156 };
157
158 template<typename T, typename Deleter = DefaultDeleterType<T>>
159 class StorageBlockWithDeleter final : public ControlBlock {
160 public:
161 StorageBlockWithDeleter(T* ptr, Deleter deleter) : ptr_ { ptr }, deleter_ { BASE_NS::move(deleter) }
162 {
163 }
164
165 void Destroy() final
166 {
167 delete this;
168 }
169
170 void Dispose() final
171 {
172 deleter_(ptr_);
173 }
174
175 private:
176 T* ptr_ { nullptr };
177 Deleter deleter_;
178 };
179
180 template<typename T>
181 class RefCountedObjectStorageBlock final : public ControlBlock {
182 public:
183 using deletableType = BASE_NS::remove_const_t<T>;
184
185 explicit RefCountedObjectStorageBlock(T* ptr) : ptr_ { ptr }
186 {
187 const_cast<deletableType*>(ptr)->Ref();
188 }
189
190 void Destroy() final
191 {
192 delete this;
193 }
194
195 void Dispose() final
196 {
197 const_cast<deletableType*>(ptr_)->Unref();
198 }
199
200 private:
201 T* ptr_ { nullptr };
202 };
203
204 } // namespace Internals
205 BASE_END_NAMESPACE()
206
207 #endif
208