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.cpp213
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;
}