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