LCOV - code coverage report
Current view: top level - media/libstagefright/system/core/libutils - RefBase.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 149 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2005 The Android Open Source Project
       3             :  *
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at
       7             :  *
       8             :  *      http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  */
      16             : 
      17             : #define LOG_TAG "RefBase"
      18             : // #define LOG_NDEBUG 0
      19             : 
      20             : #include <utils/RefBase.h>
      21             : 
      22             : #include <utils/Atomic.h>
      23             : #ifdef _MSC_VER
      24             : class CallStack {
      25             : public:
      26             :     CallStack(int x) {}
      27             : };
      28             : #else
      29             : #include <utils/CallStack.h>
      30             : #endif
      31             : #include <utils/Log.h>
      32             : #include <utils/threads.h>
      33             : 
      34             : #include <stdlib.h>
      35             : #include <stdio.h>
      36             : #include <typeinfo>
      37             : #include <sys/types.h>
      38             : #include <sys/stat.h>
      39             : #include <fcntl.h>
      40             : #include <unistd.h>
      41             : 
      42             : // compile with refcounting debugging enabled
      43             : #define DEBUG_REFS                      0
      44             : 
      45             : // whether ref-tracking is enabled by default, if not, trackMe(true, false)
      46             : // needs to be called explicitly
      47             : #define DEBUG_REFS_ENABLED_BY_DEFAULT   0
      48             : 
      49             : // whether callstack are collected (significantly slows things down)
      50             : #define DEBUG_REFS_CALLSTACK_ENABLED    0
      51             : 
      52             : // folder where stack traces are saved when DEBUG_REFS is enabled
      53             : // this folder needs to exist and be writable
      54             : #define DEBUG_REFS_CALLSTACK_PATH       "/data/debug"
      55             : 
      56             : // log all reference counting operations
      57             : #define PRINT_REFS                      0
      58             : 
      59             : // ---------------------------------------------------------------------------
      60             : 
      61             : namespace stagefright {
      62             : 
      63             : #define INITIAL_STRONG_VALUE (1<<28)
      64             : 
      65             : // ---------------------------------------------------------------------------
      66             : 
      67             : class RefBase::weakref_impl : public RefBase::weakref_type
      68             : {
      69             : public:
      70             :     volatile int32_t    mStrong;
      71             :     volatile int32_t    mWeak;
      72             :     RefBase* const      mBase;
      73             :     volatile int32_t    mFlags;
      74             : 
      75             : #if !DEBUG_REFS
      76             : 
      77           0 :     weakref_impl(RefBase* base)
      78           0 :         : mStrong(INITIAL_STRONG_VALUE)
      79             :         , mWeak(0)
      80             :         , mBase(base)
      81           0 :         , mFlags(0)
      82             :     {
      83           0 :     }
      84             : 
      85           0 :     void addStrongRef(const void* /*id*/) { }
      86           0 :     void removeStrongRef(const void* /*id*/) { }
      87           0 :     void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
      88           0 :     void addWeakRef(const void* /*id*/) { }
      89           0 :     void removeWeakRef(const void* /*id*/) { }
      90           0 :     void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
      91           0 :     void printRefs() const { }
      92           0 :     void trackMe(bool, bool) { }
      93             : 
      94             : #else
      95             : 
      96             :     weakref_impl(RefBase* base)
      97             :         : mStrong(INITIAL_STRONG_VALUE)
      98             :         , mWeak(0)
      99             :         , mBase(base)
     100             :         , mFlags(0)
     101             :         , mStrongRefs(NULL)
     102             :         , mWeakRefs(NULL)
     103             :         , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
     104             :         , mRetain(false)
     105             :     {
     106             :     }
     107             :     
     108             :     ~weakref_impl()
     109             :     {
     110             :         bool dumpStack = false;
     111             :         if (!mRetain && mStrongRefs != NULL) {
     112             :             dumpStack = true;
     113             :             ALOGE("Strong references remain:");
     114             :             ref_entry* refs = mStrongRefs;
     115             :             while (refs) {
     116             :                 char inc = refs->ref >= 0 ? '+' : '-';
     117             :                 ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
     118             : #if DEBUG_REFS_CALLSTACK_ENABLED
     119             :                 refs->stack.dump(LOG_TAG);
     120             : #endif
     121             :                 refs = refs->next;
     122             :             }
     123             :         }
     124             : 
     125             :         if (!mRetain && mWeakRefs != NULL) {
     126             :             dumpStack = true;
     127             :             ALOGE("Weak references remain!");
     128             :             ref_entry* refs = mWeakRefs;
     129             :             while (refs) {
     130             :                 char inc = refs->ref >= 0 ? '+' : '-';
     131             :                 ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
     132             : #if DEBUG_REFS_CALLSTACK_ENABLED
     133             :                 refs->stack.dump(LOG_TAG);
     134             : #endif
     135             :                 refs = refs->next;
     136             :             }
     137             :         }
     138             :         if (dumpStack) {
     139             :             ALOGE("above errors at:");
     140             :             CallStack stack(LOG_TAG);
     141             :         }
     142             :     }
     143             : 
     144             :     void addStrongRef(const void* id) {
     145             :         //ALOGD_IF(mTrackEnabled,
     146             :         //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
     147             :         addRef(&mStrongRefs, id, mStrong);
     148             :     }
     149             : 
     150             :     void removeStrongRef(const void* id) {
     151             :         //ALOGD_IF(mTrackEnabled,
     152             :         //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
     153             :         if (!mRetain) {
     154             :             removeRef(&mStrongRefs, id);
     155             :         } else {
     156             :             addRef(&mStrongRefs, id, -mStrong);
     157             :         }
     158             :     }
     159             : 
     160             :     void renameStrongRefId(const void* old_id, const void* new_id) {
     161             :         //ALOGD_IF(mTrackEnabled,
     162             :         //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
     163             :         //        mBase, old_id, new_id);
     164             :         renameRefsId(mStrongRefs, old_id, new_id);
     165             :     }
     166             : 
     167             :     void addWeakRef(const void* id) {
     168             :         addRef(&mWeakRefs, id, mWeak);
     169             :     }
     170             : 
     171             :     void removeWeakRef(const void* id) {
     172             :         if (!mRetain) {
     173             :             removeRef(&mWeakRefs, id);
     174             :         } else {
     175             :             addRef(&mWeakRefs, id, -mWeak);
     176             :         }
     177             :     }
     178             : 
     179             :     void renameWeakRefId(const void* old_id, const void* new_id) {
     180             :         renameRefsId(mWeakRefs, old_id, new_id);
     181             :     }
     182             : 
     183             :     void trackMe(bool track, bool retain)
     184             :     { 
     185             :         mTrackEnabled = track;
     186             :         mRetain = retain;
     187             :     }
     188             : 
     189             :     void printRefs() const
     190             :     {
     191             :         String8 text;
     192             : 
     193             :         {
     194             :             Mutex::Autolock _l(mMutex);
     195             :             char buf[128];
     196             :             sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
     197             :             text.append(buf);
     198             :             printRefsLocked(&text, mStrongRefs);
     199             :             sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
     200             :             text.append(buf);
     201             :             printRefsLocked(&text, mWeakRefs);
     202             :         }
     203             : 
     204             :         {
     205             :             char name[100];
     206             :             snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this);
     207             :             int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
     208             :             if (rc >= 0) {
     209             :                 write(rc, text.string(), text.length());
     210             :                 close(rc);
     211             :                 ALOGD("STACK TRACE for %p saved in %s", this, name);
     212             :             }
     213             :             else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
     214             :                       name, strerror(errno));
     215             :         }
     216             :     }
     217             : 
     218             : private:
     219             :     struct ref_entry
     220             :     {
     221             :         ref_entry* next;
     222             :         const void* id;
     223             : #if DEBUG_REFS_CALLSTACK_ENABLED
     224             :         CallStack stack;
     225             : #endif
     226             :         int32_t ref;
     227             :     };
     228             : 
     229             :     void addRef(ref_entry** refs, const void* id, int32_t mRef)
     230             :     {
     231             :         if (mTrackEnabled) {
     232             :             AutoMutex _l(mMutex);
     233             : 
     234             :             ref_entry* ref = new ref_entry;
     235             :             // Reference count at the time of the snapshot, but before the
     236             :             // update.  Positive value means we increment, negative--we
     237             :             // decrement the reference count.
     238             :             ref->ref = mRef;
     239             :             ref->id = id;
     240             : #if DEBUG_REFS_CALLSTACK_ENABLED
     241             :             ref->stack.update(2);
     242             : #endif
     243             :             ref->next = *refs;
     244             :             *refs = ref;
     245             :         }
     246             :     }
     247             : 
     248             :     void removeRef(ref_entry** refs, const void* id)
     249             :     {
     250             :         if (mTrackEnabled) {
     251             :             AutoMutex _l(mMutex);
     252             :             
     253             :             ref_entry* const head = *refs;
     254             :             ref_entry* ref = head;
     255             :             while (ref != NULL) {
     256             :                 if (ref->id == id) {
     257             :                     *refs = ref->next;
     258             :                     delete ref;
     259             :                     return;
     260             :                 }
     261             :                 refs = &ref->next;
     262             :                 ref = *refs;
     263             :             }
     264             : 
     265             :             ALOGE("RefBase: removing id %p on RefBase %p"
     266             :                     "(weakref_type %p) that doesn't exist!",
     267             :                     id, mBase, this);
     268             : 
     269             :             ref = head;
     270             :             while (ref) {
     271             :                 char inc = ref->ref >= 0 ? '+' : '-';
     272             :                 ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
     273             :                 ref = ref->next;
     274             :             }
     275             : 
     276             :             CallStack stack(LOG_TAG);
     277             :         }
     278             :     }
     279             : 
     280             :     void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
     281             :     {
     282             :         if (mTrackEnabled) {
     283             :             AutoMutex _l(mMutex);
     284             :             ref_entry* ref = r;
     285             :             while (ref != NULL) {
     286             :                 if (ref->id == old_id) {
     287             :                     ref->id = new_id;
     288             :                 }
     289             :                 ref = ref->next;
     290             :             }
     291             :         }
     292             :     }
     293             : 
     294             :     void printRefsLocked(String8* out, const ref_entry* refs) const
     295             :     {
     296             :         char buf[128];
     297             :         while (refs) {
     298             :             char inc = refs->ref >= 0 ? '+' : '-';
     299             :             sprintf(buf, "\t%c ID %p (ref %d):\n", 
     300             :                     inc, refs->id, refs->ref);
     301             :             out->append(buf);
     302             : #if DEBUG_REFS_CALLSTACK_ENABLED
     303             :             out->append(refs->stack.toString("\t\t"));
     304             : #else
     305             :             out->append("\t\t(call stacks disabled)");
     306             : #endif
     307             :             refs = refs->next;
     308             :         }
     309             :     }
     310             : 
     311             :     mutable Mutex mMutex;
     312             :     ref_entry* mStrongRefs;
     313             :     ref_entry* mWeakRefs;
     314             : 
     315             :     bool mTrackEnabled;
     316             :     // Collect stack traces on addref and removeref, instead of deleting the stack references
     317             :     // on removeref that match the address ones.
     318             :     bool mRetain;
     319             : 
     320             : #endif
     321             : };
     322             : 
     323             : // ---------------------------------------------------------------------------
     324             : 
     325           0 : void RefBase::incStrong(const void* id) const
     326             : {
     327           0 :     weakref_impl* const refs = mRefs;
     328           0 :     refs->incWeak(id);
     329             :     
     330           0 :     refs->addStrongRef(id);
     331           0 :     const int32_t c = android_atomic_inc(&refs->mStrong);
     332             :     ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
     333             : #if PRINT_REFS
     334             :     ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
     335             : #endif
     336           0 :     if (c != INITIAL_STRONG_VALUE)  {
     337           0 :         return;
     338             :     }
     339             : 
     340           0 :     android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
     341           0 :     refs->mBase->onFirstRef();
     342             : }
     343             : 
     344           0 : void RefBase::decStrong(const void* id) const
     345             : {
     346           0 :     weakref_impl* const refs = mRefs;
     347           0 :     refs->removeStrongRef(id);
     348           0 :     const int32_t c = android_atomic_dec(&refs->mStrong);
     349             : #if PRINT_REFS
     350             :     ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
     351             : #endif
     352             :     ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
     353           0 :     if (c == 1) {
     354           0 :         refs->mBase->onLastStrongRef(id);
     355           0 :         if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
     356           0 :             delete this;
     357             :         }
     358             :     }
     359           0 :     refs->decWeak(id);
     360           0 : }
     361             : 
     362           0 : void RefBase::forceIncStrong(const void* id) const
     363             : {
     364           0 :     weakref_impl* const refs = mRefs;
     365           0 :     refs->incWeak(id);
     366             :     
     367           0 :     refs->addStrongRef(id);
     368           0 :     const int32_t c = android_atomic_inc(&refs->mStrong);
     369             :     ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
     370             :                refs);
     371             : #if PRINT_REFS
     372             :     ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
     373             : #endif
     374             : 
     375           0 :     switch (c) {
     376             :     case INITIAL_STRONG_VALUE:
     377           0 :         android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
     378             :         // fall through...
     379             :     case 0:
     380           0 :         refs->mBase->onFirstRef();
     381             :     }
     382           0 : }
     383             : 
     384           0 : int32_t RefBase::getStrongCount() const
     385             : {
     386           0 :     return mRefs->mStrong;
     387             : }
     388             : 
     389           0 : RefBase* RefBase::weakref_type::refBase() const
     390             : {
     391           0 :     return static_cast<const weakref_impl*>(this)->mBase;
     392             : }
     393             : 
     394           0 : void RefBase::weakref_type::incWeak(const void* id)
     395             : {
     396           0 :     weakref_impl* const impl = static_cast<weakref_impl*>(this);
     397           0 :     impl->addWeakRef(id);
     398           0 :     const int32_t c = android_atomic_inc(&impl->mWeak);
     399             :     ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
     400           0 : }
     401             : 
     402             : 
     403           0 : void RefBase::weakref_type::decWeak(const void* id)
     404             : {
     405           0 :     weakref_impl* const impl = static_cast<weakref_impl*>(this);
     406           0 :     impl->removeWeakRef(id);
     407           0 :     const int32_t c = android_atomic_dec(&impl->mWeak);
     408             :     ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
     409           0 :     if (c != 1) return;
     410             : 
     411           0 :     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
     412             :         // This is the regular lifetime case. The object is destroyed
     413             :         // when the last strong reference goes away. Since weakref_impl
     414             :         // outlive the object, it is not destroyed in the dtor, and
     415             :         // we'll have to do it here.
     416           0 :         if (impl->mStrong == INITIAL_STRONG_VALUE) {
     417             :             // Special case: we never had a strong reference, so we need to
     418             :             // destroy the object now.
     419           0 :             delete impl->mBase;
     420             :         } else {
     421             :             // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
     422             :             delete impl;
     423             :         }
     424             :     } else {
     425             :         // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
     426           0 :         impl->mBase->onLastWeakRef(id);
     427           0 :         if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
     428             :             // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
     429             :             // is gone, we can destroy the object.
     430           0 :             delete impl->mBase;
     431             :         }
     432             :     }
     433             : }
     434             : 
     435           0 : bool RefBase::weakref_type::attemptIncStrong(const void* id)
     436             : {
     437           0 :     incWeak(id);
     438             :     
     439           0 :     weakref_impl* const impl = static_cast<weakref_impl*>(this);
     440           0 :     int32_t curCount = impl->mStrong;
     441             : 
     442             :     ALOG_ASSERT(curCount >= 0,
     443             :             "attemptIncStrong called on %p after underflow", this);
     444             : 
     445           0 :     while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
     446             :         // we're in the easy/common case of promoting a weak-reference
     447             :         // from an existing strong reference.
     448           0 :         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
     449           0 :             break;
     450             :         }
     451             :         // the strong count has changed on us, we need to re-assert our
     452             :         // situation.
     453           0 :         curCount = impl->mStrong;
     454             :     }
     455             :     
     456           0 :     if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
     457             :         // we're now in the harder case of either:
     458             :         // - there never was a strong reference on us
     459             :         // - or, all strong references have been released
     460           0 :         if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
     461             :             // this object has a "normal" life-time, i.e.: it gets destroyed
     462             :             // when the last strong reference goes away
     463           0 :             if (curCount <= 0) {
     464             :                 // the last strong-reference got released, the object cannot
     465             :                 // be revived.
     466           0 :                 decWeak(id);
     467           0 :                 return false;
     468             :             }
     469             : 
     470             :             // here, curCount == INITIAL_STRONG_VALUE, which means
     471             :             // there never was a strong-reference, so we can try to
     472             :             // promote this object; we need to do that atomically.
     473           0 :             while (curCount > 0) {
     474           0 :                 if (android_atomic_cmpxchg(curCount, curCount + 1,
     475             :                         &impl->mStrong) == 0) {
     476           0 :                     break;
     477             :                 }
     478             :                 // the strong count has changed on us, we need to re-assert our
     479             :                 // situation (e.g.: another thread has inc/decStrong'ed us)
     480           0 :                 curCount = impl->mStrong;
     481             :             }
     482             : 
     483           0 :             if (curCount <= 0) {
     484             :                 // promote() failed, some other thread destroyed us in the
     485             :                 // meantime (i.e.: strong count reached zero).
     486           0 :                 decWeak(id);
     487           0 :                 return false;
     488             :             }
     489             :         } else {
     490             :             // this object has an "extended" life-time, i.e.: it can be
     491             :             // revived from a weak-reference only.
     492             :             // Ask the object's implementation if it agrees to be revived
     493           0 :             if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
     494             :                 // it didn't so give-up.
     495           0 :                 decWeak(id);
     496           0 :                 return false;
     497             :             }
     498             :             // grab a strong-reference, which is always safe due to the
     499             :             // extended life-time.
     500           0 :             curCount = android_atomic_inc(&impl->mStrong);
     501             :         }
     502             : 
     503             :         // If the strong reference count has already been incremented by
     504             :         // someone else, the implementor of onIncStrongAttempted() is holding
     505             :         // an unneeded reference.  So call onLastStrongRef() here to remove it.
     506             :         // (No, this is not pretty.)  Note that we MUST NOT do this if we
     507             :         // are in fact acquiring the first reference.
     508           0 :         if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
     509           0 :             impl->mBase->onLastStrongRef(id);
     510             :         }
     511             :     }
     512             :     
     513           0 :     impl->addStrongRef(id);
     514             : 
     515             : #if PRINT_REFS
     516             :     ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
     517             : #endif
     518             : 
     519             :     // now we need to fix-up the count if it was INITIAL_STRONG_VALUE
     520             :     // this must be done safely, i.e.: handle the case where several threads
     521             :     // were here in attemptIncStrong().
     522           0 :     curCount = impl->mStrong;
     523           0 :     while (curCount >= INITIAL_STRONG_VALUE) {
     524             :         ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
     525             :                 "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
     526             :                 this);
     527           0 :         if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
     528             :                 &impl->mStrong) == 0) {
     529           0 :             break;
     530             :         }
     531             :         // the strong-count changed on us, we need to re-assert the situation,
     532             :         // for e.g.: it's possible the fix-up happened in another thread.
     533           0 :         curCount = impl->mStrong;
     534             :     }
     535             : 
     536           0 :     return true;
     537             : }
     538             : 
     539           0 : bool RefBase::weakref_type::attemptIncWeak(const void* id)
     540             : {
     541           0 :     weakref_impl* const impl = static_cast<weakref_impl*>(this);
     542             : 
     543           0 :     int32_t curCount = impl->mWeak;
     544             :     ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
     545             :                this);
     546           0 :     while (curCount > 0) {
     547           0 :         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
     548           0 :             break;
     549             :         }
     550           0 :         curCount = impl->mWeak;
     551             :     }
     552             : 
     553           0 :     if (curCount > 0) {
     554           0 :         impl->addWeakRef(id);
     555             :     }
     556             : 
     557           0 :     return curCount > 0;
     558             : }
     559             : 
     560           0 : int32_t RefBase::weakref_type::getWeakCount() const
     561             : {
     562           0 :     return static_cast<const weakref_impl*>(this)->mWeak;
     563             : }
     564             : 
     565           0 : void RefBase::weakref_type::printRefs() const
     566             : {
     567           0 :     static_cast<const weakref_impl*>(this)->printRefs();
     568           0 : }
     569             : 
     570           0 : void RefBase::weakref_type::trackMe(bool enable, bool retain)
     571             : {
     572           0 :     static_cast<weakref_impl*>(this)->trackMe(enable, retain);
     573           0 : }
     574             : 
     575           0 : RefBase::weakref_type* RefBase::createWeak(const void* id) const
     576             : {
     577           0 :     mRefs->incWeak(id);
     578           0 :     return mRefs;
     579             : }
     580             : 
     581           0 : RefBase::weakref_type* RefBase::getWeakRefs() const
     582             : {
     583           0 :     return mRefs;
     584             : }
     585             : 
     586           0 : RefBase::RefBase()
     587           0 :     : mRefs(new weakref_impl(this))
     588             : {
     589           0 : }
     590             : 
     591           0 : RefBase::~RefBase()
     592             : {
     593           0 :     if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
     594             :         // we never acquired a strong (and/or weak) reference on this object.
     595           0 :         delete mRefs;
     596             :     } else {
     597             :         // life-time of this object is extended to WEAK or FOREVER, in
     598             :         // which case weakref_impl doesn't out-live the object and we
     599             :         // can free it now.
     600           0 :         if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
     601             :             // It's possible that the weak count is not 0 if the object
     602             :             // re-acquired a weak reference in its destructor
     603           0 :             if (mRefs->mWeak == 0) {
     604           0 :                 delete mRefs;
     605             :             }
     606             :         }
     607             :     }
     608             :     // for debugging purposes, clear this.
     609           0 :     const_cast<weakref_impl*&>(mRefs) = NULL;
     610           0 : }
     611             : 
     612           0 : void RefBase::extendObjectLifetime(int32_t mode)
     613             : {
     614           0 :     android_atomic_or(mode, &mRefs->mFlags);
     615           0 : }
     616             : 
     617           0 : void RefBase::onFirstRef()
     618             : {
     619           0 : }
     620             : 
     621           0 : void RefBase::onLastStrongRef(const void* /*id*/)
     622             : {
     623           0 : }
     624             : 
     625           0 : bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
     626             : {
     627           0 :     return (flags&FIRST_INC_STRONG) ? true : false;
     628             : }
     629             : 
     630           0 : void RefBase::onLastWeakRef(const void* /*id*/)
     631             : {
     632           0 : }
     633             : 
     634             : // ---------------------------------------------------------------------------
     635             : 
     636           0 : void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) {
     637             : #if DEBUG_REFS
     638             :     for (size_t i=0 ; i<n ; i++) {
     639             :         renamer(i);
     640             :     }
     641             : #endif
     642           0 : }
     643             : 
     644           0 : void RefBase::renameRefId(weakref_type* ref,
     645             :         const void* old_id, const void* new_id) {
     646           0 :     weakref_impl* const impl = static_cast<weakref_impl*>(ref);
     647           0 :     impl->renameStrongRefId(old_id, new_id);
     648           0 :     impl->renameWeakRefId(old_id, new_id);
     649           0 : }
     650             : 
     651           0 : void RefBase::renameRefId(RefBase* ref,
     652             :         const void* old_id, const void* new_id) {
     653           0 :     ref->mRefs->renameStrongRefId(old_id, new_id);
     654           0 :     ref->mRefs->renameWeakRefId(old_id, new_id);
     655           0 : }
     656             : 
     657             : }; // namespace stagefright

Generated by: LCOV version 1.13