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