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