rsObjectBase.cpp revision f2649a961db2995e9e24a6c98f8a419f1496c1b7
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 20using namespace android; 21using namespace android::renderscript; 22 23ObjectBase::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 36ObjectBase::~ObjectBase() 37{ 38 //LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount); 39 rsAssert(!mUserRefCount); 40 rsAssert(!mSysRefCount); 41 remove(); 42} 43 44void ObjectBase::dumpObj(const char *op) const 45{ 46 if (mName) { 47 LOGV("%s RSobj %p, name %s, refs %i,%i from %s,%i links %p,%p,%p", 48 op, this, mName, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); 49 } else { 50 LOGV("%s RSobj %p, no-name, refs %i,%i from %s,%i links %p,%p,%p", 51 op, this, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); 52 } 53} 54 55void ObjectBase::setContext(Context *rsc) 56{ 57 if (mRSC) { 58 remove(); 59 } 60 mRSC = rsc; 61 if (rsc) { 62 add(); 63 } 64} 65 66void ObjectBase::incUserRef() const 67{ 68 mUserRefCount ++; 69 //LOGV("ObjectBase %p inc ref %i", this, mRefCount); 70} 71 72void ObjectBase::incSysRef() const 73{ 74 mSysRefCount ++; 75 //LOGV("ObjectBase %p inc ref %i", this, mRefCount); 76} 77 78bool ObjectBase::checkDelete() const 79{ 80 if (!(mSysRefCount | mUserRefCount)) { 81 if (mRSC && mRSC->props.mLogObjects) { 82 dumpObj("checkDelete"); 83 } 84 delete this; 85 return true; 86 } 87 return false; 88} 89 90bool ObjectBase::decUserRef() const 91{ 92 rsAssert(mUserRefCount > 0); 93 mUserRefCount --; 94 //dumpObj("decUserRef"); 95 return checkDelete(); 96} 97 98bool ObjectBase::zeroUserRef() const 99{ 100 mUserRefCount = 0; 101 //dumpObj("zeroUserRef"); 102 return checkDelete(); 103} 104 105bool ObjectBase::decSysRef() const 106{ 107 rsAssert(mSysRefCount > 0); 108 mSysRefCount --; 109 //dumpObj("decSysRef"); 110 return checkDelete(); 111} 112 113void ObjectBase::setName(const char *name) 114{ 115 delete mName; 116 mName = NULL; 117 if (name) { 118 mName = new char[strlen(name) +1]; 119 strcpy(mName, name); 120 } 121} 122 123void ObjectBase::setName(const char *name, uint32_t len) 124{ 125 delete mName; 126 mName = NULL; 127 if (name) { 128 mName = new char[len + 1]; 129 memcpy(mName, name, len); 130 mName[len] = 0; 131 } 132} 133 134void ObjectBase::add() const 135{ 136 rsAssert(!mNext); 137 rsAssert(!mPrev); 138 //LOGV("calling add rsc %p", mRSC); 139 mNext = mRSC->mObjHead; 140 if (mRSC->mObjHead) { 141 mRSC->mObjHead->mPrev = this; 142 } 143 mRSC->mObjHead = this; 144} 145 146void ObjectBase::remove() const 147{ 148 //LOGV("calling remove rsc %p", mRSC); 149 if (!mRSC) { 150 rsAssert(!mPrev); 151 rsAssert(!mNext); 152 return; 153 } 154 if (mRSC->mObjHead == this) { 155 mRSC->mObjHead = mNext; 156 } 157 if (mPrev) { 158 mPrev->mNext = mNext; 159 } 160 if (mNext) { 161 mNext->mPrev = mPrev; 162 } 163 mPrev = NULL; 164 mNext = NULL; 165} 166 167void ObjectBase::zeroAllUserRef(Context *rsc) 168{ 169 if (rsc->props.mLogObjects) { 170 LOGV("Forcing release of all outstanding user refs."); 171 } 172 173 // This operation can be slow, only to be called during context cleanup. 174 const ObjectBase * o = rsc->mObjHead; 175 while (o) { 176 //LOGE("o %p", o); 177 if (o->zeroUserRef()) { 178 // deleted the object and possibly others, restart from head. 179 o = rsc->mObjHead; 180 //LOGE("o head %p", o); 181 } else { 182 o = o->mNext; 183 //LOGE("o next %p", o); 184 } 185 } 186 187 if (rsc->props.mLogObjects) { 188 LOGV("Objects remaining."); 189 o = rsc->mObjHead; 190 while (o) { 191 o->dumpObj(" "); 192 o = o->mNext; 193 } 194 } 195} 196 197