Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 504abb36 authored by Tim Murray's avatar Tim Murray
Browse files

Enable asynchronous destruction of BaseObjs.

Change-Id: Iaddf8041a3c870a986ec8999e6ccc3aede38fc4c

Conflicts:
	rs/java/android/renderscript/BaseObj.java
parent e926dddb
Loading
Loading
Loading
Loading
+22 −10
Original line number Original line Diff line number Diff line
@@ -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() {
        boolean shouldDestroy = false;
        synchronized(this) {
            if (!mDestroyed) {
            if (!mDestroyed) {
            if(mID != 0 && mRS.isAlive()) {
                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);
    }
    }


    /**
    /**
+20 −3
Original line number Original line Diff line number Diff line
@@ -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;