Home | History | Annotate | Download | only in utils
      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 
     19 #include <utils/RefBase.h>
     20 
     21 #include <utils/Atomic.h>
     22 #include <utils/CallStack.h>
     23 #include <utils/KeyedVector.h>
     24 #include <utils/Log.h>
     25 #include <utils/threads.h>
     26 
     27 #include <stdlib.h>
     28 #include <stdio.h>
     29 #include <typeinfo>
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 #include <fcntl.h>
     33 #include <unistd.h>
     34 
     35 // compile with refcounting debugging enabled
     36 #define DEBUG_REFS                      0
     37 #define DEBUG_REFS_ENABLED_BY_DEFAULT   1
     38 #define DEBUG_REFS_CALLSTACK_ENABLED    1
     39 
     40 // log all reference counting operations
     41 #define PRINT_REFS                      0
     42 
     43 // ---------------------------------------------------------------------------
     44 
     45 namespace android {
     46 
     47 #define INITIAL_STRONG_VALUE (1<<28)
     48 
     49 // ---------------------------------------------------------------------------
     50 
     51 RefBase::Destroyer::~Destroyer() {
     52 }
     53 
     54 // ---------------------------------------------------------------------------
     55 
     56 class RefBase::weakref_impl : public RefBase::weakref_type
     57 {
     58 public:
     59     volatile int32_t    mStrong;
     60     volatile int32_t    mWeak;
     61     RefBase* const      mBase;
     62     volatile int32_t    mFlags;
     63     Destroyer*          mDestroyer;
     64 
     65 #if !DEBUG_REFS
     66 
     67     weakref_impl(RefBase* base)
     68         : mStrong(INITIAL_STRONG_VALUE)
     69         , mWeak(0)
     70         , mBase(base)
     71         , mFlags(0)
     72         , mDestroyer(0)
     73     {
     74     }
     75 
     76     void addStrongRef(const void* /*id*/) { }
     77     void removeStrongRef(const void* /*id*/) { }
     78     void addWeakRef(const void* /*id*/) { }
     79     void removeWeakRef(const void* /*id*/) { }
     80     void printRefs() const { }
     81     void trackMe(bool, bool) { }
     82 
     83 #else
     84 
     85     weakref_impl(RefBase* base)
     86         : mStrong(INITIAL_STRONG_VALUE)
     87         , mWeak(0)
     88         , mBase(base)
     89         , mFlags(0)
     90         , mStrongRefs(NULL)
     91         , mWeakRefs(NULL)
     92         , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
     93         , mRetain(false)
     94     {
     95         //LOGI("NEW weakref_impl %p for RefBase %p", this, base);
     96     }
     97 
     98     ~weakref_impl()
     99     {
    100         LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!");
    101         LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!");
    102     }
    103 
    104     void addStrongRef(const void* id)
    105     {
    106         addRef(&mStrongRefs, id, mStrong);
    107     }
    108 
    109     void removeStrongRef(const void* id)
    110     {
    111         if (!mRetain)
    112             removeRef(&mStrongRefs, id);
    113         else
    114             addRef(&mStrongRefs, id, -mStrong);
    115     }
    116 
    117     void addWeakRef(const void* id)
    118     {
    119         addRef(&mWeakRefs, id, mWeak);
    120     }
    121 
    122     void removeWeakRef(const void* id)
    123     {
    124         if (!mRetain)
    125             removeRef(&mWeakRefs, id);
    126         else
    127             addRef(&mWeakRefs, id, -mWeak);
    128     }
    129 
    130     void trackMe(bool track, bool retain)
    131     {
    132         mTrackEnabled = track;
    133         mRetain = retain;
    134     }
    135 
    136     void printRefs() const
    137     {
    138         String8 text;
    139 
    140         {
    141             AutoMutex _l(const_cast<weakref_impl*>(this)->mMutex);
    142 
    143             char buf[128];
    144             sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
    145             text.append(buf);
    146             printRefsLocked(&text, mStrongRefs);
    147             sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
    148             text.append(buf);
    149             printRefsLocked(&text, mWeakRefs);
    150         }
    151 
    152         {
    153             char name[100];
    154             snprintf(name, 100, "/data/%p.stack", this);
    155             int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
    156             if (rc >= 0) {
    157                 write(rc, text.string(), text.length());
    158                 close(rc);
    159                 LOGD("STACK TRACE for %p saved in %s", this, name);
    160             }
    161             else LOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
    162                       name, strerror(errno));
    163         }
    164     }
    165 
    166 private:
    167     struct ref_entry
    168     {
    169         ref_entry* next;
    170         const void* id;
    171 #if DEBUG_REFS_CALLSTACK_ENABLED
    172         CallStack stack;
    173 #endif
    174         int32_t ref;
    175     };
    176 
    177     void addRef(ref_entry** refs, const void* id, int32_t mRef)
    178     {
    179         if (mTrackEnabled) {
    180             AutoMutex _l(mMutex);
    181             ref_entry* ref = new ref_entry;
    182             // Reference count at the time of the snapshot, but before the
    183             // update.  Positive value means we increment, negative--we
    184             // decrement the reference count.
    185             ref->ref = mRef;
    186             ref->id = id;
    187 #if DEBUG_REFS_CALLSTACK_ENABLED
    188             ref->stack.update(2);
    189 #endif
    190 
    191             ref->next = *refs;
    192             *refs = ref;
    193         }
    194     }
    195 
    196     void removeRef(ref_entry** refs, const void* id)
    197     {
    198         if (mTrackEnabled) {
    199             AutoMutex _l(mMutex);
    200 
    201             ref_entry* ref = *refs;
    202             while (ref != NULL) {
    203                 if (ref->id == id) {
    204                     *refs = ref->next;
    205                     delete ref;
    206                     return;
    207                 }
    208 
    209                 refs = &ref->next;
    210                 ref = *refs;
    211             }
    212 
    213             LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!",
    214                              id, mBase, this);
    215         }
    216     }
    217 
    218     void printRefsLocked(String8* out, const ref_entry* refs) const
    219     {
    220         char buf[128];
    221         while (refs) {
    222             char inc = refs->ref >= 0 ? '+' : '-';
    223             sprintf(buf, "\t%c ID %p (ref %d):\n",
    224                     inc, refs->id, refs->ref);
    225             out->append(buf);
    226 #if DEBUG_REFS_CALLSTACK_ENABLED
    227             out->append(refs->stack.toString("\t\t"));
    228 #else
    229             out->append("\t\t(call stacks disabled)");
    230 #endif
    231             refs = refs->next;
    232         }
    233     }
    234 
    235     Mutex mMutex;
    236     ref_entry* mStrongRefs;
    237     ref_entry* mWeakRefs;
    238 
    239     bool mTrackEnabled;
    240     // Collect stack traces on addref and removeref, instead of deleting the stack references
    241     // on removeref that match the address ones.
    242     bool mRetain;
    243 
    244 #if 0
    245     void addRef(KeyedVector<const void*, int32_t>* refs, const void* id)
    246     {
    247         AutoMutex _l(mMutex);
    248         ssize_t i = refs->indexOfKey(id);
    249         if (i >= 0) {
    250             ++(refs->editValueAt(i));
    251         } else {
    252             i = refs->add(id, 1);
    253         }
    254     }
    255 
    256     void removeRef(KeyedVector<const void*, int32_t>* refs, const void* id)
    257     {
    258         AutoMutex _l(mMutex);
    259         ssize_t i = refs->indexOfKey(id);
    260         LOG_ALWAYS_FATAL_IF(i < 0, "RefBase: removing id %p that doesn't exist!", id);
    261         if (i >= 0) {
    262             int32_t val = --(refs->editValueAt(i));
    263             if (val == 0) {
    264                 refs->removeItemsAt(i);
    265             }
    266         }
    267     }
    268 
    269     void printRefs(const KeyedVector<const void*, int32_t>& refs)
    270     {
    271         const size_t N=refs.size();
    272         for (size_t i=0; i<N; i++) {
    273             printf("\tID %p: %d remain\n", refs.keyAt(i), refs.valueAt(i));
    274         }
    275     }
    276 
    277     mutable Mutex mMutex;
    278     KeyedVector<const void*, int32_t> mStrongRefs;
    279     KeyedVector<const void*, int32_t> mWeakRefs;
    280 #endif
    281 
    282 #endif
    283 };
    284 
    285 // ---------------------------------------------------------------------------
    286 
    287 void RefBase::incStrong(const void* id) const
    288 {
    289     weakref_impl* const refs = mRefs;
    290     refs->addWeakRef(id);
    291     refs->incWeak(id);
    292 
    293     refs->addStrongRef(id);
    294     const int32_t c = android_atomic_inc(&refs->mStrong);
    295     LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
    296 #if PRINT_REFS
    297     LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
    298 #endif
    299     if (c != INITIAL_STRONG_VALUE)  {
    300         return;
    301     }
    302 
    303     android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    304     const_cast<RefBase*>(this)->onFirstRef();
    305 }
    306 
    307 void RefBase::decStrong(const void* id) const
    308 {
    309     weakref_impl* const refs = mRefs;
    310     refs->removeStrongRef(id);
    311     const int32_t c = android_atomic_dec(&refs->mStrong);
    312 #if PRINT_REFS
    313     LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
    314 #endif
    315     LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    316     if (c == 1) {
    317         const_cast<RefBase*>(this)->onLastStrongRef(id);
    318         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
    319             if (refs->mDestroyer) {
    320                 refs->mDestroyer->destroy(this);
    321             } else {
    322                 delete this;
    323             }
    324         }
    325     }
    326     refs->removeWeakRef(id);
    327     refs->decWeak(id);
    328 }
    329 
    330 void RefBase::forceIncStrong(const void* id) const
    331 {
    332     weakref_impl* const refs = mRefs;
    333     refs->addWeakRef(id);
    334     refs->incWeak(id);
    335 
    336     refs->addStrongRef(id);
    337     const int32_t c = android_atomic_inc(&refs->mStrong);
    338     LOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
    339                refs);
    340 #if PRINT_REFS
    341     LOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
    342 #endif
    343 
    344     switch (c) {
    345     case INITIAL_STRONG_VALUE:
    346         android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    347         // fall through...
    348     case 0:
    349         const_cast<RefBase*>(this)->onFirstRef();
    350     }
    351 }
    352 
    353 int32_t RefBase::getStrongCount() const
    354 {
    355     return mRefs->mStrong;
    356 }
    357 
    358 void RefBase::setDestroyer(RefBase::Destroyer* destroyer) {
    359     mRefs->mDestroyer = destroyer;
    360 }
    361 
    362 RefBase* RefBase::weakref_type::refBase() const
    363 {
    364     return static_cast<const weakref_impl*>(this)->mBase;
    365 }
    366 
    367 void RefBase::weakref_type::incWeak(const void* id)
    368 {
    369     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    370     impl->addWeakRef(id);
    371     const int32_t c = android_atomic_inc(&impl->mWeak);
    372     LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
    373 }
    374 
    375 void RefBase::weakref_type::decWeak(const void* id)
    376 {
    377     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    378     impl->removeWeakRef(id);
    379     const int32_t c = android_atomic_dec(&impl->mWeak);
    380     LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    381     if (c != 1) return;
    382 
    383     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
    384         if (impl->mStrong == INITIAL_STRONG_VALUE) {
    385             if (impl->mBase) {
    386                 if (impl->mDestroyer) {
    387                     impl->mDestroyer->destroy(impl->mBase);
    388                 } else {
    389                     delete impl->mBase;
    390                 }
    391             }
    392         } else {
    393             // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
    394             delete impl;
    395         }
    396     } else {
    397         impl->mBase->onLastWeakRef(id);
    398         if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
    399             if (impl->mBase) {
    400                 if (impl->mDestroyer) {
    401                     impl->mDestroyer->destroy(impl->mBase);
    402                 } else {
    403                     delete impl->mBase;
    404                 }
    405             }
    406         }
    407     }
    408 }
    409 
    410 bool RefBase::weakref_type::attemptIncStrong(const void* id)
    411 {
    412     incWeak(id);
    413 
    414     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    415 
    416     int32_t curCount = impl->mStrong;
    417     LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
    418                this);
    419     while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
    420         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
    421             break;
    422         }
    423         curCount = impl->mStrong;
    424     }
    425 
    426     if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
    427         bool allow;
    428         if (curCount == INITIAL_STRONG_VALUE) {
    429             // Attempting to acquire first strong reference...  this is allowed
    430             // if the object does NOT have a longer lifetime (meaning the
    431             // implementation doesn't need to see this), or if the implementation
    432             // allows it to happen.
    433             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
    434                   || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
    435         } else {
    436             // Attempting to revive the object...  this is allowed
    437             // if the object DOES have a longer lifetime (so we can safely
    438             // call the object with only a weak ref) and the implementation
    439             // allows it to happen.
    440             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
    441                   && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
    442         }
    443         if (!allow) {
    444             decWeak(id);
    445             return false;
    446         }
    447         curCount = android_atomic_inc(&impl->mStrong);
    448 
    449         // If the strong reference count has already been incremented by
    450         // someone else, the implementor of onIncStrongAttempted() is holding
    451         // an unneeded reference.  So call onLastStrongRef() here to remove it.
    452         // (No, this is not pretty.)  Note that we MUST NOT do this if we
    453         // are in fact acquiring the first reference.
    454         if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
    455             impl->mBase->onLastStrongRef(id);
    456         }
    457     }
    458 
    459     impl->addWeakRef(id);
    460     impl->addStrongRef(id);
    461 
    462 #if PRINT_REFS
    463     LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
    464 #endif
    465 
    466     if (curCount == INITIAL_STRONG_VALUE) {
    467         android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
    468         impl->mBase->onFirstRef();
    469     }
    470 
    471     return true;
    472 }
    473 
    474 bool RefBase::weakref_type::attemptIncWeak(const void* id)
    475 {
    476     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    477 
    478     int32_t curCount = impl->mWeak;
    479     LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
    480                this);
    481     while (curCount > 0) {
    482         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
    483             break;
    484         }
    485         curCount = impl->mWeak;
    486     }
    487 
    488     if (curCount > 0) {
    489         impl->addWeakRef(id);
    490     }
    491 
    492     return curCount > 0;
    493 }
    494 
    495 int32_t RefBase::weakref_type::getWeakCount() const
    496 {
    497     return static_cast<const weakref_impl*>(this)->mWeak;
    498 }
    499 
    500 void RefBase::weakref_type::printRefs() const
    501 {
    502     static_cast<const weakref_impl*>(this)->printRefs();
    503 }
    504 
    505 void RefBase::weakref_type::trackMe(bool enable, bool retain)
    506 {
    507     static_cast<const weakref_impl*>(this)->trackMe(enable, retain);
    508 }
    509 
    510 RefBase::weakref_type* RefBase::createWeak(const void* id) const
    511 {
    512     mRefs->incWeak(id);
    513     return mRefs;
    514 }
    515 
    516 RefBase::weakref_type* RefBase::getWeakRefs() const
    517 {
    518     return mRefs;
    519 }
    520 
    521 RefBase::RefBase()
    522     : mRefs(new weakref_impl(this))
    523 {
    524 //    LOGV("Creating refs %p with RefBase %p\n", mRefs, this);
    525 }
    526 
    527 RefBase::~RefBase()
    528 {
    529     if ((mRefs->mFlags & OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK) {
    530         if (mRefs->mWeak == 0) {
    531             delete mRefs;
    532         }
    533     }
    534 }
    535 
    536 void RefBase::extendObjectLifetime(int32_t mode)
    537 {
    538     android_atomic_or(mode, &mRefs->mFlags);
    539 }
    540 
    541 void RefBase::onFirstRef()
    542 {
    543 }
    544 
    545 void RefBase::onLastStrongRef(const void* /*id*/)
    546 {
    547 }
    548 
    549 bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
    550 {
    551     return (flags&FIRST_INC_STRONG) ? true : false;
    552 }
    553 
    554 void RefBase::onLastWeakRef(const void* /*id*/)
    555 {
    556 }
    557 
    558 }; // namespace android
    559