diff options
Diffstat (limited to 'libs/rs/rsObjectBase.cpp')
-rw-r--r-- | libs/rs/rsObjectBase.cpp | 121 |
1 files changed, 89 insertions, 32 deletions
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index 677413e..e4b07c4 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -15,22 +15,30 @@ */ #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); + + rsAssert(rsc); + add(); } ObjectBase::~ObjectBase() @@ -39,50 +47,55 @@ ObjectBase::~ObjectBase() rsAssert(!mUserRefCount); rsAssert(!mSysRefCount); remove(); - delete[] mName; } void ObjectBase::dumpLOGV(const char *op) const { - if (mName) { + if (mName.size()) { 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); + op, this, mName.string(), mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, 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); } } -void ObjectBase::setContext(Context *rsc) +void ObjectBase::incUserRef() const { - if (mRSC) { - remove(); - } - mRSC = rsc; - if (rsc) { - add(); - } + lockUserRef(); + mUserRefCount++; + unlockUserRef(); + //LOGV("ObjectBase %p inc ref %i", this, mUserRefCount); } -void ObjectBase::incUserRef() const +void ObjectBase::prelockedIncUserRef() const { - mUserRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); + mUserRefCount++; } void ObjectBase::incSysRef() const { mSysRefCount ++; - //LOGV("ObjectBase %p inc ref %i", this, mRefCount); + //LOGV("ObjectBase %p inc ref %i", this, mSysRefCount); } bool ObjectBase::checkDelete() const { if (!(mSysRefCount | mUserRefCount)) { + lockUserRef(); + + // Recheck the user ref count since it can be incremented from other threads. + if (mUserRefCount) { + unlockUserRef(); + return false; + } + if (mRSC && mRSC->props.mLogObjects) { dumpLOGV("checkDelete"); } delete this; + + unlockUserRef(); return true; } return false; @@ -90,45 +103,59 @@ bool ObjectBase::checkDelete() const bool ObjectBase::decUserRef() const { + lockUserRef(); rsAssert(mUserRefCount > 0); - mUserRefCount --; - //dumpObj("decUserRef"); - return checkDelete(); + //dumpLOGV("decUserRef"); + mUserRefCount--; + unlockUserRef(); + bool ret = checkDelete(); + return ret; } bool ObjectBase::zeroUserRef() const { + lockUserRef(); + // This can only happen during cleanup and is therefore + // thread safe. mUserRefCount = 0; - //dumpObj("zeroUserRef"); - return checkDelete(); + //dumpLOGV("zeroUserRef"); + unlockUserRef(); + bool ret = checkDelete(); + return ret; } bool ObjectBase::decSysRef() const { rsAssert(mSysRefCount > 0); mSysRefCount --; - //dumpObj("decSysRef"); + //dumpLOGV("decSysRef"); return checkDelete(); } 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::lockUserRef() +{ + pthread_mutex_lock(&gObjectInitMutex); +} + +void ObjectBase::unlockUserRef() +{ + pthread_mutex_unlock(&gObjectInitMutex); } void ObjectBase::add() const { + pthread_mutex_lock(&gObjectInitMutex); + rsAssert(!mNext); rsAssert(!mPrev); //LOGV("calling add rsc %p", mRSC); @@ -137,16 +164,22 @@ void ObjectBase::add() const mRSC->mObjHead->mPrev = this; } mRSC->mObjHead = this; + + pthread_mutex_unlock(&gObjectInitMutex); } void ObjectBase::remove() const { + // Should be within gObjectInitMutex lock + // lock will be from checkDelete a few levels up in the stack. + //LOGV("calling remove rsc %p", mRSC); if (!mRSC) { rsAssert(!mPrev); rsAssert(!mNext); return; } + if (mRSC->mObjHead == this) { mRSC->mObjHead = mNext; } @@ -162,6 +195,8 @@ void ObjectBase::remove() const void ObjectBase::zeroAllUserRef(Context *rsc) { + lockUserRef(); + if (rsc->props.mLogObjects) { LOGV("Forcing release of all outstanding user refs."); } @@ -184,10 +219,14 @@ void ObjectBase::zeroAllUserRef(Context *rsc) LOGV("Objects remaining."); dumpAll(rsc); } + + unlockUserRef(); } void ObjectBase::dumpAll(Context *rsc) { + lockUserRef(); + LOGV("Dumping all objects"); const ObjectBase * o = rsc->mObjHead; while (o) { @@ -195,5 +234,23 @@ void ObjectBase::dumpAll(Context *rsc) o->dumpLOGV(" "); o = o->mNext; } + + unlockUserRef(); +} + +bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) +{ + lockUserRef(); + + const ObjectBase * o = rsc->mObjHead; + while (o) { + if (o == obj) { + unlockUserRef(); + return true; + } + o = o->mNext; + } + unlockUserRef(); + return false; } |