Async type creation.
Change-Id: I4d98446fabbf7e8a98c97f85b573a58c8a0c58c2
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 124d5e6..e4b07c4 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -25,16 +25,20 @@
using namespace android;
using namespace android::renderscript;
+pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER;
+
ObjectBase::ObjectBase(Context *rsc)
{
mUserRefCount = 0;
mSysRefCount = 0;
- mRSC = NULL;
+ mRSC = rsc;
mNext = NULL;
mPrev = NULL;
mAllocFile = __FILE__;
mAllocLine = __LINE__;
- setContext(rsc);
+
+ rsAssert(rsc);
+ add();
}
ObjectBase::~ObjectBase()
@@ -56,24 +60,19 @@
}
}
-void ObjectBase::setContext(Context *rsc)
-{
- if (mRSC) {
- remove();
- }
- rsAssert(rsc);
- mRSC = rsc;
- if (rsc) {
- add();
- }
-}
-
void ObjectBase::incUserRef() const
{
- mUserRefCount ++;
+ lockUserRef();
+ mUserRefCount++;
+ unlockUserRef();
//LOGV("ObjectBase %p inc ref %i", this, mUserRefCount);
}
+void ObjectBase::prelockedIncUserRef() const
+{
+ mUserRefCount++;
+}
+
void ObjectBase::incSysRef() const
{
mSysRefCount ++;
@@ -83,10 +82,20 @@
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;
@@ -94,17 +103,25 @@
bool ObjectBase::decUserRef() const
{
+ lockUserRef();
rsAssert(mUserRefCount > 0);
- mUserRefCount --;
//dumpLOGV("decUserRef");
- return checkDelete();
+ 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;
//dumpLOGV("zeroUserRef");
- return checkDelete();
+ unlockUserRef();
+ bool ret = checkDelete();
+ return ret;
}
bool ObjectBase::decSysRef() const
@@ -125,8 +142,20 @@
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);
@@ -135,16 +164,22 @@
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;
}
@@ -160,6 +195,8 @@
void ObjectBase::zeroAllUserRef(Context *rsc)
{
+ lockUserRef();
+
if (rsc->props.mLogObjects) {
LOGV("Forcing release of all outstanding user refs.");
}
@@ -182,10 +219,14 @@
LOGV("Objects remaining.");
dumpAll(rsc);
}
+
+ unlockUserRef();
}
void ObjectBase::dumpAll(Context *rsc)
{
+ lockUserRef();
+
LOGV("Dumping all objects");
const ObjectBase * o = rsc->mObjHead;
while (o) {
@@ -193,17 +234,23 @@
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;
}