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