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