OSDN Git Service

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