diff options
Diffstat (limited to 'libs/rs/rsObjectBase.cpp')
| -rw-r--r-- | libs/rs/rsObjectBase.cpp | 170 |
1 files changed, 119 insertions, 51 deletions
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index 677413e..724172e 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -15,120 +15,165 @@ */ #include "rsObjectBase.h" + +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" +#else +#include "rsContextHostStub.h" +#endif + using namespace android; using namespace android::renderscript; +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() { //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); + 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) +void ObjectBase::incUserRef() const { - if (mRSC) { - remove(); - } - mRSC = rsc; - if (rsc) { - add(); - } + android_atomic_inc(&mUserRefCount); + //LOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incUserRef() const +void ObjectBase::incSysRef() const { - mUserRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); + android_atomic_inc(&mSysRefCount); + //LOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount); } -void ObjectBase::incSysRef() const +void ObjectBase::preDestroy() const { - mSysRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); } -bool ObjectBase::checkDelete() const +bool ObjectBase::checkDelete(const ObjectBase *ref) { - if (!(mSysRefCount | mUserRefCount)) { - if (mRSC && mRSC->props.mLogObjects) { - dumpLOGV("checkDelete"); - } - delete this; - return true; + 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 { + //LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount); rsAssert(mUserRefCount > 0); - mUserRefCount --; - //dumpObj("decUserRef"); - return checkDelete(); + 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(); + //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 { + //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)); + 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; - } + mName.setTo(name, len); +} + +void ObjectBase::asyncLock() +{ + pthread_mutex_lock(&gObjectInitMutex); +} + +void ObjectBase::asyncUnlock() +{ + pthread_mutex_unlock(&gObjectInitMutex); } void ObjectBase::add() const { + asyncLock(); + rsAssert(!mNext); rsAssert(!mPrev); //LOGV("calling add rsc %p", mRSC); @@ -137,6 +182,8 @@ void ObjectBase::add() const mRSC->mObjHead->mPrev = this; } mRSC->mObjHead = this; + + asyncUnlock(); } void ObjectBase::remove() const @@ -147,6 +194,7 @@ void ObjectBase::remove() const rsAssert(!mNext); return; } + if (mRSC->mObjHead == this) { mRSC->mObjHead = mNext; } @@ -188,6 +236,8 @@ void ObjectBase::zeroAllUserRef(Context *rsc) void ObjectBase::dumpAll(Context *rsc) { + asyncLock(); + LOGV("Dumping all objects"); const ObjectBase * o = rsc->mObjHead; while (o) { @@ -195,5 +245,23 @@ 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; } |
