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