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