diff options
Diffstat (limited to 'libs/rs/rsObjectBase.cpp')
-rw-r--r-- | libs/rs/rsObjectBase.cpp | 213 |
1 files changed, 134 insertions, 79 deletions
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index 677413e..aec2f67 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -15,120 +15,156 @@ */ #include "rsObjectBase.h" + +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif + using namespace android; using namespace android::renderscript; -ObjectBase::ObjectBase(Context *rsc) -{ +pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER; + +ObjectBase::ObjectBase(Context *rsc) { mUserRefCount = 0; mSysRefCount = 0; - mName = NULL; - mRSC = NULL; + mRSC = rsc; mNext = NULL; mPrev = NULL; - mAllocFile = __FILE__; - mAllocLine = __LINE__; - setContext(rsc); + +#if RS_OBJECT_DEBUG + mStack.update(2); +#endif + + rsAssert(rsc); + add(); + //LOGV("ObjectBase %p con", this); } -ObjectBase::~ObjectBase() -{ +ObjectBase::~ObjectBase() { //LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount); +#if RS_OBJECT_DEBUG + mStack.dump(); +#endif + + if (mPrev || mNext) { + // While the normal practice is to call remove before we call + // delete. Its possible for objects without a re-use list + // for avoiding duplication to be created on the stack. In those + // cases we need to remove ourself here. + asyncLock(); + remove(); + asyncUnlock(); + } + rsAssert(!mUserRefCount); rsAssert(!mSysRefCount); - remove(); - delete[] mName; } -void ObjectBase::dumpLOGV(const char *op) const -{ - if (mName) { - LOGV("%s RSobj %p, name %s, refs %i,%i from %s,%i links %p,%p,%p", - op, this, mName, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); +void ObjectBase::dumpLOGV(const char *op) const { + if (mName.size()) { + LOGV("%s RSobj %p, name %s, refs %i,%i links %p,%p,%p", + op, this, mName.string(), mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); } else { - LOGV("%s RSobj %p, no-name, refs %i,%i from %s,%i links %p,%p,%p", - op, this, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC); + LOGV("%s RSobj %p, no-name, refs %i,%i links %p,%p,%p", + op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); } } -void ObjectBase::setContext(Context *rsc) -{ - if (mRSC) { - remove(); - } - mRSC = rsc; - if (rsc) { - add(); - } +void ObjectBase::incUserRef() const { + android_atomic_inc(&mUserRefCount); + //LOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incUserRef() const -{ - mUserRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); +void ObjectBase::incSysRef() const { + android_atomic_inc(&mSysRefCount); + //LOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incSysRef() const -{ - mSysRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); +void ObjectBase::preDestroy() const { } -bool ObjectBase::checkDelete() const -{ - if (!(mSysRefCount | mUserRefCount)) { - if (mRSC && mRSC->props.mLogObjects) { - dumpLOGV("checkDelete"); - } - delete this; - return true; +bool ObjectBase::checkDelete(const ObjectBase *ref) { + if (!ref) { + return false; } - return false; + + asyncLock(); + // This lock protects us against the non-RS threads changing + // the ref counts. At this point we should be the only thread + // working on them. + if (ref->mUserRefCount || ref->mSysRefCount) { + asyncUnlock(); + return false; + } + + ref->remove(); + // At this point we can unlock because there should be no possible way + // for another thread to reference this object. + ref->preDestroy(); + asyncUnlock(); + delete ref; + return true; } -bool ObjectBase::decUserRef() const -{ +bool ObjectBase::decUserRef() const { rsAssert(mUserRefCount > 0); - mUserRefCount --; - //dumpObj("decUserRef"); - return checkDelete(); +#if RS_OBJECT_DEBUG + LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount); + if (mUserRefCount <= 0) { + mStack.dump(); + } +#endif + + + if ((android_atomic_dec(&mUserRefCount) <= 1) && + (android_atomic_acquire_load(&mSysRefCount) <= 0)) { + return checkDelete(this); + } + return false; } -bool ObjectBase::zeroUserRef() const -{ - mUserRefCount = 0; - //dumpObj("zeroUserRef"); - return checkDelete(); +bool ObjectBase::zeroUserRef() const { + //LOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount); + android_atomic_acquire_store(0, &mUserRefCount); + if (android_atomic_acquire_load(&mSysRefCount) <= 0) { + return checkDelete(this); + } + return false; } -bool ObjectBase::decSysRef() const -{ +bool ObjectBase::decSysRef() const { + //LOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount); rsAssert(mSysRefCount > 0); - mSysRefCount --; - //dumpObj("decSysRef"); - return checkDelete(); + if ((android_atomic_dec(&mSysRefCount) <= 1) && + (android_atomic_acquire_load(&mUserRefCount) <= 0)) { + return checkDelete(this); + } + return false; } -void ObjectBase::setName(const char *name) -{ - setName(name, strlen(name)); +void ObjectBase::setName(const char *name) { + mName.setTo(name); } -void ObjectBase::setName(const char *name, uint32_t len) -{ - delete mName; - mName = NULL; - if (name) { - mName = new char[len + 1]; - memcpy(mName, name, len); - mName[len] = 0; - } +void ObjectBase::setName(const char *name, uint32_t len) { + mName.setTo(name, len); +} + +void ObjectBase::asyncLock() { + pthread_mutex_lock(&gObjectInitMutex); +} + +void ObjectBase::asyncUnlock() { + pthread_mutex_unlock(&gObjectInitMutex); } -void ObjectBase::add() const -{ +void ObjectBase::add() const { + asyncLock(); + rsAssert(!mNext); rsAssert(!mPrev); //LOGV("calling add rsc %p", mRSC); @@ -137,16 +173,18 @@ void ObjectBase::add() const mRSC->mObjHead->mPrev = this; } mRSC->mObjHead = this; + + asyncUnlock(); } -void ObjectBase::remove() const -{ +void ObjectBase::remove() const { //LOGV("calling remove rsc %p", mRSC); if (!mRSC) { rsAssert(!mPrev); rsAssert(!mNext); return; } + if (mRSC->mObjHead == this) { mRSC->mObjHead = mNext; } @@ -160,8 +198,7 @@ void ObjectBase::remove() const mNext = NULL; } -void ObjectBase::zeroAllUserRef(Context *rsc) -{ +void ObjectBase::zeroAllUserRef(Context *rsc) { if (rsc->props.mLogObjects) { LOGV("Forcing release of all outstanding user refs."); } @@ -186,8 +223,9 @@ void ObjectBase::zeroAllUserRef(Context *rsc) } } -void ObjectBase::dumpAll(Context *rsc) -{ +void ObjectBase::dumpAll(Context *rsc) { + asyncLock(); + LOGV("Dumping all objects"); const ObjectBase * o = rsc->mObjHead; while (o) { @@ -195,5 +233,22 @@ void ObjectBase::dumpAll(Context *rsc) o->dumpLOGV(" "); o = o->mNext; } + + asyncUnlock(); +} + +bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) { + asyncLock(); + + const ObjectBase * o = rsc->mObjHead; + while (o) { + if (o == obj) { + asyncUnlock(); + return true; + } + o = o->mNext; + } + asyncUnlock(); + return false; } |