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 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 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 45 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 56 void ObjectBase::setContext(Context *rsc) 57 { 58 if (mRSC) { 59 remove(); 60 } 61 mRSC = rsc; 62 if (rsc) { 63 add(); 64 } 65 } 66 67 void ObjectBase::incUserRef() const 68 { 69 mUserRefCount ++; 70 //LOGV("ObjectBase %p inc ref %i", this, mRefCount); 71 } 72 73 void ObjectBase::incSysRef() const 74 { 75 mSysRefCount ++; 76 //LOGV("ObjectBase %p inc ref %i", this, mRefCount); 77 } 78 79 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 91 bool ObjectBase::decUserRef() const 92 { 93 rsAssert(mUserRefCount > 0); 94 mUserRefCount --; 95 //dumpObj("decUserRef"); 96 return checkDelete(); 97 } 98 99 bool ObjectBase::zeroUserRef() const 100 { 101 mUserRefCount = 0; 102 //dumpObj("zeroUserRef"); 103 return checkDelete(); 104 } 105 106 bool ObjectBase::decSysRef() const 107 { 108 rsAssert(mSysRefCount > 0); 109 mSysRefCount --; 110 //dumpObj("decSysRef"); 111 return checkDelete(); 112 } 113 114 void ObjectBase::setName(const char *name) 115 { 116 setName(name, strlen(name)); 117 } 118 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 130 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 142 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 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 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