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