1 /*
2 * Copyright (c) 2025 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 API_BASE_CONTAINERS_SHARED_PTR_INTERNALS_H
17 #define API_BASE_CONTAINERS_SHARED_PTR_INTERNALS_H
18
19 #include <base/containers/atomics.h>
20 #include <base/containers/type_traits.h>
21 #include <base/namespace.h>
22 #include <base/util/log.h>
23
BASE_BEGIN_NAMESPACE()24 BASE_BEGIN_NAMESPACE()
25 namespace Internals {
26 template<typename U, typename T>
27 using EnableIfPointerConvertible = BASE_NS::enable_if_t<BASE_NS::is_convertible_v<U*, T*>>;
28
29 class ControlBlock {
30 public:
31 ControlBlock() = default;
32 virtual ~ControlBlock() = default;
33
34 ControlBlock(const ControlBlock&) = delete;
35 ControlBlock& operator=(const ControlBlock&) = delete;
36 ControlBlock(ControlBlock&&) = delete;
37 ControlBlock& operator=(ControlBlock&&) = delete;
38
39 void AddStrongCopy() noexcept
40 {
41 BASE_NS::AtomicIncrementRelaxed(&strongCount_);
42 }
43
44 void AddWeak() noexcept
45 {
46 BASE_NS::AtomicIncrementRelaxed(&weakCount_);
47 }
48
49 void Release()
50 {
51 if (BASE_NS::AtomicDecrementRelease(&strongCount_) == 0) {
52 BASE_NS::AtomicFenceAcquire();
53 Dispose();
54 // The strong references are counted as one weak references to keep the control block alive
55 ReleaseWeak();
56 }
57 }
58
59 void ReleaseWeak()
60 {
61 // The weak count is initialised to 1, so releasing weak pointers does not destroy
62 // the control block unless there is no more strong references
63 if (BASE_NS::AtomicDecrementRelease(&weakCount_) == 0) {
64 BASE_NS::AtomicFenceAcquire();
65 Destroy();
66 }
67 }
68
69 bool AddStrongLock() noexcept
70 {
71 return BASE_NS::AtomicIncrementIfNotZero(&strongCount_) != 0;
72 }
73
74 int32_t GetStrongCount() const noexcept
75 {
76 return BASE_NS::AtomicReadRelaxed(&strongCount_);
77 }
78 int32_t GetWeakCount() const noexcept
79 {
80 return BASE_NS::AtomicReadRelaxed(&weakCount_);
81 }
82
83 virtual void Destroy() = 0;
84 virtual void Dispose() = 0;
85
86 private:
87 // Count of the weak references +1 for the strong references
88 int32_t weakCount_ { 1 };
89 int32_t strongCount_ { 1 };
90 };
91
92 class ptr_base {
93 protected:
94 ptr_base() = default;
95 ~ptr_base() = default;
96 ptr_base(const ptr_base&) = default;
97 ptr_base(ptr_base&&) = default;
98 ptr_base& operator=(const ptr_base&) = default;
99 ptr_base& operator=(ptr_base&&) = default;
100 };
101
102 template<typename Type>
103 class PtrCountedBase : public ptr_base {
104 public:
105 // NOLINTNEXTLINE(readability-identifier-naming) to keep std like syntax
106 int32_t use_count() const noexcept
107 {
108 return control_ ? control_->GetStrongCount() : 0;
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() noexcept
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 BASE_ASSERT(ptr != nullptr);
143 }
144
145 void Destroy() final
146 {
147 delete this;
148 }
149
150 void Dispose() final
151 {
152 delete ptr_;
153 }
154
155 private:
156 T* ptr_ { nullptr };
157 };
158
159 template<typename T, typename Deleter = DefaultDeleterType<T>>
160 class StorageBlockWithDeleter final : public ControlBlock {
161 public:
162 StorageBlockWithDeleter(T* ptr, Deleter deleter) : ptr_ { ptr }, deleter_ { BASE_NS::move(deleter) }
163 {
164 BASE_ASSERT(ptr != nullptr);
165 }
166
167 void Destroy() final
168 {
169 delete this;
170 }
171
172 void Dispose() final
173 {
174 deleter_(ptr_);
175 }
176
177 private:
178 T* ptr_ { nullptr };
179 Deleter deleter_;
180 };
181
182 template<typename T>
183 class RefCountedObjectStorageBlock final : public ControlBlock {
184 public:
185 using deletableType = BASE_NS::remove_const_t<T>;
186
187 explicit RefCountedObjectStorageBlock(T* ptr) : ptr_ { ptr }
188 {
189 BASE_ASSERT(ptr != nullptr);
190 const_cast<deletableType*>(ptr)->Ref();
191 }
192
193 void Destroy() final
194 {
195 delete this;
196 }
197
198 void Dispose() final
199 {
200 const_cast<deletableType*>(ptr_)->Unref();
201 }
202
203 private:
204 T* ptr_ { nullptr };
205 };
206 } // namespace Internals
207 BASE_END_NAMESPACE()
208
209 #endif // API_BASE_CONTAINERS_SHARED_PTR_INTERNALS_H
210