TaskDrainerpublic 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. |
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 | mTaskSetSet 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}.
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}.
// 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 void | beginDrain()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 void | checkIfDrainFinished()
if (mTaskSet.isEmpty() && mDraining && !mDrainFinished) {
mDrainFinished = true;
postDrained();
}
| private void | postDrained()
mHandler.post(new Runnable() {
@Override
public void run() {
if (VERBOSE) {
Log.v(TAG + "[" + mName + "]", "onDrained");
}
mListener.onDrained();
}
});
| public void | taskFinished(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).
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 void | taskStarted(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.
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");
}
}
|
|