• 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 FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_BASE_REFERENCED_H
17 #define FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_BASE_REFERENCED_H
18 
19 #include "ui/base/lifecycle_checkable.h"
20 #include "ui/base/macros.h"
21 #include "ui/base/memory_monitor.h"
22 #include "ui/base/ref_counter.h"
23 
24 #define ACE_REMOVE(...)
25 
26 namespace OHOS::Ace {
27 
28 namespace NG {
29 class UiNodeGc;
30 } // namespace NG
31 
32 template<class T>
33 class RefPtr;
34 template<class T>
35 class WeakPtr;
36 
37 // Inherit this class to use 'RefPtr' and 'WeakPtr' to manage pointer of instance.
38 class ACE_FORCE_EXPORT Referenced : public LifeCycleCheckable {
39 public:
40     // Use raw pointer to construct 'RefPtr' and 'WeakPtr'.
41     template<class T, bool isNewOrRecycle = false>
Claim(T * rawPtr)42     static RefPtr<T> Claim(T* rawPtr)
43     {
44         if constexpr (isNewOrRecycle) {
45             if (rawPtr && rawPtr->RefCount()) {
46                 rawPtr->OnDetectedClaimDeathObj(isNewOrRecycle);
47             }
48         } else {
49             if (rawPtr && !rawPtr->RefCount()) {
50                 rawPtr->OnDetectedClaimDeathObj(isNewOrRecycle);
51             }
52         }
53         if (MemoryMonitor::IsEnable()) {
54             MemoryMonitor::GetInstance().Update(rawPtr, static_cast<Referenced*>(rawPtr));
55         }
56         return RefPtr<T>(rawPtr);
57     }
58     template<class T>
WeakClaim(T * rawPtr)59     static WeakPtr<T> WeakClaim(T* rawPtr)
60     {
61         return WeakPtr<T>(rawPtr);
62     }
63 
64     // 'Referenced::MakeRefPtr' is used to create new instance inherited from 'Referenced',
65     // and manager its pointer using 'RefPtr'.
66     template<class T, class... Args>
MakeRefPtr(Args &&...args)67     static RefPtr<T> MakeRefPtr(Args&&... args)
68     {
69         return Claim<T, true>(new T(std::forward<Args>(args)...));
70     }
71 
72     // Get raw pointer from 'RefPtr'.
73     template<class T>
RawPtr(const RefPtr<T> & ptr)74     static T* RawPtr(const RefPtr<T>& ptr)
75     {
76         return ptr.rawPtr_;
77     }
78     // Forbid getting raw pointer from rvalue 'RefPtr'.
79     template<class T>
80     static T* RawPtr(const RefPtr<T>&& ptr) = delete;
81 
IncRefCount()82     void IncRefCount()
83     {
84         refCounter_->IncStrongRef();
85     }
DecRefCount()86     void DecRefCount()
87     {
88         int32_t refCount = refCounter_->DecStrongRef();
89         if (refCount == 0 && MaybeRelease()) {
90             // Release this instance, while its strong reference have reduced to zero.
91             delete this;
92         }
93     }
94 
RefCount()95     int32_t RefCount() const
96     {
97         return refCounter_->StrongRefCount();
98     }
99 
100 protected:
101     explicit Referenced(bool threadSafe = true)
102         : refCounter_(threadSafe ? ThreadSafeRef::Create() : ThreadUnsafeRef::Create())
103     {
104         if (MemoryMonitor::IsEnable()) {
105             MemoryMonitor::GetInstance().Add(this);
106         }
107     }
108 
~Referenced()109     virtual ~Referenced()
110     {
111         // Decrease weak reference count held by 'Referenced' itself.
112         refCounter_->DecWeakRef();
113         refCounter_ = nullptr;
114         if (MemoryMonitor::IsEnable()) {
115             MemoryMonitor::GetInstance().Remove(this);
116         }
117     }
118 
MaybeRelease()119     virtual bool MaybeRelease()
120     {
121         return true;
122     }
123 
124 private:
125     template<class T>
126     friend class RefPtr;
127     template<class T>
128     friend class WeakPtr;
129 
130     void OnDetectedClaimDeathObj(bool isNewOrRecycle);
131     RefCounter* refCounter_ { nullptr };
132 
133     ACE_DISALLOW_COPY_AND_MOVE(Referenced);
134 
135     friend class NG::UiNodeGc;
136 };
137 
138 // Use reference count to manager instance inherited from 'Referenced'.
139 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function.
140 template<class T>
141 class RefPtr final {
142 public:
143     // Basic constructors.
144     RefPtr() = default;
RefPtr(std::nullptr_t)145     ACE_REMOVE(explicit) RefPtr(std::nullptr_t) {}
146     // Basic copy and move constructors.
RefPtr(const RefPtr & other)147     ACE_REMOVE(explicit) RefPtr(const RefPtr& other) : RefPtr(other.rawPtr_) {}
RefPtr(RefPtr && other)148     ACE_REMOVE(explicit) RefPtr(RefPtr&& other) : rawPtr_(other.rawPtr_)
149     {
150         other.rawPtr_ = nullptr;
151     }
152     // Construct instance by other 'RefPtr' that inherited from type 'T'.
153     template<class O>
ACE_REMOVE(explicit)154     ACE_REMOVE(explicit) RefPtr(const RefPtr<O>& other) : RefPtr(other.rawPtr_) {}
155     template<class O>
ACE_REMOVE(explicit)156     ACE_REMOVE(explicit) RefPtr(RefPtr<O>&& other) : rawPtr_(other.rawPtr_)
157     {
158         other.rawPtr_ = nullptr;
159     }
160 
~RefPtr()161     ~RefPtr()
162     {
163         if (rawPtr_ != nullptr) {
164             // Decrease strong reference count.
165             rawPtr_->DecRefCount();
166             rawPtr_ = nullptr;
167         }
168     }
169 
Swap(RefPtr & other)170     void Swap(RefPtr& other)
171     {
172         std::swap(rawPtr_, other.rawPtr_);
173     }
Swap(RefPtr && other)174     void Swap(RefPtr&& other)
175     {
176         Swap(other);
177     }
Reset()178     void Reset()
179     {
180         Swap(RefPtr());
181     }
182 
183     typename LifeCycleCheckable::PtrHolder<T> operator->() const
184     {
185         return rawPtr_;
186     }
187     T& operator*() const
188     {
189         ACE_DCHECK(rawPtr_ != nullptr);
190         return *rawPtr_;
191     }
192     operator bool() const
193     {
194         return rawPtr_ != nullptr;
195     }
196 
GetRawPtr()197     T* GetRawPtr() const
198     {
199         return rawPtr_;
200     }
201 
202     // Use 'Swap' to implement overloaded operator '='.
203     // Construct a temporary 'RefPtr' by different parameters to increase strong reference count of the new instance,
204     // swap with 'this', and then decrease strong reference of the old instance while destroying the temporary 'RefPtr'.
205     RefPtr& operator=(const RefPtr& other)
206     {
207         if (this != &other) {
208             Swap(RefPtr(other));
209         }
210         return *this;
211     }
212     RefPtr& operator=(RefPtr&& other)
213     {
214         if (this != &other) {
215             Swap(RefPtr(std::move(other)));
216         }
217         return *this;
218     }
219 
220     template<class O>
221     RefPtr& operator=(O* rawPtr)
222     {
223         Swap(RefPtr(rawPtr));
224         return *this;
225     }
226     template<class O>
227     RefPtr& operator=(const RefPtr<O>& other)
228     {
229         Swap(RefPtr(other));
230         return *this;
231     }
232     template<class O>
233     RefPtr& operator=(RefPtr<O>&& other)
234     {
235         Swap(RefPtr(std::move(other)));
236         return *this;
237     }
238 
239     // Comparing pointer of reference counter to implement Overloaded operator '==' and '!='.
240     template<class O>
241     bool operator==(const O* rawPtr) const
242     {
243         if (rawPtr_ == nullptr) {
244             return rawPtr == nullptr;
245         }
246         return rawPtr != nullptr && rawPtr_->refCounter_ == rawPtr->refCounter_;
247     }
248     template<class O>
249     bool operator!=(const O* rawPtr) const
250     {
251         return !operator==(rawPtr);
252     }
253 
254     template<class O>
255     bool operator==(const RefPtr<O>& other) const
256     {
257         return *this == other.rawPtr_;
258     }
259     template<class O>
260     bool operator!=(const RefPtr<O>& other) const
261     {
262         return !operator==(other);
263     }
264 
265     template<class O>
266     bool operator==(const WeakPtr<O>& weak) const
267     {
268         return weak == *this;
269     }
270     template<class O>
271     bool operator!=(const WeakPtr<O>& weak) const
272     {
273         return !operator==(weak);
274     }
275 
276     bool operator==(std::nullptr_t) const
277     {
278         return rawPtr_ == nullptr;
279     }
280     bool operator!=(std::nullptr_t) const
281     {
282         return rawPtr_ != nullptr;
283     }
284 
285     // Overload '<' is useful for 'std::map', 'std::set' and so on.
286     template<class O>
287     bool operator<(const RefPtr<O>& other) const
288     {
289         if (rawPtr_ == nullptr) {
290             return other.rawPtr_ != nullptr;
291         }
292         return other.rawPtr_ != nullptr && rawPtr_->refCounter_ < other.rawPtr_->refCounter_;
293     }
294 
295 private:
296     // Construct instance by raw pointer.
297     // 'WeakPtr' may construct 'RefPtr' without increasing its strong reference count,
298     // because strong reference count is already increased in 'WeakPtr' while upgrading.
299     // In that case, 'forceIncRef' should be 'false'.
rawPtr_(rawPtr)300     explicit RefPtr(T* rawPtr, bool forceIncRef = true) : rawPtr_(rawPtr)
301     {
302         if (rawPtr_ != nullptr && forceIncRef) {
303             // Increase strong reference count for holding instance.
304             rawPtr_->IncRefCount();
305         }
306     }
307 
308     friend class Referenced;
309     template<class O>
310     friend class RefPtr;
311     template<class O>
312     friend class WeakPtr;
313 
314     T* rawPtr_ { nullptr };
315 };
316 
317 // Working with 'RefPtr' to resolve 'circular reference'.
318 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function.
319 template<class T>
320 class WeakPtr final {
321 public:
322     // Basic constructors.
323     WeakPtr() = default;
WeakPtr(std::nullptr_t)324     ACE_REMOVE(explicit) WeakPtr(std::nullptr_t) {}
325     // Basic copy and move constructors.
WeakPtr(const WeakPtr & other)326     ACE_REMOVE(explicit) WeakPtr(const WeakPtr& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {}
WeakPtr(WeakPtr && other)327     ACE_REMOVE(explicit) WeakPtr(WeakPtr&& other) : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_)
328     {
329         other.unsafeRawPtr_ = nullptr;
330         other.refCounter_ = nullptr;
331     }
332     // Construct instance by other 'WeakPtr' that inherited from type 'T'.
333     template<class O>
ACE_REMOVE(explicit)334     ACE_REMOVE(explicit) WeakPtr(const WeakPtr<O>& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {}
335     template<class O>
ACE_REMOVE(explicit)336     ACE_REMOVE(explicit) WeakPtr(WeakPtr<O>&& other)
337         : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_)
338     {
339         other.unsafeRawPtr_ = nullptr;
340         other.refCounter_ = nullptr;
341     }
342     // Construct instance by 'RefPtr' that inherited from type 'T' or 'T' itself.
343     template<class O>
ACE_REMOVE(explicit)344     ACE_REMOVE(explicit) WeakPtr(const RefPtr<O>& other) : WeakPtr(other.rawPtr_) {}
WeakPtr(const RefPtr<T> & other)345     ACE_REMOVE(explicit) WeakPtr(const RefPtr<T>& other) : WeakPtr(other.rawPtr_) {}
346 
~WeakPtr()347     ~WeakPtr()
348     {
349         // Decrease weak reference count while releasing reference counter.
350         if (refCounter_ != nullptr) {
351             refCounter_->DecWeakRef();
352             refCounter_ = nullptr;
353             unsafeRawPtr_ = nullptr;
354         }
355     }
356 
Swap(WeakPtr & other)357     void Swap(WeakPtr& other)
358     {
359         std::swap(unsafeRawPtr_, other.unsafeRawPtr_);
360         std::swap(refCounter_, other.refCounter_);
361     }
Swap(WeakPtr && other)362     void Swap(WeakPtr&& other)
363     {
364         Swap(other);
365     }
Reset()366     void Reset()
367     {
368         Swap(WeakPtr());
369     }
370 
Upgrade()371     RefPtr<T> Upgrade() const
372     {
373         // A 'WeakPtr' could upgrade to 'RefPtr' if this instance is still alive.
374         return refCounter_ != nullptr && refCounter_->TryIncStrongRef() ? RefPtr<T>(unsafeRawPtr_, false) : nullptr;
375     }
Invalid()376     bool Invalid() const
377     {
378         return refCounter_ == nullptr || refCounter_->StrongRefCount() == 0;
379     }
380 
381     // Use 'Swap' to implement overloaded operator '=', just like 'RefPtr'.
382     WeakPtr& operator=(const WeakPtr& other)
383     {
384         if (this != &other) {
385             Swap(WeakPtr(other));
386         }
387         return *this;
388     }
389     WeakPtr& operator=(WeakPtr&& other)
390     {
391         if (this != &other) {
392             Swap(WeakPtr(std::move(other)));
393         }
394         return *this;
395     }
396 
397     template<class O>
398     WeakPtr& operator=(O* rawPtr)
399     {
400         Swap(WeakPtr(rawPtr));
401         return *this;
402     }
403     template<class O>
404     WeakPtr& operator=(const WeakPtr<O>& other)
405     {
406         Swap(WeakPtr(other));
407         return *this;
408     }
409     template<class O>
410     WeakPtr& operator=(WeakPtr<O>&& other)
411     {
412         Swap(WeakPtr(std::move(other)));
413         return *this;
414     }
415     template<class O>
416     WeakPtr& operator=(const RefPtr<O>& other)
417     {
418         Swap(WeakPtr(other.rawPtr_));
419         return *this;
420     }
421 
422     // Comparing pointer of reference counter to implement Overloaded operator '==' and '!=', just like 'RefPtr'.
423     template<class O>
424     bool operator==(const O* rawPtr) const
425     {
426         if (refCounter_ == nullptr) {
427             return rawPtr == nullptr;
428         }
429         return rawPtr != nullptr && refCounter_ == rawPtr->refCounter_;
430     }
431     template<class O>
432     bool operator!=(const O* rawPtr) const
433     {
434         return !operator==(rawPtr);
435     }
436 
437     template<class O>
438     bool operator==(const WeakPtr<O>& other) const
439     {
440         return refCounter_ == other.refCounter_;
441     }
442     template<class O>
443     bool operator!=(const WeakPtr<O>& other) const
444     {
445         return !operator==(other);
446     }
447 
448     template<class O>
449     bool operator==(const RefPtr<O>& strong) const
450     {
451         return strong.rawPtr_ != nullptr ? strong.rawPtr_->refCounter_ == refCounter_ : refCounter_ == nullptr;
452     }
453     template<class O>
454     bool operator!=(const RefPtr<O>& strong) const
455     {
456         return !operator==(strong);
457     }
458 
459     // Overload '<' is useful for 'std::map', 'std::set' and so on, just like 'RefPtr'.
460     template<class O>
461     bool operator<(const WeakPtr<O>& other) const
462     {
463         return refCounter_ < other.refCounter_;
464     }
465 
466     // Hash function for WeakPtr to be used in unordered containers like std::unordered_map or std::unordered_set.
467     struct Hash {
operatorHash468         std::size_t operator()(const WeakPtr& k) const
469         {
470             using std::hash;
471             using std::size_t;
472 
473             return hash<void*>()(k.refCounter_);
474         }
475     };
476 
477 private:
478     // Construct instance by raw pointer.
WeakPtr(T * rawPtr)479     explicit WeakPtr(T* rawPtr) : WeakPtr(rawPtr, rawPtr != nullptr ? rawPtr->refCounter_ : nullptr) {}
480     template<class O>
WeakPtr(O * rawPtr,RefCounter * aceRef)481     WeakPtr(O* rawPtr, RefCounter* aceRef) : unsafeRawPtr_(rawPtr), refCounter_(aceRef)
482     {
483         if (refCounter_) {
484             refCounter_->IncWeakRef();
485         }
486     }
487 
488     friend class Referenced;
489     template<class O>
490     friend class WeakPtr;
491 
492     // Notice: Raw pointer of instance is kept, but NEVER use it except succeed to upgrade to 'RefPtr'.
493     T* unsafeRawPtr_ { nullptr };
494     RefCounter* refCounter_ { nullptr };
495 };
496 
497 } // namespace OHOS::Ace
498 
499 #endif // FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_BASE_REFERENCED_H
500