summaryrefslogtreecommitdiffstats
path: root/libs/rs/rsObjectBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/rs/rsObjectBase.cpp')
-rw-r--r--libs/rs/rsObjectBase.cpp170
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;
}