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