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