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