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 #include "refbase.h"
17 #include "utils_log.h"
18 #ifdef DEBUG_REFBASE
19 #include <unistd.h>
20 #endif
21
22 namespace OHOS {
23
RefBaseDebugPrint(int curCount,const void * caller,const void * objectId,const char * operation,const char * countType)24 void RefCounter::RefBaseDebugPrint([[maybe_unused]] int curCount,
25 [[maybe_unused]] const void* caller,
26 [[maybe_unused]] const void* objectId,
27 [[maybe_unused]] const char* operation,
28 [[maybe_unused]] const char* countType)
29 {
30 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
31 if (this->enableTrack) {
32 UTILS_LOGT(this->domainId_, "curCount: %{public}d, operation: %{public}s, countType: %{public}s",
33 curCount, operation, countType);
34 }
35 #endif
36 }
37
WeakRefCounter(RefCounter * counter,void * cookie)38 WeakRefCounter::WeakRefCounter(RefCounter *counter, void *cookie)
39 : atomicWeak_(0), refCounter_(counter), cookie_(cookie)
40 {
41 if (refCounter_ != nullptr) {
42 refCounter_->IncRefCount();
43 }
44 }
45
~WeakRefCounter()46 WeakRefCounter::~WeakRefCounter()
47 {
48 if (refCounter_ != nullptr) {
49 refCounter_->DecRefCount();
50 }
51 }
52
GetWeakRefCount() const53 int WeakRefCounter::GetWeakRefCount() const
54 {
55 return atomicWeak_.load(std::memory_order_relaxed);
56 }
57
GetRefPtr()58 void* WeakRefCounter::GetRefPtr()
59 {
60 if ((cookie_ != nullptr) && (!refCounter_->IsRefPtrValid())) {
61 cookie_ = nullptr;
62 }
63 return cookie_;
64 }
65
IncWeakRefCount(const void * objectId)66 void WeakRefCounter::IncWeakRefCount(const void *objectId)
67 {
68 if (atomicWeak_.fetch_add(1, std::memory_order_relaxed) == 0) {
69 refCounter_->IncWeakRefCount(objectId);
70 }
71 }
72
DecWeakRefCount(const void * objectId)73 void WeakRefCounter::DecWeakRefCount(const void *objectId)
74 {
75 if (atomicWeak_.fetch_sub(1, std::memory_order_release) == 1) {
76 refCounter_->DecWeakRefCount(objectId);
77 delete this;
78 }
79 }
80
AttemptIncStrongRef(const void * objectId)81 bool WeakRefCounter::AttemptIncStrongRef(const void *objectId)
82 {
83 int unuse = 0;
84 return refCounter_->AttemptIncStrongRef(objectId, unuse);
85 }
86
87 #if ((defined DEBUG_REFBASE) && (!defined PRINT_TRACK_AT_ONCE))
88 // RefTracker is a debug tool, used to record the trace of RefBase.
89 // RefTracker will save the information about the count of RefBase,
90 // including the pointer of sptr/wptr(The pointer of itself, not the pointer
91 // it manages), the amount of strong/weak/refcout and the PID&TID.
92 // The Tracker can live with RefCounter.
93 // User should keep thread-safety of RefTracker.
94 class RefTracker {
95 public:
96 RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
97
98 void PrintTrace(const void* refCounterPtr);
99
100 RefTracker* PopTrace(const void* refCounterPtr);
101
102 private:
103 const void* ptrID;
104 int strongRefCnt;
105 int weakRefCnt;
106 int refCnt;
107 int PID;
108 int TID;
109 RefTracker* exTrace;
110 };
111
RefTracker(RefTracker * exTracker,const void * id,int strong,int weak,int ref,int pid,int tid)112 RefTracker::RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid)
113 : ptrID (id), strongRefCnt (strong), weakRefCnt (weak), refCnt (ref), PID (pid), TID (tid), exTrace (exTracker)
114 {
115 }
116
PrintTrace(const void * refCounterPtr)117 void RefTracker::PrintTrace(const void* refCounterPtr)
118 {
119 UTILS_LOGI("strong: %{public}d weak: %{public}d, refcnt: %{public}d PID: %{public}d TID: %{public}d",
120 strongRefCnt, weakRefCnt, refCnt, PID, TID);
121 }
122
PopTrace(const void * refCounterPtr)123 RefTracker* RefTracker::PopTrace(const void* refCounterPtr)
124 {
125 RefTracker* ref = exTrace;
126 PrintTrace(refCounterPtr);
127 delete this;
128 return ref;
129 }
130 #endif
131
132 #ifdef DEBUG_REFBASE
133 #ifdef PRINT_TRACK_AT_ONCE
EnableTrackerWithDomainId(unsigned int domainId)134 void RefCounter::EnableTrackerWithDomainId(unsigned int domainId)
135 {
136 std::lock_guard<std::mutex> lock(trackerMutex);
137 this->domainId_ = domainId;
138 enableTrack = true;
139 }
140 #else
GetNewTrace(const void * objectId)141 void RefCounter::GetNewTrace(const void* objectId)
142 {
143 std::lock_guard<std::mutex> lock(trackerMutex);
144 RefTracker* newTracker = new RefTracker(refTracker, objectId, atomicStrong_,
145 atomicWeak_, atomicRefCount_, getpid(), gettid());
146 refTracker = newTracker;
147 }
148
PrintTracker()149 void RefCounter::PrintTracker()
150 {
151 std::lock_guard<std::mutex> lock(trackerMutex);
152 if (refTracker) {
153 UTILS_LOGI("Start backtrace");
154 while (refTracker) {
155 refTracker = refTracker->PopTrace(this);
156 }
157 UTILS_LOGI("End backtrace");
158 }
159 }
160 #endif
161
162 #ifndef TRACK_ALL
EnableTracker()163 void RefCounter::EnableTracker()
164 {
165 std::lock_guard<std::mutex> lock(trackerMutex);
166 #ifndef PRINT_TRACK_AT_ONCE
167 enableTrack = true;
168 #endif
169 }
170 #endif
171
172 #endif
173
DebugRefBase(const void * objectId)174 void RefCounter::DebugRefBase([[maybe_unused]]const void* objectId)
175 {
176 #ifdef DEBUG_REFBASE
177 if (enableTrack) {
178 #ifndef PRINT_TRACK_AT_ONCE
179 GetNewTrace(objectId);
180 #endif
181 }
182 #endif
183 }
184
RefCounter()185 RefCounter::RefCounter()
186 : atomicStrong_(INITIAL_PRIMARY_VALUE), atomicWeak_(0), atomicRefCount_(0), atomicFlags_(0), atomicAttempt_(0)
187 {
188 }
189
GetRefCount()190 int RefCounter::GetRefCount()
191 {
192 return atomicRefCount_.load(std::memory_order_relaxed);
193 }
194
IncRefCount()195 void RefCounter::IncRefCount()
196 {
197 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
198 int curCount = atomicRefCount_.fetch_add(1, std::memory_order_relaxed);
199 RefBaseDebugPrint(curCount, __builtin_return_address(0), nullptr, "++", "atomicRefCount_");
200 #else
201 atomicRefCount_.fetch_add(1, std::memory_order_relaxed);
202 #endif
203 }
204
DecRefCount()205 void RefCounter::DecRefCount()
206 {
207 if (atomicRefCount_.load(std::memory_order_relaxed) > 0) {
208 int curCount = atomicRefCount_.fetch_sub(1, std::memory_order_release);
209 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
210 RefBaseDebugPrint(curCount, __builtin_return_address(0), nullptr, "++", "atomicRefCount_");
211 #endif
212 if (curCount == 1) {
213 delete (this);
214 }
215 }
216 }
217
SetCallback(const RefPtrCallback & callback)218 void RefCounter::SetCallback(const RefPtrCallback& callback)
219 {
220 callback_ = callback;
221 }
222
RemoveCallback()223 void RefCounter::RemoveCallback()
224 {
225 callback_ = nullptr;
226 }
227
IsRefPtrValid()228 bool RefCounter::IsRefPtrValid()
229 {
230 return callback_ != nullptr;
231 }
232
233 #ifdef OHOS_PLATFORM
SetCanPromote(const CanPromote & canPromote)234 void RefCounter::SetCanPromote(const CanPromote &canPromote)
235 {
236 canPromote_ = canPromote;
237 }
238
RemoveCanPromote()239 void RefCounter::RemoveCanPromote()
240 {
241 canPromote_ = nullptr;
242 }
243
IsCanPromoteValid()244 bool RefCounter::IsCanPromoteValid()
245 {
246 return canPromote_ != nullptr;
247 }
248 #endif
249
~RefCounter()250 RefCounter::~RefCounter()
251 {
252 #ifdef DEBUG_REFBASE
253 if (enableTrack) {
254 #ifndef PRINT_TRACK_AT_ONCE
255 PrintTracker();
256 #endif
257 }
258 #endif
259 }
260
IncStrongRefCount(const void * objectId)261 int RefCounter::IncStrongRefCount(const void* objectId)
262 {
263 DebugRefBase(objectId);
264 int curCount = atomicStrong_.load(std::memory_order_relaxed);
265 if (curCount >= 0) {
266 curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed);
267 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
268 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicStrong_");
269 #endif
270 if (curCount == INITIAL_PRIMARY_VALUE) {
271 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
272 int newCurCount = atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release);
273 RefBaseDebugPrint(newCurCount, __builtin_return_address(0), objectId, "--", "atomicStrong_");
274 #else
275 atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release);
276 #endif
277 }
278 }
279
280 return curCount;
281 }
282
DecStrongRefCount(const void * objectId)283 int RefCounter::DecStrongRefCount(const void* objectId)
284 {
285 DebugRefBase(objectId);
286 int curCount = GetStrongRefCount();
287 if (curCount == INITIAL_PRIMARY_VALUE) {
288 // unexpected case: there had never a strong reference.
289 UTILS_LOGD("decStrongRef when there is nerver a strong reference");
290 } else if (curCount > 0) {
291 // we should update the current count here.
292 // it may be changed after last operation.
293 curCount = atomicStrong_.fetch_sub(1, std::memory_order_release);
294 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
295 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "--", "atomicStrong_");
296 #endif
297 }
298
299 return curCount;
300 }
301
GetStrongRefCount()302 int RefCounter::GetStrongRefCount()
303 {
304 return atomicStrong_.load(std::memory_order_relaxed);
305 }
306
IncWeakRefCount(const void * objectId)307 int RefCounter::IncWeakRefCount(const void* objectId)
308 {
309 DebugRefBase(objectId);
310 int curCount = atomicWeak_.fetch_add(1, std::memory_order_relaxed);
311 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
312 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicWeak_");
313 #endif
314 return curCount;
315 }
316
DecWeakRefCount(const void * objectId)317 int RefCounter::DecWeakRefCount(const void* objectId)
318 {
319 DebugRefBase(objectId);
320 int curCount = GetWeakRefCount();
321 if (curCount > 0) {
322 curCount = atomicWeak_.fetch_sub(1, std::memory_order_release);
323 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
324 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "--", "atomicWeak_");
325 #endif
326 }
327
328 if (curCount != 1) {
329 return curCount;
330 }
331 std::atomic_thread_fence(std::memory_order_acquire);
332 if (IsLifeTimeExtended()) {
333 if (callback_) {
334 callback_();
335 }
336 } else {
337 // only weak ptr but never had a strong ref, we should do nothing here theoretically. But it may cause a leak.
338 if (GetStrongRefCount() == INITIAL_PRIMARY_VALUE) {
339 UTILS_LOGW("dec the last weakRef before it had a strong reference, delete refbase to avoid Memory Leak");
340 if (callback_) {
341 callback_();
342 }
343 } else {
344 // free RefCounter
345 DecRefCount();
346 }
347 }
348
349 return curCount;
350 }
351
GetWeakRefCount()352 int RefCounter::GetWeakRefCount()
353 {
354 return atomicWeak_.load(std::memory_order_relaxed);
355 }
356
GetAttemptAcquire()357 int RefCounter::GetAttemptAcquire()
358 {
359 return atomicAttempt_.load(std::memory_order_relaxed);
360 }
361
SetAttemptAcquire()362 void RefCounter::SetAttemptAcquire()
363 {
364 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
365 int curCount = atomicAttempt_.fetch_add(1, std::memory_order_relaxed);
366 RefBaseDebugPrint(curCount, __builtin_return_address(0), nullptr, "++", "atomicAttempt_");
367 #else
368 (void)atomicAttempt_.fetch_add(1, std::memory_order_relaxed);
369 #endif
370 }
371
IsAttemptAcquireSet()372 bool RefCounter::IsAttemptAcquireSet()
373 {
374 return static_cast<bool>(atomicAttempt_.load(std::memory_order_relaxed) > 0);
375 }
376
ClearAttemptAcquire()377 void RefCounter::ClearAttemptAcquire()
378 {
379 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
380 int curCount = atomicAttempt_.fetch_sub(1, std::memory_order_relaxed);
381 RefBaseDebugPrint(curCount, __builtin_return_address(0), nullptr, "--", "atomicAttempt_");
382 #else
383 atomicAttempt_.fetch_sub(1, std::memory_order_relaxed);
384 #endif
385 }
386
ExtendObjectLifetime()387 void RefCounter::ExtendObjectLifetime()
388 {
389 atomicFlags_.fetch_or(FLAG_EXTEND_LIFE_TIME, std::memory_order_relaxed);
390 }
391
IsLifeTimeExtended()392 bool RefCounter::IsLifeTimeExtended()
393 {
394 return static_cast<bool>(atomicFlags_.load(std::memory_order_relaxed) & FLAG_EXTEND_LIFE_TIME);
395 }
396
AttemptIncStrongRef(const void * objectId,int & outCount)397 bool RefCounter::AttemptIncStrongRef(const void *objectId, int &outCount)
398 {
399 int curCount = GetStrongRefCount();
400 IncWeakRefCount(objectId);
401
402 // if the object already had strong references.just promoting it.
403 while ((curCount > 0) && (curCount != INITIAL_PRIMARY_VALUE)) {
404 if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) {
405 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicStrong_");
406 goto ATTEMPT_SUCCESS;
407 }
408 // someone else changed the counter.re-acquire the counter value.
409 curCount = atomicStrong_.load(std::memory_order_relaxed);
410 }
411
412 if ((curCount == INITIAL_PRIMARY_VALUE) && !IsLifeTimeExtended()) {
413 // this object has a "normal" life-time,
414 while (curCount > 0) {
415 if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) {
416 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicStrong_");
417 goto ATTEMPT_SUCCESS;
418 }
419 curCount = atomicStrong_.load(std::memory_order_relaxed);
420 }
421 }
422
423 if (IsLifeTimeExtended()) {
424 #ifdef OHOS_PLATFORM
425 if (!IsCanPromoteValid() || !canPromote_()) {
426 return false;
427 }
428 #endif
429 curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed);
430 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicStrong_");
431 }
432
433 ATTEMPT_SUCCESS:
434 if (curCount == INITIAL_PRIMARY_VALUE) {
435 outCount = curCount;
436 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
437 int newCurCount = atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release);
438 RefBaseDebugPrint(newCurCount, __builtin_return_address(0), objectId, "--", "atomicStrong_");
439 #else
440 atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release);
441 #endif
442 return true;
443 }
444
445 if (curCount < 0 || (!IsLifeTimeExtended() && curCount == 0)) {
446 // the object destroyed on strong reference count reduce to zero.
447 DecWeakRefCount(objectId);
448 return false;
449 }
450
451 return true;
452 }
453
AttemptIncStrong(const void * objectId)454 bool RefCounter::AttemptIncStrong(const void *objectId)
455 {
456 IncWeakRefCount(objectId);
457 int curCount = GetStrongRefCount();
458 while (curCount > 0) {
459 if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) {
460 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
461 RefBaseDebugPrint(curCount, __builtin_return_address(0), objectId, "++", "atomicStrong_");
462 #endif
463 break;
464 }
465 // curCount has been updated.
466 }
467 if (curCount <= 0) {
468 DecWeakRefCount(objectId);
469 }
470 return curCount > 0;
471 }
472
RefBase()473 RefBase::RefBase() : refs_(new RefCounter())
474 {
475 refs_->IncRefCount();
476 refs_->SetCallback([this] { this->RefPtrCallback(); });
477 #ifdef OHOS_PLATFORM
478 refs_->SetCanPromote([this] { return this->CanPromote(); });
479 #endif
480 }
481
RefBase(const RefBase &)482 RefBase::RefBase(const RefBase &)
483 {
484 refs_ = new (std::nothrow) RefCounter();
485 if (refs_ != nullptr) {
486 refs_->IncRefCount();
487 refs_->SetCallback([this] { this->RefPtrCallback(); });
488 #ifdef OHOS_PLATFORM
489 refs_->SetCanPromote([this] { return this->CanPromote(); });
490 #endif
491 }
492 }
493
494 #ifdef OHOS_PLATFORM
CanPromote()495 bool RefBase::CanPromote()
496 {
497 return true;
498 }
499 #endif
500
RefPtrCallback()501 void RefBase::RefPtrCallback()
502 {
503 delete this;
504 }
505
506 /*
507 * The two ends of the assignment are two independent and exclusive,
508 * and the application should not share the reference counter.
509 * RISK: If there is a reference count on the left of the equal sign,
510 * it may cause a reference count exception
511 */
operator =(const RefBase &)512 RefBase &RefBase::operator=(const RefBase &)
513 {
514 if (refs_ != nullptr) {
515 refs_->RemoveCallback();
516 refs_->DecRefCount();
517 }
518
519 refs_ = new (std::nothrow) RefCounter();
520 if (refs_ != nullptr) {
521 refs_->IncRefCount();
522 refs_->SetCallback([this] { this->RefPtrCallback(); });
523 #ifdef OHOS_PLATFORM
524 refs_->SetCanPromote([this] { return this->CanPromote(); });
525 #endif
526 }
527
528 return *this;
529 }
530
RefBase(RefBase && other)531 RefBase::RefBase(RefBase &&other) noexcept
532 {
533 refs_ = other.refs_;
534 other.refs_ = nullptr;
535 }
536
operator =(RefBase && other)537 RefBase &RefBase::operator=(RefBase &&other) noexcept
538 {
539 if (refs_ == other.refs_) {
540 return *this;
541 }
542
543 if (refs_ != nullptr) {
544 refs_->RemoveCallback();
545 refs_->DecRefCount();
546 }
547
548 refs_ = other.refs_;
549 other.refs_ = nullptr;
550 return *this;
551 }
552
~RefBase()553 RefBase::~RefBase()
554 {
555 if (refs_ != nullptr) {
556 refs_->RemoveCallback();
557 if ((refs_->IsLifeTimeExtended() && refs_->GetWeakRefCount() == 0) ||
558 refs_->GetStrongRefCount() == INITIAL_PRIMARY_VALUE) {
559 refs_->DecRefCount();
560 }
561 refs_ = nullptr;
562 }
563 }
564
ExtendObjectLifetime()565 void RefBase::ExtendObjectLifetime()
566 {
567 refs_->ExtendObjectLifetime();
568 }
569
IncStrongRef(const void * objectId)570 void RefBase::IncStrongRef(const void *objectId)
571 {
572 if (refs_ == nullptr) {
573 return;
574 }
575
576 IncWeakRef(objectId);
577 const int curCount = refs_->IncStrongRefCount(objectId);
578 if (!refs_->IsLifeTimeExtended() && curCount == 0) {
579 UTILS_LOGF("RefBase object still incStrongRef after last strong ref");
580 }
581 if (curCount == INITIAL_PRIMARY_VALUE) {
582 OnFirstStrongRef(objectId);
583 }
584 }
585
CheckIsAttemptAcquireSet(const void * objectId)586 void RefBase::CheckIsAttemptAcquireSet(const void *objectId)
587 {
588 if (refs_->IsAttemptAcquireSet()) {
589 refs_->ClearAttemptAcquire();
590 const int attemptCount = refs_->GetAttemptAcquire();
591 if (attemptCount < 0) {
592 UTILS_LOGF("Multi-threads trigger illegal decstrong from %{public}d due to AttemptIncStrong in ipc",
593 attemptCount);
594 }
595 refs_->DecStrongRefCount(objectId);
596 refs_->DecWeakRefCount(objectId);
597 }
598 }
599
DecStrongRef(const void * objectId)600 void RefBase::DecStrongRef(const void *objectId)
601 {
602 if (refs_ == nullptr) {
603 return;
604 }
605
606 RefCounter * const refs = refs_;
607 const int curCount = refs->DecStrongRefCount(objectId);
608 if (curCount <= 0) {
609 UTILS_LOGF("RefBase object call decStrongRef too many times");
610 }
611 if (curCount == 1) {
612 std::atomic_thread_fence(std::memory_order_acquire);
613 OnLastStrongRef(objectId);
614 if (!refs->IsLifeTimeExtended()) {
615 if (refs->callback_) {
616 refs->callback_();
617 }
618 }
619 }
620
621 refs->DecWeakRefCount(objectId);
622 }
623
GetSptrRefCount()624 int RefBase::GetSptrRefCount()
625 {
626 if (refs_ == nullptr) {
627 return 0;
628 }
629 return refs_->GetStrongRefCount();
630 }
631
CreateWeakRef(void * cookie)632 WeakRefCounter *RefBase::CreateWeakRef(void *cookie)
633 {
634 if (refs_ != nullptr) {
635 return new WeakRefCounter(refs_, cookie);
636 }
637 return nullptr;
638 }
639
IncWeakRef(const void * objectId)640 void RefBase::IncWeakRef(const void *objectId)
641 {
642 if (refs_ != nullptr) {
643 refs_->IncWeakRefCount(objectId);
644 }
645 }
646
GetRefCounter() const647 RefCounter *RefBase::GetRefCounter() const
648 {
649 return refs_;
650 }
651
DecWeakRef(const void * objectId)652 void RefBase::DecWeakRef(const void *objectId)
653 {
654 if (refs_ != nullptr) {
655 refs_->DecWeakRefCount(objectId);
656 }
657 }
658
GetWptrRefCount()659 int RefBase::GetWptrRefCount()
660 {
661 if (refs_ == nullptr) {
662 return 0;
663 }
664 return refs_->GetWeakRefCount();
665 }
666
AttemptAcquire(const void * objectId)667 bool RefBase::AttemptAcquire(const void *objectId)
668 {
669 if (refs_ == nullptr) {
670 return false;
671 }
672
673 int count = 0;
674 if (refs_->AttemptIncStrongRef(objectId, count)) {
675 refs_->SetAttemptAcquire();
676 if (count == INITIAL_PRIMARY_VALUE) {
677 OnFirstStrongRef(objectId);
678 }
679
680 return true;
681 }
682 return false;
683 }
684
AttemptIncStrongRef(const void * objectId)685 bool RefBase::AttemptIncStrongRef(const void *objectId)
686 {
687 if ((refs_ != nullptr) && (OnAttemptPromoted(objectId))) {
688 int count = 0;
689 bool ret = refs_->AttemptIncStrongRef(objectId, count);
690 if (count == INITIAL_PRIMARY_VALUE) {
691 OnFirstStrongRef(objectId);
692 }
693 return ret;
694 }
695
696 return false;
697 }
698
AttemptIncStrong(const void * objectId)699 bool RefBase::AttemptIncStrong(const void *objectId)
700 {
701 if (refs_ == nullptr) {
702 return false;
703 }
704 if (refs_->AttemptIncStrong(objectId)) {
705 refs_->SetAttemptAcquire();
706 return true;
707 }
708 return false;
709 }
710
IsAttemptAcquireSet()711 bool RefBase::IsAttemptAcquireSet()
712 {
713 if (refs_ == nullptr) {
714 return false;
715 }
716 return refs_->IsAttemptAcquireSet();
717 }
718
IsExtendLifeTimeSet()719 bool RefBase::IsExtendLifeTimeSet()
720 {
721 if (refs_ == nullptr) {
722 return false;
723 }
724 return refs_->IsLifeTimeExtended();
725 }
726
OnFirstStrongRef(const void *)727 void RefBase::OnFirstStrongRef(const void*)
728 {}
729
OnLastStrongRef(const void *)730 void RefBase::OnLastStrongRef(const void*)
731 {}
732
OnLastWeakRef(const void *)733 void RefBase::OnLastWeakRef(const void*)
734 {}
735
OnAttemptPromoted(const void *)736 bool RefBase::OnAttemptPromoted(const void*)
737 {
738 return true;
739 }
740
741 #if ((defined DEBUG_REFBASE) && (!defined TRACK_ALL))
EnableTracker()742 void RefBase::EnableTracker()
743 {
744 refs_->EnableTracker();
745 }
746 #else
EnableTracker()747 void RefBase::EnableTracker()
748 {
749 }
750 #endif
751
EnableTrackerWithDomainId(unsigned int domainId)752 void RefBase::EnableTrackerWithDomainId(unsigned int domainId)
753 {
754 #if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
755 refs_->EnableTrackerWithDomainId(domainId);
756 #endif
757 }
758
759 } // namespace OHOS
760