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