1 /*
2 * Copyright (c) 2021-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 /**
17 * @file refbase.h
18 *
19 * @brief Provide smart pointer implemented in c_utils.
20 */
21
22 /**
23 * @defgroup SmartPointer
24 * @{
25 * @brief Smart Pointer are pointer-like classes.
26 *
27 * They simulates a pointer while providing added features,
28 * such as automatic memory management.\n
29 * Automatic memory management is mainly about deallocating
30 * the related memory correctly when an object beyonds its life cycle.
31 */
32
33 #ifndef UTILS_BASE_REFBASE_H
34 #define UTILS_BASE_REFBASE_H
35
36 #include <atomic>
37 #include <functional>
38 #ifdef DEBUG_REFBASE
39 #include <mutex>
40 #endif
41
42 #ifdef _WIN32
43 #define RS_EXPORT __attribute__((dllexport))
44 #else
45 #define RS_EXPORT __attribute__((visibility("default")))
46 #endif
47
48 namespace OHOS {
49 /**
50 * @ingroup SmartPointer
51 * @brief A value indicates no strong references exist ever.
52 */
53 #define INITIAL_PRIMARY_VALUE (1 << 28)
54
55 class RefBase;
56
57 #ifdef DEBUG_REFBASE
58 class RefTracker;
59 #endif
60
61 /**
62 * @ingroup SmartPointer
63 * @brief Reference counter. A class records two kinds of count of references to
64 * the corresponding RefBase object, and a count of references to the RefCounter
65 * itself.
66 *
67 * There are two different references for a single object.\n
68 * Strong Reference holds a reference directly point to the object.
69 * Objects which are strong referenced ought to be alive/existed
70 * as long as this strong reference exists, thus the reference
71 * is still valid.\n
72 * Weak Reference holds a reference indirectly point to the object.
73 * Objects which are weak referenced are not guaranteed to be alive/existed
74 * even if the weak reference exists.
75 * @note Descriptions above are valid only when smart pointers
76 * are properly used.
77 */
78 class RefCounter {
79 public:
80 /**
81 * @brief Callback function to destroy the corresponding RefBase object.
82 */
83 using RefPtrCallback = std::function<void()>;
84 friend class RefBase;
85
86 RefCounter();
87
88 explicit RefCounter(RefCounter *counter);
89
90 RefCounter &operator=(const RefCounter &counter);
91
92 virtual ~RefCounter();
93
94 /**
95 * @brief Set the callback function.
96 *
97 * @param callback A function to be set to delete
98 * the corresponding RefBase object.
99 */
100 void SetCallback(const RefPtrCallback& callback);
101
102 /**
103 * @brief Remove the current callback function. Set it to a `nullptr`.
104 */
105 void RemoveCallback();
106
107 /**
108 * @brief Get reference count to the RefCounter object.
109 *
110 * @return Value of the related count.
111 */
112 int GetRefCount();
113
114 /**
115 * @brief Increment the reference count to the RefCounter object by 1.
116 */
117 void IncRefCount();
118
119 /**
120 * @brief Decrement the reference count to the RefCounter object by 1.
121 *
122 * Once the count reaches 0 after being decremented,
123 * it will call `delete this` to deallocate this RefCounter object.
124 */
125 void DecRefCount();
126
127 /**
128 * @brief Check if pointer to the call back function is a `nullptr`.
129 *
130 * @return Return true if it is not a `nullptr`.
131 */
132 bool IsRefPtrValid();
133
134 /**
135 * @brief Increment the strong reference count to the
136 * corresponding RefBase object by 1.
137 *
138 * @return Original (before increment) value of the count.
139 */
140 int IncStrongRefCount(const void *objectId);
141
142 /**
143 * @brief Decrement the strong reference count to the
144 * corresponding RefBase object by 1.
145 *
146 * @return Original (before decrement) value of the count.
147 * @note If the strong reference has never existed,
148 * decrement will cause no effection.
149 */
150 int DecStrongRefCount(const void *objectId);
151
152 /**
153 * @brief Get the strong reference count to the
154 * corresponding RefBase object.
155 *
156 * @return Value of the related count.
157 */
158 int GetStrongRefCount();
159
160 /**
161 * @brief Increment the weak reference count to the
162 * corresponding RefBase object by 1.
163 *
164 * @return Original (before increment) value of the count.
165 */
166 int IncWeakRefCount(const void *objectId);
167
168 /**
169 * @brief Decrement the weak reference count to the
170 * corresponding RefBase object by 1.
171 *
172 * @return Original (before decrement) value of atomicWeak_.
173 * @note When the count reaches 0 after being decremented, the
174 * corresponding RefBase object with no strong reference ever,
175 * or the object with strong reference count of 0 but has not been
176 * deallocated due to its extended 'life time', will be deallocated.
177 */
178 int DecWeakRefCount(const void *objectId);
179
180 /**
181 * @brief Get the weak reference count to the
182 * corresponding RefBase object.
183 *
184 * @return Value of the related count.
185 */
186 int GetWeakRefCount();
187
188 /**
189 * @brief Increment the times of attempts to increment.
190 */
191 void SetAttemptAcquire();
192
193 /**
194 * @brief Check if the times of attempts greater than 0.
195 *
196 * @return Return true if the times is greater than 0.
197 */
198 bool IsAttemptAcquireSet();
199
200 /**
201 * @brief Clear the times of attempts to increment.
202 */
203 void ClearAttemptAcquire();
204
205 /**
206 * @brief Attempt to increment the strong reference count to the
207 * corresponding RefBase object by 1.
208 *
209 * @param outCount If the attempt success, the original value
210 * (before increment) of the count will be stored here.
211 * @return Return true if the attempt success.
212 */
213 bool AttemptIncStrongRef(const void *objectId, int &outCount);
214
215 // Only for IPC use.
216 /**
217 * @brief Attempt to increment the strong reference count to
218 * the corresponding RefBase object by 1(Simplified).
219 *
220 * @return Return true if the attempt success.
221 * @note Ony for IPC use.
222 */
223 bool AttemptIncStrong(const void *objectId);
224
225 /**
226 * @brief Check if the corresponding RefBase object
227 * own an extended life-time.
228 *
229 * @return Return true if its life-time has been extended.
230 */
231 bool IsLifeTimeExtended();
232
233 /**
234 * @brief Extend the life-time of corresponding RefBase object.
235 *
236 * It allows the corresponding object keep alive
237 * even if there exists no strong reference to it.
238 * @note Corresponding object will be deallocated
239 * when related weak reference count also reach 0.
240 */
241 void ExtendObjectLifetime();
242
243 #ifndef ROSEN_EMULATOR
244 using CanPromote = std::function<bool()>;
245
246 void SetCanPromote(const CanPromote& canPromote);
247
248 void RemoveCanPromote();
249
250 bool IsCanPromoteValid();
251 #endif
252 private:
253 std::atomic<int> atomicStrong_; // = (num of sptr) or Initial-value
254 std::atomic<int> atomicWeak_; // = (num of sptr)+(num of WeakRefCounter)
255 std::atomic<int> atomicRefCount_; // = (num of WeakRefCounter) + 1
256 std::atomic<unsigned int> atomicFlags_; // A life-time extended flag
257 std::atomic<int> atomicAttempt_; // Times of attempts
258 RefPtrCallback callback_ = nullptr; // A callback function to deallocate the corresponding RefBase object
259 static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR
260 #ifndef ROSEN_EMULATOR
261 CanPromote canPromote_ = nullptr;
262 #endif
263 #ifdef DEBUG_REFBASE
264 RefTracker* refTracker = nullptr;
265 std::mutex trackerMutex; // To ensure refTracker be thread-safe
266 void GetNewTrace(const void* objectId);
267 void PrintTracker();
268 #endif
269 };
270
271 #ifdef DEBUG_REFBASE
272 // RefTracker is a debug tool, used to record the trace of RefBase.
273 // RefTracker will save the information about the count of RefBase,
274 // including the pointer of sptr/wptr(The pointer of itself, not the pointer
275 // it manages), the amount of strong/weak/refcout and the PID&TID.
276 // The Tracker can live with RefCounter/RefBase(including its derivation).
277 // User should keep thread-safety of RefTracker.
278 class RefTracker {
279 public:
RefTracker()280 RefTracker() {};
281
282 RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
283
284 void GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
285
286 // Only used for tracking the amount of Strong Reference.
287 void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid);
288
289 // Only used for tracking the amount of Weak Reference.
290 void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid);
291
292 void PrintTrace(const void* root);
293
294 void PrintStrongTrace(const void* root);
295
296 void PrintWeakTrace(const void* root);
297
298 RefTracker* GetexTrace();
299
300 RefTracker* PopTrace(const void* root);
301
302 private:
303 const void* ptrID;
304 int strongRefCNT;
305 int weakRefCNT;
306 int refCNT;
307 int PID;
308 int TID;
309 RefTracker* exTrace;
310 };
311 #endif
312
313 /**
314 * @ingroup SmartPointer
315 * @brief An intermediate class to represent the weak reference
316 * to the correspond RefBase object.
317 *
318 * A WeakRefCounter object can be held by multiple wptr objects.\n
319 * It holds references to the corresponding RefBase and RefCounter object.
320 * Those two references will be set as `nullptr`s, when the weak referenced
321 * target and its RefCounter object has been deallocated. Thus WeakRefCounter
322 * object can still alive even if the target refereneced by this object
323 * is vanished.
324 */
325 class WeakRefCounter {
326 public:
327 /**
328 * @brief Construct a new Weak Ref Counter object.
329 *
330 * @param counter Pointer to corresponding RefCounter object.
331 * @param cookie Pointer to corresponding RefBase object.
332 */
333 WeakRefCounter(RefCounter *counter, void *cookie);
334
335 virtual ~WeakRefCounter();
336
337 /**
338 * @brief Get current pointer to the corresponding RefBase object.
339 *
340 * @return A void pointer to the RefBase object.
341 * If the corresponding object does not alive, a `nullptr` will return.
342 * @note Void pointer means you should cast it to the real type, since it
343 * can be kinds of subclasses of RefBase.
344 */
345 void *GetRefPtr();
346
347 /**
348 * @brief Increment the reference count to this WeakRefCounter object.
349 *
350 * @note Notice the difference between this count and the weak reference
351 * count in RefCounter. This value equals to the number of wptrs directly
352 * referencing this WeakRefCount object.
353 * @see RefCounter
354 */
355 void IncWeakRefCount(const void *objectId);
356
357 /**
358 * @brief Decrement the reference count to this WeakRefCounter object.
359 *
360 * @note This WeakRefCounter object will be deallocated when this count
361 * reaches 0.
362 */
363 void DecWeakRefCount(const void *objectId);
364
365 /**
366 * @brief Get the count recorded by this WeakRefCounter object.
367 *
368 * @return Value of the count.
369 * @note This value of count is different from that in RefCounter.
370 * @see RefCounter::GetWeakRefCount()
371 */
372 int GetWeakRefCount() const;
373
374 /**
375 * @brief Attempt to increment the strong reference count of
376 * the corresponding RefBase object(Used in promoting a wptr to a sptr).
377 *
378 * @return Return `true` after a success increment.
379 */
380 bool AttemptIncStrongRef(const void *objectId);
381
382 private:
383 std::atomic<int> atomicWeak_; // Count of references to this WeakRefCounter object
384 // The value equals to the total amount of wptrs which
385 // reference this WeakRefCounter object
386 RefCounter *refCounter_ = nullptr; // reference to the RefCounter object of corresponding RefBase Object
387 void *cookie_ = nullptr; // Pointer to the corresponding RefBase object
388 };
389
390 /**
391 * @ingroup SmartPointer
392 * @brief A base class which can be managed by a smart pointer.
393 *
394 * @note All classes which intend to be managed by smart pointers should be
395 * derived from RefBase.
396 */
397 class RS_EXPORT RefBase {
398 public:
399 RefBase();
400
401 /**
402 * @brief Copy constructor of RefBase.
403 *
404 * @note Note that this method will construct a new RefCounter object,
405 * and bind with it.
406 */
407 RefBase(const RefBase &);
408
409 /**
410 * @brief Copy assignment operator of RefBase.
411 *
412 * @note This method will unbind the current RefBase object and its
413 * original RefCounter object, then bind a newly constructed
414 * RefCounter object.
415 */
416 RefBase &operator=(const RefBase &);
417
418 /**
419 * @brief Move constructor of RefBase.
420 */
421 RefBase(RefBase &&other) noexcept;
422
423 /**
424 * @brief Move assignment operator of RefBase.
425 *
426 * @note This method will bind this RefBase object with the RefCounter
427 * object of the argument `other`, then `other` will unbind the RefCounter
428 * object.\n No counts operation will be poccessed.
429 */
430 RefBase &operator=(RefBase &&other) noexcept;
431
432 virtual ~RefBase();
433
434 /**
435 * @brief A callback method to deallocate this object.
436 *
437 * This method has default implement to simply deallocate this RefBase
438 * object simply by calling `delete(this)`.
439 */
440 virtual void RefPtrCallback();
441
442 /**
443 * @brief Extend life time of the RefBase object.
444 *
445 * @note The object whose life time has been extended will not be
446 * deallocated when the the weak reference count reach 0 instead of the
447 * strong one.
448 */
449 void ExtendObjectLifetime();
450
451 /**
452 * @brief Increment the strong reference count.
453 *
454 * `OnFirstStrongRef()`, which is an empty method by default, will be
455 * called when the first strong reference are established.、
456 *
457 * @note It will atomically increment the weak reference count meanwhile.
458 */
459 void IncStrongRef(const void *objectId);
460
461 /**
462 * @brief Decrement the strong reference count.
463 *
464 * This object will be deallocated when the count reaches 0, if it owns a
465 * normal life time.\n `OnLastStrongRef()`, which is an empty method by
466 * default, will be called when the last strong reference vanishes.
467 */
468 void DecStrongRef(const void *objectId);
469
470 /**
471 * @brief Get the strong reference count.
472 *
473 * @return Related count value. Return 0 when corresponding RefCounter
474 * object does not exist.
475 * @note Only valid when corresponding RefCounter object exists.
476 */
477 int GetSptrRefCount();
478
479 /**
480 * @brief Create weak reference to this RefBase object.
481 *
482 * Create a WeakRefCounter object which holds reference to this RefBase
483 * object and set the reference count.
484 *
485 * @param cookie Void pointer to this RefBase object.
486 * @return Pointer to the newly created WeakRefCounter object.
487 * @note Avoid using it independently. Use related methods of wptr.
488 */
489 WeakRefCounter *CreateWeakRef(void *cookie);
490
491 /**
492 * @brief Get the pointer to corresponding counter object.
493 *
494 * @return Pointer to the counter object.
495 */
496 RefCounter *GetRefCounter() const;
497
498 /**
499 * @brief Increment the weak reference count.
500 *
501 * @note Only valid when corresponding RefCounter object exists.
502 */
503 void IncWeakRef(const void *objectId);
504
505 /**
506 * @brief Decrement the weak reference count.
507 *
508 * @note Only valid when corresponding RefCounter object exists.
509 */
510 void DecWeakRef(const void *objectId);
511
512 /**
513 * @brief Get the weak reference count.
514 *
515 * @return Value of related count. Return 0 when corresponding
516 * RefCounter object doesn't exist.
517 */
518 int GetWptrRefCount();
519
520 /**
521 * @brief Attempt to increment the strong reference count.
522 *
523 * `OnFirstStrongRef()`, which is an empty method by default, will be
524 * called when the first strong reference are established.
525 *
526 * @return Return true if successfully increment the count.
527 * @note Note that count of times of attempts will increment by 1
528 * after a successful increment.
529 */
530 bool AttemptAcquire(const void *objectId);
531
532 /**
533 * @brief Attempt to increment the strong reference count.
534 *
535 * `OnFirstStrongRef()`, which is an empty method by default, will be
536 * called when the first strong reference are established.
537 * @return Return true if successfully increment the count.
538 * @note Used in various copy constructor of sptr in scenario of
539 * interaction between sptr and wptr. Avoid using it independently.
540 */
541 bool AttemptIncStrongRef(const void *objectId);
542
543 // Only for IPC use.
544 /**
545 * @brief Attempt to increment the strong reference count.
546 *
547 * @return Return true if successfully increment the count, otherwise
548 * return false.
549 * @note Note that times of successful attempts will increment by 1 after
550 * a successful increment of the related count.
551 * @note This method is a simplified version of `AttemptAcquire`, but only
552 * for IPC use.
553 */
554 bool AttemptIncStrong(const void *objectId);
555
556 /**
557 * @brief check if the times of successful attempts of greater than 0.
558 *
559 * @return Return true if times of successful attempts is greater than 0;
560 * Return false if it is not greater than 0, or the corresponding
561 * RefCounter object does not exist.
562 */
563 bool IsAttemptAcquireSet();
564
565 /**
566 * @brief Check if the life time of this RefBase object has been extended.
567 *
568 * @return Return false when have a normal life time, or the corresponding
569 * RefCounter object does not exist.
570 */
571 bool IsExtendLifeTimeSet();
572
573 /**
574 * @brief An event-drive method, which will be automatically called when
575 * first strong reference comes up.
576 *
577 * @note It is an empty function by default.
578 */
579 virtual void OnFirstStrongRef(const void *);
580
581 /**
582 * @brief An event-drive method, which will be automatically called when
583 * last strong reference eliminates.
584 *
585 * @note It is an empty function by default.
586 */
587 virtual void OnLastStrongRef(const void *);
588
589 /**
590 * @brief An event-drive method, which will be automatically called when
591 * last weak reference eliminates.
592 *
593 * @note It is an empty function by default.
594 */
595 virtual void OnLastWeakRef(const void *);
596
597 /**
598 * @brief An event-drive method, which will be autmatically called when
599 * use `wptr::Promote()`.
600 *
601 * @note Directly return true by default.
602 * @return Return true if success, otherwise return false.
603 */
604 virtual bool OnAttemptPromoted(const void *);
605
606 #ifndef ROSEN_EMULATOR
607 virtual bool CanPromote();
608 #endif
609
610 private:
611 RefCounter *refs_ = nullptr; // Pointer to the corresponding reference counter of this RefBase object
612 };
613
614 template <typename T>
615 class wptr;
616
617 /**
618 * @ingroup SmartPointer
619 * @brief Strong reference smart pointer to a RefBase(or its subclass) object.
620 *
621 * It directly reference the RefBase object.
622 *
623 * @tparam T Specific class type managed by sptr. This class must inherit
624 * from RefBase.
625 */
626 template <typename T>
627 class sptr {
628 friend class wptr<T>;
629
630 public:
631 sptr();
632
633 ~sptr();
634
635 /**
636 * @brief Constructor with specified object to be managed.
637 *
638 * @note Null sptr will be created if `other` is a `nullptr`.
639 * @param other Object to be managed by wptr.
640 */
641 sptr(T *other);
642
643 /**
644 * @brief Copy Constructor for sptr with different managed class type(T).
645 *
646 * @param other Input sptr object.
647 */
648 sptr(const sptr<T> &other);
649
650 /**
651 * @brief Move constructor.
652 *
653 * @note `other` will be set to a null sptr.
654 * @param other Input sptr object.
655 */
656 sptr(sptr<T> &&other);
657
658 /**
659 * @brief Move assignment operator.
660 *
661 * @param other Input sptr object.
662 * @note Original strong reference in target sptr object will be removed.
663 */
664 sptr<T> &operator=(sptr<T> &&other);
665
666 /**
667 * @brief Copy Constructor for sptr with different managed class type(O).
668 *
669 * @tparam O Another specific class type managed by `other`.
670 * @param other Input sptr object.
671 */
672 template <typename O>
673 sptr(const sptr<O> &other);
674
675 /**
676 * @brief Constructor only used in promote process of wptr.
677 *
678 * @param p WeakRefCounter object which hold the reference to the
679 * managed object.
680 * @param force Only used to identify from other constructor.
681 */
682 inline sptr(WeakRefCounter *p, bool force);
683
684 /**
685 * @brief Get the pointer to the managed object.
686 *
687 * @return Pointer of the specific managed class type.
688 */
GetRefPtr()689 inline T *GetRefPtr() const
690 {
691 return refs_;
692 }
693
694 /**
695 * @brief Set the pointer to the managed object.
696 *
697 * @param other Another pointer object to be managed by sptr.
698 * @note Avoid using independently, otherwise it will
699 * cause mismatch of reference count and thus memory problems.
700 */
701 inline void ForceSetRefPtr(T *other);
702
703 /**
704 * @brief Remove the reference to the managed object held by current sptr.
705 *
706 * @note It will make this sptr a "null sptr".
707 */
708 void clear();
709
710 /**
711 * @brief Type conversion operator.
712 *
713 * @return Raw pointer to the managed object.
714 * @note Sptr object itself will not be converted, only the member raw
715 * pointer returns.
716 */
717 inline operator T *() const
718 {
719 return refs_;
720 }
721
722 /**
723 * @brief Dereference operator.
724 *
725 * It will return the object managed by this sptr.
726 *
727 * @return Return reference of specific object managed by sptr.
728 */
729 inline T &operator*() const
730 {
731 return *refs_;
732 }
733
734 /**
735 * @brief Member selection operator.
736 *
737 * It will return the specified member of the object managed by this sptr.
738 */
739 inline T *operator->() const
740 {
741 return refs_;
742 }
743
744 /**
745 * @brief Logical-NOT operator. Check if sptr is a "null sptr".
746 *
747 * @return Return true if sptr is a "null sptr".
748 */
749 inline bool operator!() const
750 {
751 return refs_ == nullptr;
752 }
753
754 /**
755 * @brief Copy assignment operator with specified object to be managed.
756 *
757 * @note Original reference will be removed, then new reference to the
758 * input object will be established.
759 * @param other Another object to be managed by this sptr.
760 */
761 sptr<T> &operator=(T *other);
762
763 /**
764 * @brief Copy assignment operator for sptr with
765 * same managed class type(T).
766 *
767 * @note Original reference will be removed, this sptr will manage the
768 * same object with the input sptr object.
769 * @param other Another sptr object with same managed class type(T).
770 */
771 sptr<T> &operator=(const sptr<T> &other);
772
773 /**
774 * @brief Copy assignment operator for wptr with
775 * same managed class type(T).
776 *
777 * @note Original reference will be removed, this sptr will manage the
778 * same object with the input wptr object.
779 * @note This may fail, then this sptr will turn to be a "null sptr".
780 * @param other Another wptr object with same managed class type(T).
781 */
782 sptr<T> &operator=(const wptr<T> &other);
783
784 /**
785 * @brief Copy assignment operator for sptr with
786 * different managed class type(O).
787 *
788 * @note Original reference will be removed, this sptr will manage the
789 * same object with the input sptr object.
790 * @note This sptr will interpret the managed object as a type T.
791 * @param other Another sptr object with different managed class type(O).
792 */
793 template <typename O>
794 sptr<T> &operator=(const sptr<O> &other);
795
796 /**
797 * @brief Equal-to operator between sptr and a raw pointer.
798 *
799 * @param other Input raw pointer.
800 * @return Return true if sptr point to the same object with input
801 * raw pointer.
802 */
803 bool operator==(const T *other) const;
804
805 /**
806 * @brief Not-equal-to operator between sptr and a raw pointer.
807 *
808 * @param other Input raw pointer.
809 * @return Return true if sptr does not point to the same object with input
810 * raw pointer.
811 */
812 inline bool operator!=(const T *other) const
813 {
814 return !operator==(other);
815 }
816
817 /**
818 * @brief Equal-to operator between sptr and a wptr.
819 *
820 * @param other Input wptr.
821 * @return Return true if sptr and wptr are managing same object.
822 */
823 bool operator==(const wptr<T> &other) const;
824
825 /**
826 * @brief Not-equal-to operator between sptr and a wptr.
827 *
828 * @param other Input wptr.
829 * @return Return true if sptr and wptr are not managing same object.
830 */
831 inline bool operator!=(const wptr<T> &other) const
832 {
833 return !operator==(other);
834 }
835
836 /**
837 * @brief Equal-to operator between sptrs.
838 *
839 * @param other Input sptr.
840 * @return Return true if two sptrs are managing same object.
841 */
842 bool operator==(const sptr<T> &other) const;
843
844 /**
845 * @brief Not-equal-to operator between sptrs.
846 *
847 * @param other Input sptr.
848 * @return Return true if two sptrs are not managing same object.
849 */
850 inline bool operator!=(const sptr<T> &other) const
851 {
852 return !operator==(other);
853 }
854
855 private:
856 T *refs_ = nullptr; // Raw pointer to the managed specific object
857 };
858
859 template <typename T>
ForceSetRefPtr(T * other)860 inline void sptr<T>::ForceSetRefPtr(T *other)
861 {
862 refs_ = other;
863 }
864
865 template <typename T>
sptr()866 inline sptr<T>::sptr()
867 {
868 refs_ = nullptr;
869 }
870
871 template <typename T>
sptr(T * other)872 inline sptr<T>::sptr(T *other)
873 {
874 refs_ = other;
875 if (refs_ != nullptr) {
876 refs_->IncStrongRef(this);
877 }
878 }
879
880 template <typename T>
sptr(const sptr<T> & other)881 inline sptr<T>::sptr(const sptr<T> &other)
882 {
883 refs_ = other.GetRefPtr();
884 if (refs_ != nullptr) {
885 refs_->IncStrongRef(this);
886 }
887 }
888
889 template <typename T>
sptr(sptr<T> && other)890 sptr<T>::sptr(sptr<T> &&other)
891 {
892 refs_ = other.GetRefPtr();
893 other.ForceSetRefPtr(nullptr);
894 }
895
896 template <typename T>
897 sptr<T> &sptr<T>::operator=(sptr<T> &&other)
898 {
899 if (refs_ != nullptr) {
900 refs_->DecStrongRef(this);
901 }
902 refs_ = other.GetRefPtr();
903 other.ForceSetRefPtr(nullptr);
904 return *this;
905 }
906
907 template <typename T>
908 template <typename O>
sptr(const sptr<O> & other)909 sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
910 {
911 if (refs_ != nullptr) {
912 refs_->IncStrongRef(this);
913 }
914 }
915
916 template <typename T>
917 inline sptr<T> &sptr<T>::operator=(T *other)
918 {
919 if (other != nullptr) {
920 other->IncStrongRef(this);
921 }
922
923 if (refs_ != nullptr) {
924 refs_->DecStrongRef(this);
925 }
926
927 refs_ = other;
928 return *this;
929 }
930
931 template <typename T>
932 inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
933 {
934 T *otherRef(other.GetRefPtr());
935 if (otherRef != nullptr) {
936 otherRef->IncStrongRef(this);
937 }
938
939 if (refs_ != nullptr) {
940 refs_->DecStrongRef(this);
941 }
942
943 refs_ = otherRef;
944 return *this;
945 }
946
947 template <typename T>
948 inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
949 {
950 if (refs_ != nullptr) {
951 refs_->DecStrongRef(this);
952 }
953 if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
954 refs_ = other.GetRefPtr();
955 } else {
956 refs_ = nullptr;
957 }
958
959 return *this;
960 }
961
962 template <typename T>
963 template <typename O>
964 sptr<T> &sptr<T>::operator=(const sptr<O> &other)
965 {
966 T *otherRef(other.GetRefPtr());
967 if (otherRef != nullptr) {
968 otherRef->IncStrongRef(this);
969 }
970
971 if (refs_ != nullptr) {
972 refs_->DecStrongRef(this);
973 }
974
975 refs_ = otherRef;
976 return *this;
977 }
978
979 template <typename T>
980 inline bool sptr<T>::operator==(const T *other) const
981 {
982 return other == refs_;
983 }
984
985 template <typename T>
986 inline bool sptr<T>::operator==(const wptr<T> &other) const
987 {
988 return refs_ == other.GetRefPtr();
989 }
990
991 template <typename T>
992 inline bool sptr<T>::operator==(const sptr<T> &other) const
993 {
994 return refs_ == other.GetRefPtr();
995 }
996
997 template<typename T>
clear()998 void sptr<T>::clear()
999 {
1000 if (refs_) {
1001 refs_->DecStrongRef(this);
1002 refs_ = 0;
1003 }
1004 }
1005
1006 template <typename T>
~sptr()1007 inline sptr<T>::~sptr()
1008 {
1009 if (refs_ != nullptr) {
1010 refs_->DecStrongRef(this);
1011 }
1012 }
1013
1014 template <typename T>
sptr(WeakRefCounter * p,bool)1015 inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
1016 {
1017 if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
1018 refs_ = reinterpret_cast<T *>(p->GetRefPtr());
1019 } else {
1020 refs_ = nullptr;
1021 }
1022 }
1023
1024 /**
1025 * @ingroup SmartPointer
1026 * @brief Weak reference smart pointer to a RefBase(or its subclass) object.
1027 *
1028 * Indirectly reference the RefBase object;
1029 * Directly reference the WeakRefCounter object.
1030 *
1031 * @tparam T Specific class type managed by wptr.
1032 * This class must inherit from RefBase.
1033 */
1034 template <typename T>
1035 class wptr {
1036 template <typename O>
1037 friend class wptr;
1038
1039 public:
1040 wptr();
1041
1042 /**
1043 * @brief Constructor with specified object to be managed.
1044 *
1045 * This method will create WeakRefCounter object for `other` and set its
1046 * weak reference count to 1.
1047 *
1048 * @note WeakRefCounter object will not be created if `other` is a
1049 * `nullptr`.
1050 * @param other Object to be managed by wptr.
1051 */
1052 wptr(T *other);
1053
1054 /**
1055 * @brief Copy constructor for wptr with same managed class type(T).
1056 *
1057 * This method will share the WeakRefCounter object of `other` with this
1058 * wptr. Weak reference count in this WeakRefCounter object will be set
1059 * properly.
1060 *
1061 * @param other Another wptr with same managed class type(T).
1062 */
1063 wptr(const wptr<T> &other);
1064
1065 /**
1066 * @brief Copy constructor for sptr with same managed class type(T).
1067 *
1068 * This method will create WeakRefCounter object for the managed object of
1069 * `other`, and set its weak reference count properly.
1070 *
1071 * @param other Another sptr with same managed class type(T).
1072 * @tparam T Specific class type managed by `other`.
1073 */
1074 wptr(const sptr<T> &other);
1075
1076 /**
1077 * @brief Copy constructor for wptr with different managed class type(O).
1078 *
1079 * Same with wptr<T>::wptr(const wptr<T> &other).
1080 *
1081 * @tparam O Class type managed by `other`.
1082 * @param other Another wptr with different managed class type(O).
1083 * @tparam T Specific class type managed by `other`.
1084 */
1085 template <typename O>
1086 wptr(const wptr<O> &other);
1087
1088 /**
1089 * @brief Copy constructor for sptr with different managed class type(O).
1090 *
1091 * Same with wptr<T>::wptr(const sptr<T> &other).
1092 *
1093 * @param other Another sptr with same managed class type(O).
1094 * @tparam T Specific class type managed by `other`.
1095 */
1096 template <typename O>
1097 wptr(const sptr<O> &other);
1098
1099 /**
1100 * @brief Copy assignment operator with specified object to be managed.
1101 *
1102 * @note Current wptr will unbind the original WeakRefCounter object and
1103 * create a new WeakRefCounter object, then set its weak reference count
1104 * properly.
1105 * @param other Another object to be managed by this wptr.
1106 */
1107 wptr<T> &operator=(T *other);
1108
1109 /**
1110 * @brief Copy assignment operator with specified object to be managed.
1111 *
1112 * @note Same with wptr<T> &operator=(T *other), but a pointer type casting
1113 * which will not affect the type of `*other` is proccessed.
1114 * @tparam O Specific class type managed by `other`.
1115 * @param other Another object to be managed by this wptr.
1116 *
1117 */
1118 template <typename O>
1119 wptr<T> &operator=(O *other);
1120
1121 /**
1122 * @brief Copy assignment operator for wptr with same managed class type(T).
1123 *
1124 * @note Current wptr will unbind the original WeakRefCounter object and
1125 * share the WeakRefCounter object with `other`, then set its weak
1126 * reference count properly.
1127 * @param other Another wptr. Object managed by it will also be managed by
1128 * this wptr.
1129 */
1130 wptr<T> &operator=(const wptr<T> &other);
1131
1132 /**
1133 * @brief Copy assignment operator for sptr with
1134 * same managed class type(T).
1135 *
1136 * @note Current wptr will unbind the original WeakRefCounter object and
1137 * create a new WeakRefCounter object, then set its weak reference count
1138 * properly.
1139 * @param other A sptr object. Object managed by it will also be managed by
1140 * this wptr.
1141 */
1142 wptr<T> &operator=(const sptr<T> &other);
1143
1144 /**
1145 * @brief Copy assignment operator for wptr with
1146 * different managed class type(O).
1147 *
1148 * @note Same with wptr<T> &operator=(const wptr<T> &). Note that no cast
1149 * here is proccessed.
1150 * @param other An wptr object. Object managed by it will also be managed by
1151 * this wptr.
1152 * @tparam O Specific class type managed by `other`.
1153 */
1154 template <typename O>
1155 wptr<T> &operator=(const wptr<O> &other);
1156
1157 /**
1158 * @brief Copy assignment operator for sptr with
1159 * different managed class type(O).
1160 *
1161 * @note Same with wptr<T> &wptr<T>::operator=(const sptr<T> &). Note that
1162 * no cast here is proccessed.
1163 * @param other An sptr object. Object managed by it will also be managed by
1164 * this wptr.
1165 * @tparam O Specific class type managed by `other`.
1166 */
1167 template <typename O>
1168 wptr<T> &operator=(const sptr<O> &other);
1169
1170 /**
1171 * @brief Dereference operator. It will return the object managed by this
1172 * wptr.
1173 *
1174 * @return Return specific object managed by wptr.
1175 */
1176 inline T &operator*() const
1177 {
1178 return *GetRefPtr();
1179 }
1180
1181 /**
1182 * @brief Member selection operator.
1183 *
1184 * It will return the specified member of the object managed by this wptr.
1185 */
1186 inline T *operator->() const
1187 {
1188 return reinterpret_cast<T *>(refs_->GetRefPtr());
1189 }
1190
1191 /**
1192 * @brief Equal-to operator between wptr and a raw pointer.
1193 *
1194 * @param other Input raw pointer.
1195 * @return Return true if two pointers have same value.
1196 */
1197 bool operator==(const T *other) const;
1198
1199 /**
1200 * @brief Not-equal-to operator between wptr and a raw pointer.
1201 *
1202 * @param other Input raw pointer.
1203 * @return Return true if two pointers have different value.
1204 */
1205 inline bool operator!=(const T *other) const
1206 {
1207 return !operator==(other);
1208 };
1209
1210 /**
1211 * @brief Equal-to operator between two wptrs.
1212 *
1213 * @param other Input reference of a wptr object.
1214 * @return Return if two pointers have same value.
1215 */
1216 bool operator==(const wptr<T> &other) const;
1217
1218 /**
1219 * @brief Not-equal-to operator between two wptrs.
1220 *
1221 * @param other Input reference of a wptr object.
1222 * @return Return if two pointers have different value.
1223 */
1224 inline bool operator!=(const wptr<T> &other) const
1225 {
1226 return !operator==(other);
1227 }
1228
1229 /**
1230 * @brief Equal-to operator between wptr and a input sptr object.
1231 *
1232 * @param other Input reference of an sptr object.
1233 * @return Comparison result.
1234 */
1235 bool operator==(const sptr<T> &other) const;
1236
1237 /**
1238 * @brief Not-Equal-to operator between wptr and a input sptr object.
1239 *
1240 * @param other Input reference of an sptr object.
1241 * @return Comparison result.
1242 */
1243 inline bool operator!=(const sptr<T> &other) const
1244 {
1245 return !operator==(other);
1246 }
1247
1248 /**
1249 * @brief Get the pointer to the RefBase object.
1250 *
1251 * @return Raw pointer to the RefBase object.
1252 * @note Return `nullptr` if the managed object has been deallocated.
1253 */
1254 T *GetRefPtr() const;
1255
1256 /**
1257 * @brief Get the count value of corresponding WeakRefCounter object.
1258 *
1259 * The value indicates how many wptrs share the same WeakRefCounter object.
1260 *
1261 * @return Value of the count.
1262 * @note Only for test.
1263 */
GetWeakRefCount()1264 inline int GetWeakRefCount() const
1265 {
1266 return refs_->GetWeakRefCount();
1267 }
1268
1269 /**
1270 * @brief Attempt to increment the strong reference count of
1271 * the managed object.
1272 *
1273 * @return Return true after a success increment.
1274 * @note Avoid using it independently. Use `promote()`.
1275 */
AttemptIncStrongRef(const void * objectId)1276 inline bool AttemptIncStrongRef(const void *objectId) const
1277 {
1278 return refs_->AttemptIncStrongRef(objectId);
1279 }
1280
1281 /**
1282 * @brief Promote a wptr to an sptr.
1283 *
1284 * It will create an sptr object based on
1285 * object managed by this wptr.
1286 *
1287 * @note Original weak reference will be retained. Promote may fail,
1288 * and then return a "null sptr".
1289 */
1290 const sptr<T> promote() const;
1291
1292 ~wptr();
1293
1294 private:
1295 WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding weak reference counter object
1296 };
1297
1298 template <typename T>
GetRefPtr()1299 inline T *wptr<T>::GetRefPtr() const
1300 {
1301 return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
1302 }
1303
1304 template <typename T>
wptr()1305 wptr<T>::wptr()
1306 {
1307 refs_ = nullptr;
1308 }
1309
1310 template <typename T>
wptr(T * other)1311 wptr<T>::wptr(T *other)
1312 {
1313 if (other != nullptr) {
1314 refs_ = other->CreateWeakRef(other);
1315 if (refs_ != nullptr) {
1316 refs_->IncWeakRefCount(this);
1317 }
1318 } else {
1319 refs_ = nullptr;
1320 }
1321 }
1322
1323 template <typename T>
wptr(const wptr<T> & other)1324 wptr<T>::wptr(const wptr<T> &other)
1325 {
1326 refs_ = other.refs_;
1327 if (refs_ != nullptr) {
1328 refs_->IncWeakRefCount(this);
1329 }
1330 }
1331
1332 template <typename T>
wptr(const sptr<T> & other)1333 wptr<T>::wptr(const sptr<T> &other)
1334 {
1335 if (other.GetRefPtr() != nullptr) {
1336 refs_ = other->CreateWeakRef(other.GetRefPtr());
1337 if (refs_ != nullptr) {
1338 refs_->IncWeakRefCount(this);
1339 }
1340 }
1341 }
1342
1343 template <typename T>
1344 template <typename O>
wptr(const wptr<O> & other)1345 wptr<T>::wptr(const wptr<O> &other)
1346 {
1347 refs_ = other.refs_;
1348 if (refs_ != nullptr) {
1349 refs_->IncWeakRefCount(this);
1350 }
1351 }
1352
1353 template <typename T>
1354 template <typename O>
wptr(const sptr<O> & other)1355 wptr<T>::wptr(const sptr<O> &other)
1356 {
1357 if (other.GetRefPtr() != nullptr) {
1358 refs_ = other->CreateWeakRef(other.GetRefPtr());
1359 if (refs_ != nullptr) {
1360 refs_->IncWeakRefCount(this);
1361 }
1362 }
1363 }
1364
1365 template <typename T>
1366 wptr<T> &wptr<T>::operator=(T *other)
1367 {
1368 WeakRefCounter *newWeakRef = nullptr;
1369 if (other != nullptr) {
1370 newWeakRef = other->CreateWeakRef(other);
1371 if (newWeakRef != nullptr) {
1372 newWeakRef->IncWeakRefCount(this);
1373 }
1374 }
1375
1376 if (refs_ != nullptr) {
1377 refs_->DecWeakRefCount(this);
1378 }
1379
1380 refs_ = newWeakRef;
1381 return *this;
1382 }
1383
1384 template <typename T>
1385 template <typename O>
1386 wptr<T> &wptr<T>::operator=(O *other)
1387 {
1388 T *object = reinterpret_cast<T *>(other);
1389 WeakRefCounter *newWeakRef = nullptr;
1390 if (object != nullptr) {
1391 newWeakRef = object->CreateWeakRef(object);
1392 if (newWeakRef != nullptr) {
1393 newWeakRef->IncWeakRefCount(this);
1394 }
1395 }
1396
1397 if (refs_ != nullptr) {
1398 refs_->DecWeakRefCount(this);
1399 }
1400
1401 refs_ = newWeakRef;
1402 return *this;
1403 }
1404
1405 template <typename T>
1406 inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
1407 {
1408 if (other.refs_ != nullptr) {
1409 other.refs_->IncWeakRefCount(this);
1410 }
1411
1412 if (refs_ != nullptr) {
1413 refs_->DecWeakRefCount(this);
1414 }
1415
1416 refs_ = other.refs_;
1417 return *this;
1418 }
1419
1420 template <typename T>
1421 inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
1422 {
1423 WeakRefCounter *newWeakRef = nullptr;
1424 if (other.GetRefPtr() != nullptr) {
1425 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1426 if (newWeakRef != nullptr) {
1427 newWeakRef->IncWeakRefCount(this);
1428 }
1429 }
1430
1431 if (refs_ != nullptr) {
1432 refs_->DecWeakRefCount(this);
1433 }
1434
1435 refs_ = newWeakRef;
1436 return *this;
1437 }
1438
1439 template <typename T>
1440 template <typename O>
1441 wptr<T> &wptr<T>::operator=(const wptr<O> &other)
1442 {
1443 if (other.refs_ != nullptr) {
1444 other.refs_->IncWeakRefCount(this);
1445 }
1446
1447 if (refs_ != nullptr) {
1448 refs_->DecWeakRefCount(this);
1449 }
1450
1451 refs_ = other.refs_;
1452 return *this;
1453 }
1454
1455 template <typename T>
1456 template <typename O>
1457 wptr<T> &wptr<T>::operator=(const sptr<O> &other)
1458 {
1459 WeakRefCounter *newWeakRef = nullptr;
1460 if (other.GetRefPtr() != nullptr) {
1461 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1462 if (newWeakRef != nullptr) {
1463 newWeakRef->IncWeakRefCount(this);
1464 }
1465 }
1466
1467 if (refs_ != nullptr) {
1468 refs_->DecWeakRefCount(this);
1469 }
1470
1471 refs_ = newWeakRef;
1472 return *this;
1473 }
1474
1475 template <typename T>
1476 inline bool wptr<T>::operator==(const T *other) const
1477 {
1478 return GetRefPtr() == other;
1479 }
1480
1481 template <typename T>
1482 inline bool wptr<T>::operator==(const wptr<T> &other) const
1483 {
1484 return GetRefPtr() == other.GetRefPtr();
1485 }
1486
1487 template <typename T>
1488 inline bool wptr<T>::operator==(const sptr<T> &other) const
1489 {
1490 return GetRefPtr() == other.GetRefPtr();
1491 }
1492
1493 template <typename T>
promote()1494 inline const sptr<T> wptr<T>::promote() const
1495 {
1496 return sptr<T>(refs_, true);
1497 }
1498
1499 template <typename T>
~wptr()1500 inline wptr<T>::~wptr()
1501 {
1502 if (refs_ != nullptr) {
1503 refs_->DecWeakRefCount(this);
1504 }
1505 }
1506
1507 } // namespace OHOS
1508
1509 #endif
1510
1511 /**@}*/
1512