1 /*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "rsObjectBase.h"
18 #include "rsContext.h"
19
20 using namespace android;
21 using namespace android::renderscript;
22
ObjectBase(Context * rsc)23 ObjectBase::ObjectBase(Context *rsc)
24 {
25 mUserRefCount = 0;
26 mSysRefCount = 0;
27 mName = NULL;
28 mRSC = NULL;
29 mNext = NULL;
30 mPrev = NULL;
31 mAllocFile = __FILE__;
32 mAllocLine = __LINE__;
33 setContext(rsc);
34 }
35
~ObjectBase()36 ObjectBase::~ObjectBase()
37 {
38 //LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount);
39 rsAssert(!mUserRefCount);
40 rsAssert(!mSysRefCount);
41 remove();
42 delete[] mName;
43 }
44
dumpLOGV(const char * op) const45 void ObjectBase::dumpLOGV(const char *op) const
46 {
47 if (mName) {
48 LOGV("%s RSobj %p, name %s, refs %i,%i from %s,%i links %p,%p,%p",
49 op, this, mName, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC);
50 } else {
51 LOGV("%s RSobj %p, no-name, refs %i,%i from %s,%i links %p,%p,%p",
52 op, this, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC);
53 }
54 }
55
setContext(Context * rsc)56 void ObjectBase::setContext(Context *rsc)
57 {
58 if (mRSC) {
59 remove();
60 }
61 mRSC = rsc;
62 if (rsc) {
63 add();
64 }
65 }
66
incUserRef() const67 void ObjectBase::incUserRef() const
68 {
69 mUserRefCount ++;
70 //LOGV("ObjectBase %p inc ref %i", this, mRefCount);
71 }
72
incSysRef() const73 void ObjectBase::incSysRef() const
74 {
75 mSysRefCount ++;
76 //LOGV("ObjectBase %p inc ref %i", this, mRefCount);
77 }
78
checkDelete() const79 bool ObjectBase::checkDelete() const
80 {
81 if (!(mSysRefCount | mUserRefCount)) {
82 if (mRSC && mRSC->props.mLogObjects) {
83 dumpLOGV("checkDelete");
84 }
85 delete this;
86 return true;
87 }
88 return false;
89 }
90
decUserRef() const91 bool ObjectBase::decUserRef() const
92 {
93 rsAssert(mUserRefCount > 0);
94 mUserRefCount --;
95 //dumpObj("decUserRef");
96 return checkDelete();
97 }
98
zeroUserRef() const99 bool ObjectBase::zeroUserRef() const
100 {
101 mUserRefCount = 0;
102 //dumpObj("zeroUserRef");
103 return checkDelete();
104 }
105
decSysRef() const106 bool ObjectBase::decSysRef() const
107 {
108 rsAssert(mSysRefCount > 0);
109 mSysRefCount --;
110 //dumpObj("decSysRef");
111 return checkDelete();
112 }
113
setName(const char * name)114 void ObjectBase::setName(const char *name)
115 {
116 setName(name, strlen(name));
117 }
118
setName(const char * name,uint32_t len)119 void ObjectBase::setName(const char *name, uint32_t len)
120 {
121 delete mName;
122 mName = NULL;
123 if (name) {
124 mName = new char[len + 1];
125 memcpy(mName, name, len);
126 mName[len] = 0;
127 }
128 }
129
add() const130 void ObjectBase::add() const
131 {
132 rsAssert(!mNext);
133 rsAssert(!mPrev);
134 //LOGV("calling add rsc %p", mRSC);
135 mNext = mRSC->mObjHead;
136 if (mRSC->mObjHead) {
137 mRSC->mObjHead->mPrev = this;
138 }
139 mRSC->mObjHead = this;
140 }
141
remove() const142 void ObjectBase::remove() const
143 {
144 //LOGV("calling remove rsc %p", mRSC);
145 if (!mRSC) {
146 rsAssert(!mPrev);
147 rsAssert(!mNext);
148 return;
149 }
150 if (mRSC->mObjHead == this) {
151 mRSC->mObjHead = mNext;
152 }
153 if (mPrev) {
154 mPrev->mNext = mNext;
155 }
156 if (mNext) {
157 mNext->mPrev = mPrev;
158 }
159 mPrev = NULL;
160 mNext = NULL;
161 }
162
zeroAllUserRef(Context * rsc)163 void ObjectBase::zeroAllUserRef(Context *rsc)
164 {
165 if (rsc->props.mLogObjects) {
166 LOGV("Forcing release of all outstanding user refs.");
167 }
168
169 // This operation can be slow, only to be called during context cleanup.
170 const ObjectBase * o = rsc->mObjHead;
171 while (o) {
172 //LOGE("o %p", o);
173 if (o->zeroUserRef()) {
174 // deleted the object and possibly others, restart from head.
175 o = rsc->mObjHead;
176 //LOGE("o head %p", o);
177 } else {
178 o = o->mNext;
179 //LOGE("o next %p", o);
180 }
181 }
182
183 if (rsc->props.mLogObjects) {
184 LOGV("Objects remaining.");
185 dumpAll(rsc);
186 }
187 }
188
dumpAll(Context * rsc)189 void ObjectBase::dumpAll(Context *rsc)
190 {
191 LOGV("Dumping all objects");
192 const ObjectBase * o = rsc->mObjHead;
193 while (o) {
194 LOGV(" Object %p", o);
195 o->dumpLOGV(" ");
196 o = o->mNext;
197 }
198 }
199
200