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