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