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