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