diff options
author | Tim Murray <timmurray@google.com> | 2014-01-07 11:13:56 -0800 |
---|---|---|
committer | Tim Murray <timmurray@google.com> | 2014-01-10 10:39:38 -0800 |
commit | 06b4567559bbf39eccfa9c28152c8e5e067cf576 (patch) | |
tree | 668d498fdde464a765f3abc183755f25e4683670 /rs/java | |
parent | 71a01b8648a440d4773acf0d2376d015c129ebb5 (diff) | |
download | frameworks_base-06b4567559bbf39eccfa9c28152c8e5e067cf576.zip frameworks_base-06b4567559bbf39eccfa9c28152c8e5e067cf576.tar.gz frameworks_base-06b4567559bbf39eccfa9c28152c8e5e067cf576.tar.bz2 |
Enable asynchronous destruction of BaseObjs.
Change-Id: Iaddf8041a3c870a986ec8999e6ccc3aede38fc4c
Diffstat (limited to 'rs/java')
-rw-r--r-- | rs/java/android/renderscript/BaseObj.java | 32 | ||||
-rw-r--r-- | rs/java/android/renderscript/RenderScript.java | 23 |
2 files changed, 43 insertions, 12 deletions
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java index 1a15ce6..eee4936 100644 --- a/rs/java/android/renderscript/BaseObj.java +++ b/rs/java/android/renderscript/BaseObj.java @@ -16,6 +16,8 @@ package android.renderscript; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * BaseObj is the base class for all RenderScript objects owned by a RS context. * It is responsible for lifetime management and resource tracking. This class @@ -107,17 +109,30 @@ public class BaseObj { return mName; } - protected void finalize() throws Throwable { - if (!mDestroyed) { - if(mID != 0 && mRS.isAlive()) { + private void helpDestroy() { + boolean shouldDestroy = false; + synchronized(this) { + if (!mDestroyed) { + shouldDestroy = true; + mDestroyed = true; + } + } + + if (shouldDestroy) { + // must include nObjDestroy in the critical section + ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock(); + rlock.lock(); + if(mRS.isAlive()) { mRS.nObjDestroy(mID); } + rlock.unlock(); mRS = null; mID = 0; - mDestroyed = true; - //Log.v(RenderScript.LOG_TAG, getClass() + - // " auto finalizing object without having released the RS reference."); } + } + + protected void finalize() throws Throwable { + helpDestroy(); super.finalize(); } @@ -126,12 +141,11 @@ public class BaseObj { * primary use is to force immediate cleanup of resources when it is * believed the GC will not respond quickly enough. */ - synchronized public void destroy() { + public void destroy() { if(mDestroyed) { throw new RSInvalidStateException("Object already destroyed."); } - mDestroyed = true; - mRS.nObjDestroy(mID); + helpDestroy(); } /** diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index d2c7456..b0ef156 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -18,6 +18,7 @@ package android.renderscript; import java.io.File; import java.lang.reflect.Method; +import java.util.concurrent.locks.ReentrantReadWriteLock; import android.content.Context; import android.content.res.AssetManager; @@ -147,6 +148,7 @@ public class RenderScript { } ContextType mContextType; + ReentrantReadWriteLock mRWLock; // Methods below are wrapped to protect the non-threadsafe // lockless fifo. @@ -174,7 +176,18 @@ public class RenderScript { native void rsnContextDestroy(long con); synchronized void nContextDestroy() { validate(); - rsnContextDestroy(mContext); + + // take teardown lock + // teardown lock can only be taken when no objects are being destroyed + ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock(); + wlock.lock(); + + long curCon = mContext; + // context is considered dead as of this point + mContext = 0; + + wlock.unlock(); + rsnContextDestroy(curCon); } native void rsnContextSetSurface(long con, int w, int h, Surface sur); synchronized void nContextSetSurface(int w, int h, Surface sur) { @@ -259,8 +272,10 @@ public class RenderScript { validate(); return rsnGetName(mContext, obj); } + + // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers native void rsnObjDestroy(long con, long id); - synchronized void nObjDestroy(long id) { + void nObjDestroy(long id) { // There is a race condition here. The calling code may be run // by the gc while teardown is occuring. This protects againts // deleting dead objects. @@ -1092,6 +1107,7 @@ public class RenderScript { if (ctx != null) { mApplicationContext = ctx.getApplicationContext(); } + mRWLock = new ReentrantReadWriteLock(); } /** @@ -1186,6 +1202,8 @@ public class RenderScript { */ public void destroy() { validate(); + nContextFinish(); + nContextDeinitToClient(mContext); mMessageThread.mRun = false; try { @@ -1194,7 +1212,6 @@ public class RenderScript { } nContextDestroy(); - mContext = 0; nDeviceDestroy(mDev); mDev = 0; |