• 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 UTILS_BASE_REFBASE_H
17 #define UTILS_BASE_REFBASE_H
18 
19 #include <atomic>
20 #include <functional>
21 #ifdef DEBUG_REFBASE
22 #include <mutex>
23 #endif
24 
25 namespace OHOS {
26 
27 #define INITIAL_PRIMARY_VALUE (1 << 28)
28 
29 class RefBase;
30 
31 #ifdef DEBUG_REFBASE
32 class RefTracker;
33 #endif
34 
35 class RefCounter {
36 public:
37     using RefPtrCallback = std::function<void()>;
38     friend class RefBase;
39 
40     RefCounter();
41 
42     explicit RefCounter(RefCounter *counter);
43 
44     RefCounter &operator=(const RefCounter &counter);
45 
46     virtual ~RefCounter();
47 
48     void SetCallback(const RefPtrCallback& callback);
49 
50     void RemoveCallback();
51 
52     int GetRefCount();
53 
54     void IncRefCount();
55 
56     void DecRefCount();
57 
58     bool IsRefPtrValid();
59 
60     int IncStrongRefCount(const void *objectId);
61 
62     int DecStrongRefCount(const void *objectId);
63 
64     int GetStrongRefCount();
65 
66     int IncWeakRefCount(const void *objectId);
67 
68     int DecWeakRefCount(const void *objectId);
69 
70     int GetWeakRefCount();
71 
72     void SetAttemptAcquire();
73 
74     bool IsAttemptAcquireSet();
75 
76     void ClearAttemptAcquire();
77 
78     bool AttemptIncStrongRef(const void *objectId, int &outCount);
79 
80     // Only for IPC use.
81     bool AttemptIncStrong(const void *objectId);
82 
83     bool IsLifeTimeExtended();
84 
85     void ExtendObjectLifetime();
86 
87 private:
88     std::atomic<int> atomicStrong_;
89     std::atomic<int> atomicWeak_;
90     std::atomic<int> atomicRefCount_;
91     std::atomic<unsigned int> atomicFlags_;
92     std::atomic<int> atomicAttempt_;
93     RefPtrCallback callback_ = nullptr;
94     static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002;
95 #ifdef DEBUG_REFBASE
96     RefTracker* refTracker = nullptr;
97     std::mutex trackerMutex;  // To ensure refTracker be thread-safe
98     void GetNewTrace(const void* object);
99     void PrintTracker();
100 #endif
101 };
102 
103 #ifdef DEBUG_REFBASE
104 // RefTracker is a debug tool, used to record the trace of RefBase.
105 // RefTracker will save the information about the count of RefBase,
106 // including the pointer of sptr/wptr(The pointer of itself, not the pointer
107 // it manages), the amount of strong/weak/refcout and the PID&TID.
108 // The Tracker can live with RefCounter/RefBase(including its derivation).
109 // User should keep thread-safety of RefTracker.
110 class RefTracker {
111 public:
RefTracker()112     RefTracker() {};
113 
114     RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
115 
116     void GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
117 
118     // Only used for tracking the amount of Strong Reference.
119     void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid);
120 
121     // Only used for tracking the amount of Weak Reference.
122     void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid);
123 
124     void PrintTrace(const void* root);
125 
126     void PrintStrongTrace(const void* root);
127 
128     void PrintWeakTrace(const void* root);
129 
130     RefTracker* GetexTrace();
131 
132     RefTracker* PopTrace(const void* root);
133 
134 private:
135     const void* ptrID;
136     int strongRefCNT;
137     int weakRefCNT;
138     int refCNT;
139     int PID;
140     int TID;
141     RefTracker* exTrace;
142 };
143 #endif
144 
145 class WeakRefCounter {
146 public:
147     WeakRefCounter(RefCounter *base, void *cookie);
148 
149     virtual ~WeakRefCounter();
150 
151     void *GetRefPtr();
152 
153     void IncWeakRefCount(const void *objectId);
154 
155     void DecWeakRefCount(const void *objectId);
156 
157     bool AttemptIncStrongRef(const void *objectId);
158 
159 private:
160     std::atomic<int> atomicWeak_;
161     RefCounter *refCounter_ = nullptr;
162     void *cookie_ = nullptr;
163 };
164 
165 class RefBase {
166 public:
167     RefBase();
168 
169     RefBase(const RefBase &refbase);
170 
171     RefBase &operator=(const RefBase &refbase);
172 
173     RefBase(RefBase &&refbase) noexcept;
174 
175     RefBase &operator=(RefBase &&refbase) noexcept;
176 
177     virtual ~RefBase();
178 
179     virtual void RefPtrCallback();
180 
181     void ExtendObjectLifetime();
182 
183     void IncStrongRef(const void *objectId);
184 
185     void DecStrongRef(const void *objectId);
186 
187     int GetSptrRefCount();
188 
189     WeakRefCounter *CreateWeakRef(void *cookie);
190 
191     void IncWeakRef(const void *objectId);
192 
193     void DecWeakRef(const void *objectId);
194 
195     int GetWptrRefCount();
196 
197     bool AttemptAcquire(const void *objectId);
198 
199     bool AttemptIncStrongRef(const void *objectId);
200 
201     // Only for IPC use.
202     bool AttemptIncStrong(const void *objectId);
203 
204     bool IsAttemptAcquireSet();
205 
206     bool IsExtendLifeTimeSet();
207 
208     virtual void OnFirstStrongRef(const void *objectId);
209 
210     virtual void OnLastStrongRef(const void *objectId);
211 
212     virtual void OnLastWeakRef(const void *objectId);
213 
214     virtual bool OnAttemptPromoted(const void *objectId);
215 
216 private:
217     RefCounter *refs_ = nullptr;
218 };
219 
220 template <typename T>
221 class wptr;
222 
223 template <typename T>
224 
225 class sptr {
226     friend class wptr<T>;
227 
228 public:
229     sptr();
230 
231     ~sptr();
232 
233     sptr(T *other);
234 
235     sptr(const sptr<T> &other);
236 
237     sptr(sptr<T> &&other);
238 
239     sptr<T> &operator=(sptr<T> &&other);
240 
241     template <typename O>
242     sptr(const sptr<O> &other);
243 
244     inline sptr(WeakRefCounter *p, bool force);
245 
GetRefPtr()246     inline T *GetRefPtr() const
247     {
248         return refs_;
249     }
250 
251     inline void ForceSetRefPtr(T *other);
252 
253     void clear();
254 
255     inline operator T *() const
256     {
257         return refs_;
258     }
259 
260     inline T &operator*() const
261     {
262         return *refs_;
263     }
264 
265     inline T *operator->() const
266     {
267         return refs_;
268     }
269 
270     inline bool operator!() const
271     {
272         return refs_ == nullptr;
273     }
274 
275     sptr<T> &operator=(T *other);
276 
277     sptr<T> &operator=(const sptr<T> &other);
278 
279     sptr<T> &operator=(const wptr<T> &other);
280 
281     template <typename O>
282     sptr<T> &operator=(const sptr<O> &other);
283 
284     bool operator==(const T *other) const;
285 
286     inline bool operator!=(const T *other) const
287     {
288         return !operator==(other);
289     }
290 
291     bool operator==(const wptr<T> &other) const;
292 
293     inline bool operator!=(const wptr<T> &other) const
294     {
295         return !operator==(other);
296     }
297 
298     bool operator==(const sptr<T> &other) const;
299 
300     inline bool operator!=(const sptr<T> &other) const
301     {
302         return !operator==(other);
303     }
304 
305 private:
306     T *refs_ = nullptr;
307 };
308 
309 template <typename T>
ForceSetRefPtr(T * other)310 inline void sptr<T>::ForceSetRefPtr(T *other)
311 {
312     refs_ = other;
313 }
314 
315 template <typename T>
sptr()316 inline sptr<T>::sptr()
317 {
318     refs_ = nullptr;
319 }
320 
321 template <typename T>
sptr(T * other)322 inline sptr<T>::sptr(T *other)
323 {
324     refs_ = other;
325     if (refs_ != nullptr) {
326         refs_->IncStrongRef(this);
327     }
328 }
329 
330 template <typename T>
sptr(const sptr<T> & other)331 inline sptr<T>::sptr(const sptr<T> &other)
332 {
333     refs_ = other.GetRefPtr();
334     if (refs_ != nullptr) {
335         refs_->IncStrongRef(this);
336     }
337 }
338 
339 template <typename T>
sptr(sptr<T> && other)340 sptr<T>::sptr(sptr<T> &&other)
341 {
342     refs_ = other.GetRefPtr();
343     other.ForceSetRefPtr(nullptr);
344 }
345 
346 template <typename T>
347 sptr<T> &sptr<T>::operator=(sptr<T> &&other)
348 {
349     if (refs_ != nullptr) {
350         refs_->DecStrongRef(this);
351     }
352     refs_ = other.GetRefPtr();
353     other.ForceSetRefPtr(nullptr);
354     return *this;
355 }
356 
357 template <typename T>
358 template <typename O>
sptr(const sptr<O> & other)359 sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
360 {
361     if (refs_ != nullptr) {
362         refs_->IncStrongRef(this);
363     }
364 }
365 
366 template <typename T>
367 inline sptr<T> &sptr<T>::operator=(T *other)
368 {
369     if (other != nullptr) {
370         other->IncStrongRef(this);
371     }
372 
373     if (refs_ != nullptr) {
374         refs_->DecStrongRef(this);
375     }
376 
377     refs_ = other;
378     return *this;
379 }
380 
381 template <typename T>
382 inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
383 {
384     T *otherRef(other.GetRefPtr());
385     if (otherRef != nullptr) {
386         otherRef->IncStrongRef(this);
387     }
388 
389     if (refs_ != nullptr) {
390         refs_->DecStrongRef(this);
391     }
392 
393     refs_ = otherRef;
394     return *this;
395 }
396 
397 template <typename T>
398 inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
399 {
400     if (refs_ != nullptr) {
401         refs_->DecStrongRef(this);
402     }
403     if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
404         refs_ = other.GetRefPtr();
405     } else {
406         refs_ = nullptr;
407     }
408 
409     return *this;
410 }
411 
412 template <typename T>
413 template <typename O>
414 sptr<T> &sptr<T>::operator=(const sptr<O> &other)
415 {
416     T *otherRef(other.GetRefPtr());
417     if (otherRef != nullptr) {
418         otherRef->IncStrongRef(this);
419     }
420 
421     if (refs_ != nullptr) {
422         refs_->DecStrongRef(this);
423     }
424 
425     refs_ = otherRef;
426     return *this;
427 }
428 
429 template <typename T>
430 inline bool sptr<T>::operator==(const T *other) const
431 {
432     return other == refs_;
433 }
434 
435 template <typename T>
436 inline bool sptr<T>::operator==(const wptr<T> &other) const
437 {
438     return refs_ == other.GetRefPtr();
439 }
440 
441 template <typename T>
442 inline bool sptr<T>::operator==(const sptr<T> &other) const
443 {
444     return refs_ == other.GetRefPtr();
445 }
446 
447 template<typename T>
clear()448 void sptr<T>::clear()
449 {
450     if (refs_) {
451         refs_->DecStrongRef(this);
452         refs_ = 0;
453     }
454 }
455 
456 template <typename T>
~sptr()457 inline sptr<T>::~sptr()
458 {
459     if (refs_ != nullptr) {
460         refs_->DecStrongRef(this);
461     }
462 }
463 
464 template <typename T>
sptr(WeakRefCounter * p,bool)465 inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
466 {
467     if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
468         refs_ = reinterpret_cast<T *>(p->GetRefPtr());
469     } else {
470         refs_ = nullptr;
471     }
472 }
473 
474 template <typename T>
475 class wptr {
476     template <typename O>
477     friend class wptr;
478 
479 public:
480     wptr();
481 
482     wptr(T *other);
483 
484     wptr(const wptr<T> &other);
485 
486     wptr(const sptr<T> &other);
487 
488     template <typename O>
489     wptr(const wptr<O> &other);
490 
491     template <typename O>
492     wptr(const sptr<O> &other);
493 
494     wptr<T> &operator=(T *other);
495 
496     template <typename O>
497     wptr<T> &operator=(O *other);
498 
499     wptr<T> &operator=(const wptr<T> &other);
500 
501     wptr<T> &operator=(const sptr<T> &other);
502 
503     template <typename O>
504     wptr<T> &operator=(const wptr<O> &other);
505 
506     template <typename O>
507     wptr<T> &operator=(const sptr<O> &other);
508 
509     inline T *operator*() const
510     {
511         return *refs_;
512     }
513     inline T *operator->() const
514     {
515         return reinterpret_cast<T *>(refs_->GetRefPtr());
516     }
517 
518     bool operator==(const T *other) const;
519 
520     inline bool operator!=(const T *other) const
521     {
522         return !operator==(other);
523     };
524 
525     bool operator==(const wptr<T> &other) const;
526 
527     inline bool operator!=(const wptr<T> &other) const
528     {
529         return !operator==(other);
530     }
531 
532     bool operator==(const sptr<T> &other) const;
533 
534     inline bool operator!=(const sptr<T> &other) const
535     {
536         return !operator==(other);
537     }
538 
539     T *GetRefPtr() const;
540 
AttemptIncStrongRef(const void * objectId)541     inline bool AttemptIncStrongRef(const void *objectId) const
542     {
543         return refs_->AttemptIncStrongRef(objectId);
544     }
545 
546     const sptr<T> promote() const;
547 
548     ~wptr();
549 
550 private:
551     WeakRefCounter *refs_ = nullptr;
552 };
553 
554 template <typename T>
GetRefPtr()555 inline T *wptr<T>::GetRefPtr() const
556 {
557     return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
558 }
559 
560 template <typename T>
wptr()561 wptr<T>::wptr()
562 {
563     refs_ = nullptr;
564 }
565 
566 template <typename T>
wptr(T * other)567 wptr<T>::wptr(T *other)
568 {
569     if (other != nullptr) {
570         refs_ = other->CreateWeakRef(other);
571         if (refs_ != nullptr) {
572             refs_->IncWeakRefCount(this);
573         }
574     } else {
575         refs_ = nullptr;
576     }
577 }
578 
579 template <typename T>
wptr(const wptr<T> & other)580 wptr<T>::wptr(const wptr<T> &other)
581 {
582     refs_ = other.refs_;
583     if (refs_ != nullptr) {
584         refs_->IncWeakRefCount(this);
585     }
586 }
587 
588 template <typename T>
wptr(const sptr<T> & other)589 wptr<T>::wptr(const sptr<T> &other)
590 {
591     if (other.GetRefPtr() != nullptr) {
592         refs_ = other->CreateWeakRef(other.GetRefPtr());
593         if (refs_ != nullptr) {
594             refs_->IncWeakRefCount(this);
595         }
596     }
597 }
598 
599 template <typename T>
600 template <typename O>
wptr(const wptr<O> & other)601 wptr<T>::wptr(const wptr<O> &other)
602 {
603     refs_ = other.refs_;
604     if (refs_ != nullptr) {
605         refs_->IncWeakRefCount(this);
606     }
607 }
608 
609 template <typename T>
610 template <typename O>
wptr(const sptr<O> & other)611 wptr<T>::wptr(const sptr<O> &other)
612 {
613     if (other.GetRefPtr() != nullptr) {
614         refs_ = other->CreateWeakRef(other.GetRefPtr());
615         if (refs_ != nullptr) {
616             refs_->IncWeakRefCount(this);
617         }
618     }
619 }
620 
621 template <typename T>
622 wptr<T> &wptr<T>::operator=(T *other)
623 {
624     WeakRefCounter *newWeakRef = nullptr;
625     if (other != nullptr) {
626         newWeakRef = other->CreateWeakRef(other);
627         if (newWeakRef != nullptr) {
628             newWeakRef->IncWeakRefCount(this);
629         }
630     }
631 
632     if (refs_ != nullptr) {
633         refs_->DecWeakRefCount(this);
634     }
635 
636     refs_ = newWeakRef;
637     return *this;
638 }
639 
640 template <typename T>
641 template <typename O>
642 wptr<T> &wptr<T>::operator=(O *other)
643 {
644     T *object = reinterpret_cast<T *>(other);
645     WeakRefCounter *newWeakRef = nullptr;
646     if (object != nullptr) {
647         newWeakRef = object->CreateWeakRef(object);
648         if (newWeakRef != nullptr) {
649             newWeakRef->IncWeakRefCount(this);
650         }
651     }
652 
653     if (refs_ != nullptr) {
654         refs_->DecWeakRefCount(this);
655     }
656 
657     refs_ = newWeakRef;
658     return *this;
659 }
660 
661 template <typename T>
662 inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
663 {
664     if (other.refs_ != nullptr) {
665         other.refs_->IncWeakRefCount(this);
666     }
667 
668     if (refs_ != nullptr) {
669         refs_->DecWeakRefCount(this);
670     }
671 
672     refs_ = other.refs_;
673     return *this;
674 }
675 
676 template <typename T>
677 inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
678 {
679     WeakRefCounter *newWeakRef = nullptr;
680     if (other.GetRefPtr() != nullptr) {
681         newWeakRef = other->CreateWeakRef(other.GetRefPtr());
682         if (newWeakRef != nullptr) {
683             newWeakRef->IncWeakRefCount(this);
684         }
685     }
686 
687     if (refs_ != nullptr) {
688         refs_->DecWeakRefCount(this);
689     }
690 
691     refs_ = newWeakRef;
692     return *this;
693 }
694 
695 template <typename T>
696 template <typename O>
697 wptr<T> &wptr<T>::operator=(const wptr<O> &other)
698 {
699     if (other.refs_ != nullptr) {
700         other.refs_->IncWeakRefCount(this);
701     }
702 
703     if (refs_ != nullptr) {
704         refs_->DecWeakRefCount(this);
705     }
706 
707     refs_ = other.refs_;
708     return *this;
709 }
710 
711 template <typename T>
712 template <typename O>
713 wptr<T> &wptr<T>::operator=(const sptr<O> &other)
714 {
715     WeakRefCounter *newWeakRef = nullptr;
716     if (other.GetRefPtr() != nullptr) {
717         newWeakRef = other->CreateWeakRef(other->GetRefPtr());
718         if (newWeakRef != nullptr) {
719             newWeakRef->IncWeakRefCount(this);
720         }
721     }
722 
723     if (refs_ != nullptr) {
724         refs_->DecWeakRefCount(this);
725     }
726 
727     refs_ = newWeakRef;
728     return *this;
729 }
730 
731 template <typename T>
732 inline bool wptr<T>::operator==(const T *other) const
733 {
734     return GetRefPtr() == other;
735 }
736 
737 template <typename T>
738 inline bool wptr<T>::operator==(const wptr<T> &other) const
739 {
740     return GetRefPtr() == other.GetRefPtr();
741 }
742 
743 template <typename T>
744 inline bool wptr<T>::operator==(const sptr<T> &other) const
745 {
746     return GetRefPtr() == other.GetRefPtr();
747 }
748 
749 template <typename T>
promote()750 inline const sptr<T> wptr<T>::promote() const
751 {
752     return sptr<T>(refs_, true);
753 }
754 
755 template <typename T>
~wptr()756 inline wptr<T>::~wptr()
757 {
758     if (refs_ != nullptr) {
759         refs_->DecWeakRefCount(this);
760     }
761 }
762 
763 } // namespace OHOS
764 
765 #endif
766