FileDocCategorySizeDatePackage
TaskDrainer.javaAPI DocAndroid 5.1 API7111Thu Mar 12 22:22:10 GMT 2015android.hardware.camera2.utils

TaskDrainer

public class TaskDrainer extends Object
Keep track of multiple concurrent tasks starting and finishing by their key; allow draining existing tasks and figuring out when all tasks have finished (and new ones won't begin).

The initial state is to allow all tasks to be started and finished. A task may only be started once, after which it must be finished before starting again. Likewise, finishing a task that hasn't been started is also not allowed.

When draining begins, no more new tasks can be started. This guarantees that at some point when all the tasks are finished there will be no more collective new tasks, at which point the {@link DrainListener#onDrained} callback will be invoked.

param
a type for the key that will represent tracked tasks; must implement {@code Object#equals}

Fields Summary
private static final String
TAG
private final boolean
VERBOSE
private final android.os.Handler
mHandler
private final DrainListener
mListener
private final String
mName
private final Set
mTaskSet
Set of tasks which have been started but not yet finished with #taskFinished
private final Object
mLock
private boolean
mDraining
private boolean
mDrainFinished
Constructors Summary
public TaskDrainer(android.os.Handler handler, DrainListener listener)
Create a new task drainer; {@code onDrained} callbacks will be posted to the listener via the {@code handler}.

param
handler a non-{@code null} handler to use to post runnables to
param
listener a non-{@code null} listener where {@code onDrained} will be called


                                                   
         
        mHandler = checkNotNull(handler, "handler must not be null");
        mListener = checkNotNull(listener, "listener must not be null");
        mName = null;
    
public TaskDrainer(android.os.Handler handler, DrainListener listener, String name)
Create a new task drainer; {@code onDrained} callbacks will be posted to the listener via the {@code handler}.

param
handler a non-{@code null} handler to use to post runnables to
param
listener a non-{@code null} listener where {@code onDrained} will be called
param
name an optional name used for debug logging

        // XX: Probably don't need a handler at all here
        mHandler = checkNotNull(handler, "handler must not be null");
        mListener = checkNotNull(listener, "listener must not be null");
        mName = name;
    
Methods Summary
public voidbeginDrain()
Do not allow any more tasks to be started; once all existing started tasks are finished, fire the {@link DrainListener#onDrained} callback asynchronously.

This operation is idempotent; calling it more than once has no effect.

        synchronized (mLock) {
            if (!mDraining) {
                if (VERBOSE) {
                    Log.v(TAG + "[" + mName + "]", "beginDrain started");
                }

                mDraining = true;

                // If all tasks that had started had already finished by now, fire #onDrained
                checkIfDrainFinished();
            } else {
                if (VERBOSE) {
                    Log.v(TAG + "[" + mName + "]", "beginDrain ignored");
                }
            }
        }
    
private voidcheckIfDrainFinished()

        if (mTaskSet.isEmpty() && mDraining && !mDrainFinished) {
            mDrainFinished = true;
            postDrained();
        }
    
private voidpostDrained()

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (VERBOSE) {
                    Log.v(TAG + "[" + mName + "]", "onDrained");
                }

                mListener.onDrained();
            }
        });
    
public voidtaskFinished(T task)
Mark an asynchronous task as having finished.

A task cannot be finished if it hasn't started. Once finished, a task cannot be finished again (unless it's started again).

param
task a key to identify a task
see
#taskStarted
see
#beginDrain
throws
IllegalStateException If attempting to start a task which is already finished (and not re-started),

        synchronized (mLock) {
            if (VERBOSE) {
                Log.v(TAG + "[" + mName + "]", "taskFinished " + task);
            }

            if (!mTaskSet.remove(task)) {
                throw new IllegalStateException("Task " + task + " was already finished");
            }

            // If this is the last finished task and draining has already begun, fire #onDrained
            checkIfDrainFinished();
        }
    
public voidtaskStarted(T task)
Mark an asynchronous task as having started.

A task cannot be started more than once without first having finished. Once draining begins with {@link #beginDrain}, no new tasks can be started.

param
task a key to identify a task
see
#taskFinished
see
#beginDrain
throws
IllegalStateException If attempting to start a task which is already started (and not finished), or if attempting to start a task after draining has begun.

        synchronized (mLock) {
            if (VERBOSE) {
                Log.v(TAG + "[" + mName + "]", "taskStarted " + task);
            }

            if (mDraining) {
                throw new IllegalStateException("Can't start more tasks after draining has begun");
            }

            if (!mTaskSet.add(task)) {
                throw new IllegalStateException("Task " + task + " was already started");
            }
        }