am 0539b7b4: Merge "Enable asynchronous destruction of BaseObjs."

* commit '0539b7b4116622d33c91dbaa9a3040c7a3a703d6':
  Enable asynchronous destruction of BaseObjs.
This commit is contained in:
Tim Murray
2014-02-03 14:41:27 -08:00
committed by Android Git Automerger
2 changed files with 42 additions and 13 deletions

View File

@@ -16,7 +16,7 @@
package android.renderscript; package android.renderscript;
import android.util.Log; import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
* BaseObj is the base class for all RenderScript objects owned by a RS context. * BaseObj is the base class for all RenderScript objects owned by a RS context.
@@ -109,17 +109,30 @@ public class BaseObj {
return mName; return mName;
} }
protected void finalize() throws Throwable { private void helpDestroy() {
if (!mDestroyed) { boolean shouldDestroy = false;
if(mID != 0 && mRS.isAlive()) { 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); mRS.nObjDestroy(mID);
} }
rlock.unlock();
mRS = null; mRS = null;
mID = 0; 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(); super.finalize();
} }
@@ -128,12 +141,11 @@ public class BaseObj {
* primary use is to force immediate cleanup of resources when it is * primary use is to force immediate cleanup of resources when it is
* believed the GC will not respond quickly enough. * believed the GC will not respond quickly enough.
*/ */
synchronized public void destroy() { public void destroy() {
if(mDestroyed) { if(mDestroyed) {
throw new RSInvalidStateException("Object already destroyed."); throw new RSInvalidStateException("Object already destroyed.");
} }
mDestroyed = true; helpDestroy();
mRS.nObjDestroy(mID);
} }
/** /**

View File

@@ -19,6 +19,7 @@ package android.renderscript;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -151,6 +152,7 @@ public class RenderScript {
} }
ContextType mContextType; ContextType mContextType;
ReentrantReadWriteLock mRWLock;
// Methods below are wrapped to protect the non-threadsafe // Methods below are wrapped to protect the non-threadsafe
// lockless fifo. // lockless fifo.
@@ -178,7 +180,18 @@ public class RenderScript {
native void rsnContextDestroy(long con); native void rsnContextDestroy(long con);
synchronized void nContextDestroy() { synchronized void nContextDestroy() {
validate(); 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); native void rsnContextSetSurface(long con, int w, int h, Surface sur);
synchronized void nContextSetSurface(int w, int h, Surface sur) { synchronized void nContextSetSurface(int w, int h, Surface sur) {
@@ -263,8 +276,10 @@ public class RenderScript {
validate(); validate();
return rsnGetName(mContext, obj); return rsnGetName(mContext, obj);
} }
// nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
native void rsnObjDestroy(long con, long id); 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 // There is a race condition here. The calling code may be run
// by the gc while teardown is occuring. This protects againts // by the gc while teardown is occuring. This protects againts
// deleting dead objects. // deleting dead objects.
@@ -1096,6 +1111,7 @@ public class RenderScript {
if (ctx != null) { if (ctx != null) {
mApplicationContext = ctx.getApplicationContext(); mApplicationContext = ctx.getApplicationContext();
} }
mRWLock = new ReentrantReadWriteLock();
} }
/** /**
@@ -1190,6 +1206,8 @@ public class RenderScript {
*/ */
public void destroy() { public void destroy() {
validate(); validate();
nContextFinish();
nContextDeinitToClient(mContext); nContextDeinitToClient(mContext);
mMessageThread.mRun = false; mMessageThread.mRun = false;
try { try {
@@ -1198,7 +1216,6 @@ public class RenderScript {
} }
nContextDestroy(); nContextDestroy();
mContext = 0;
nDeviceDestroy(mDev); nDeviceDestroy(mDev);
mDev = 0; mDev = 0;