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