• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     int32_t GetWeakCount() const
77     {
78         return CORE_NS::AtomicRead(&weakCount_);
79     }
80 
81     virtual void Destroy() = 0;
82     virtual void Dispose() = 0;
83 
84 private:
85     // Count of the weak references +1 for the strong references
86     int32_t weakCount_ { 1 };
87     int32_t strongCount_ { 1 };
88 };
89 
90 class ptr_base {
91 protected:
92     ptr_base() = default;
93     ~ptr_base() = default;
94     ptr_base(const ptr_base&) = default;
95     ptr_base(ptr_base&&) = default;
96     ptr_base& operator=(const ptr_base&) = default;
97     ptr_base& operator=(ptr_base&&) = default;
98 };
99 
100 template<typename Type>
101 class PtrCountedBase : public ptr_base {
102 public:
103     // for compatibility
104     template<typename U>
105     bool Compare(const PtrCountedBase<U>& p) const
106     {
107         return static_cast<const void*>(pointer_) == static_cast<const void*>(p.pointer_);
108     }
109     template<typename U>
110     bool CompareOwner(const PtrCountedBase<U>& p) const
111     {
112         return control_ == p.control_;
113     }
114 
115     // NOLINTNEXTLINE(readability-identifier-naming) to keep std like syntax
116     int32_t use_count() const
117     {
118         return control_ ? control_->GetStrongCount() : 0;
119     }
120 
121 protected:
122     PtrCountedBase() = default;
123     PtrCountedBase(ControlBlock* c) : control_(c) {}
124     ~PtrCountedBase() = default;
125     PtrCountedBase(const PtrCountedBase&) = default;
126     PtrCountedBase& operator=(const PtrCountedBase&) = default;
127     PtrCountedBase(PtrCountedBase&&) = default;
128     PtrCountedBase& operator=(PtrCountedBase&&) = default;
129 
130     void InternalReset()
131     {
132         control_ = nullptr;
133         pointer_ = nullptr;
134     }
135 
136 protected:
137     Type* pointer_ {};
138     ControlBlock* control_ {};
139 
140     template<typename>
141     friend class PtrCountedBase;
142 };
143 
144 template<typename T>
145 using DefaultDeleterType = void (*)(T*);
146 
147 template<typename T>
148 class StorageBlock final : public ControlBlock {
149 public:
150     explicit StorageBlock(T* ptr) : ptr_ { ptr }
151     {
152         assert(ptr != nullptr);
153     }
154 
155     void Destroy() final
156     {
157         delete this;
158     }
159 
160     void Dispose() final
161     {
162         delete ptr_;
163     }
164 
165 private:
166     T* ptr_ { nullptr };
167 };
168 
169 template<typename T, typename Deleter = DefaultDeleterType<T>>
170 class StorageBlockWithDeleter final : public ControlBlock {
171 public:
172     StorageBlockWithDeleter(T* ptr, Deleter deleter) : ptr_ { ptr }, deleter_ { BASE_NS::move(deleter) }
173     {
174         assert(ptr != nullptr);
175     }
176 
177     void Destroy() final
178     {
179         delete this;
180     }
181 
182     void Dispose() final
183     {
184         deleter_(ptr_);
185     }
186 
187 private:
188     T* ptr_ { nullptr };
189     Deleter deleter_;
190 };
191 
192 template<typename T>
193 class RefCountedObjectStorageBlock final : public ControlBlock {
194 public:
195     using deletableType = BASE_NS::remove_const_t<T>;
196 
197     explicit RefCountedObjectStorageBlock(T* ptr) : ptr_ { ptr }
198     {
199         assert(ptr != nullptr);
200         const_cast<deletableType*>(ptr)->Ref();
201     }
202 
203     void Destroy() final
204     {
205         delete this;
206     }
207 
208     void Dispose() final
209     {
210         const_cast<deletableType*>(ptr_)->Unref();
211     }
212 
213 private:
214     T* ptr_ { nullptr };
215 };
216 
217 } // namespace Internals
218 BASE_END_NAMESPACE()
219 
220 #endif
221