Implement OOB destroy method that can be called from the java finalizer removing the need to explicitly destroy objects.
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index eaeb401..c25f16a 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -60,8 +60,13 @@
protected void finalize() throws Throwable
{
if (!mDestroyed) {
+ if(mID != 0) {
+ mRS.nObjDestroyOOB(mID);
+ }
+ mID = 0;
+ mDestroyed = true;
Log.v(RenderScript.LOG_TAG,
- getClass() + " finalized without having released the RS reference.");
+ getClass() + " auto finalizing object without having released the RS reference.");
}
super.finalize();
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 08418c6..fca1c7a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -75,6 +75,7 @@
native void nAssignName(int obj, byte[] name);
native void nObjDestroy(int id);
+ native void nObjDestroyOOB(int id);
native int nFileOpen(byte[] name);
native void nElementBegin();
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 2d48165..001ecd0 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -86,6 +86,15 @@
rsObjDestroy(con, (void *)obj);
}
+static void
+nObjDestroyOOB(JNIEnv *_env, jobject _this, jint obj)
+{
+ // This function only differs from nObjDestroy in that it calls the
+ // special Out Of Band version of ObjDestroy which is thread safe.
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ LOG_API("nObjDestroyOOB, con(%p) obj(%p)", con, (void *)obj);
+ rsObjDestroyOOB(con, (void *)obj);
+}
static jint
nFileOpen(JNIEnv *_env, jobject _this, jbyteArray str)
@@ -1217,6 +1226,7 @@
{"nContextDestroy", "(I)V", (void*)nContextDestroy },
{"nAssignName", "(I[B)V", (void*)nAssignName },
{"nObjDestroy", "(I)V", (void*)nObjDestroy },
+{"nObjDestroyOOB", "(I)V", (void*)nObjDestroyOOB },
{"nFileOpen", "([B)I", (void*)nFileOpen },
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index d7d572e..e4cf00f 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -51,6 +51,7 @@
RsContext rsContextCreate(RsDevice, void *, uint32_t version);
void rsContextDestroy(RsContext);
+void rsObjDestroyOOB(RsContext, void *);
#define RS_MAX_TEXTURE 2
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index da9eda8..6d400c5 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -67,8 +67,6 @@
private RenderScript mRS;
private Allocation mIntAlloc;
- private Allocation mPartAlloc;
- private Script mScript;
private SimpleMesh mSM;
private SomeData mSD;
private Type mSDType;
@@ -94,9 +92,9 @@
mSM = smb.create();
mSM.setName("PartMesh");
- mPartAlloc = mSM.createVertexAllocation(vtxSlot);
- mPartAlloc.setName("PartBuffer");
- mSM.bindVertexAllocation(mPartAlloc, 0);
+ Allocation partAlloc = mSM.createVertexAllocation(vtxSlot);
+ partAlloc.setName("PartBuffer");
+ mSM.bindVertexAllocation(partAlloc, 0);
// All setup of named objects should be done by this point
// because we are about to compile the script.
@@ -104,12 +102,12 @@
sb.setScript(mRes, R.raw.fountain);
sb.setRoot(true);
sb.setType(mSDType, "Control", 0);
- mScript = sb.create();
- mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ Script script = sb.create();
+ script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- mScript.bindAllocation(mIntAlloc, 0);
- mScript.bindAllocation(mPartAlloc, 1);
- mRS.contextBindRootScript(mScript);
+ script.bindAllocation(mIntAlloc, 0);
+ script.bindAllocation(partAlloc, 1);
+ mRS.contextBindRootScript(script);
}
}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index bc0cf12..7bfa81e 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -170,12 +170,14 @@
mDraw = rsc->runRootScript();
eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
}
+ rsc->objDestroyOOBRun();
}
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
eglTerminate(rsc->mDisplay);
+ rsc->objDestroyOOBRun();
return NULL;
}
@@ -210,6 +212,8 @@
mWndSurface = sur;
+ objDestroyOOBInit();
+
LOGV("RS Launching thread");
status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
if (status) {
@@ -229,11 +233,14 @@
void *res;
int status = pthread_join(mThreadId, &res);
+ objDestroyOOBRun();
if (mDev) {
mDev->removeContext(this);
pthread_key_delete(gThreadTLSKey);
}
+
+ objDestroyOOBDestroy();
}
void Context::swapBuffers()
@@ -345,6 +352,62 @@
}
}
+bool Context::objDestroyOOBInit()
+{
+ int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBInit mutex init failure");
+ return false;
+ }
+ return true;
+}
+
+void Context::objDestroyOOBRun()
+{
+ if (mObjDestroy.mNeedToEmpty) {
+ int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+ return;
+ }
+
+ for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
+ mObjDestroy.mDestroyList[ct]->decRef();
+ }
+ mObjDestroy.mDestroyList.clear();
+ mObjDestroy.mNeedToEmpty = false;
+
+ status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+ }
+ }
+}
+
+void Context::objDestroyOOBDestroy()
+{
+ rsAssert(!mObjDestroy.mNeedToEmpty);
+ pthread_mutex_destroy(&mObjDestroy.mMutex);
+}
+
+void Context::objDestroyAdd(ObjectBase *obj)
+{
+ int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+ return;
+ }
+
+ mObjDestroy.mNeedToEmpty = true;
+ mObjDestroy.mDestroyList.add(obj);
+
+ status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+ }
+}
+
+
///////////////////////////////////////////////////////////////////////////////////////////
//
@@ -429,3 +492,9 @@
delete rsc;
}
+void rsObjDestroyOOB(RsContext vrsc, void *obj)
+{
+ Context * rsc = static_cast<Context *>(vrsc);
+ rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
+}
+
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3d17298..52901b2 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -118,6 +118,7 @@
ThreadIO mIO;
+ void objDestroyAdd(ObjectBase *);
protected:
Device *mDev;
@@ -142,6 +143,17 @@
ObjectBaseRef<ProgramVertex> mVertex;
ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
+
+ struct ObjDestroyOOB {
+ pthread_mutex_t mMutex;
+ Vector<ObjectBase *> mDestroyList;
+ bool mNeedToEmpty;
+ };
+ ObjDestroyOOB mObjDestroy;
+ bool objDestroyOOBInit();
+ void objDestroyOOBRun();
+ void objDestroyOOBDestroy();
+
private:
Context();