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

Commit 45fbe0e7 authored by Tim Murray's avatar Tim Murray Committed by Android (Google) Code Review
Browse files

Merge "Enable asynchronous destruction of BaseObjs."

parents 1f7488e2 06b45675
Loading
Loading
Loading
Loading
+23 −9
Original line number Diff line number Diff line
@@ -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 {
    private void helpDestroy() {
        boolean shouldDestroy = false;
        synchronized(this) {
            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);
            }
            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();
    }

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