• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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