Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.hardware.camera2.utils;
     17 
     18 import android.hardware.camera2.utils.TaskDrainer.DrainListener;
     19 
     20 import java.util.concurrent.Executor;
     21 
     22 /**
     23  * Keep track of a single concurrent task starting and finishing;
     24  * allow draining the existing task and figuring out when the task has finished
     25  * (and won't restart).
     26  *
     27  * <p>The initial state is to allow all tasks to be started and finished. A task may only be started
     28  * once, after which it must be finished before starting again. Likewise, finishing a task
     29  * that hasn't been started is also not allowed.</p>
     30  *
     31  * <p>When draining begins, the task cannot be started again. This guarantees that at some
     32  * point the task will be finished forever, at which point the {@link DrainListener#onDrained}
     33  * callback will be invoked.</p>
     34  */
     35 public class TaskSingleDrainer {
     36 
     37     private final TaskDrainer<Object> mTaskDrainer;
     38     private final Object mSingleTask = new Object();
     39 
     40     /**
     41      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
     42      * via the {@code executor}.
     43      *
     44      * @param executor a non-{@code null} executor to use for listener execution
     45      * @param listener a non-{@code null} listener where {@code onDrained} will be called
     46      */
     47     public TaskSingleDrainer(Executor executor, DrainListener listener) {
     48         mTaskDrainer = new TaskDrainer<>(executor, listener);
     49     }
     50 
     51     /**
     52      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
     53      * via the {@code executor}.
     54      *
     55      * @param executor a non-{@code null} executor to use for listener execution
     56      * @param listener a non-{@code null} listener where {@code onDrained} will be called
     57      * @param name an optional name used for debug logging
     58      */
     59     public TaskSingleDrainer(Executor executor, DrainListener listener, String name) {
     60         mTaskDrainer = new TaskDrainer<>(executor, listener, name);
     61     }
     62 
     63     /**
     64      * Mark this asynchronous task as having started.
     65      *
     66      * <p>The task cannot be started more than once without first having finished. Once
     67      * draining begins with {@link #beginDrain}, no new tasks can be started.</p>
     68      *
     69      * @see #taskFinished
     70      * @see #beginDrain
     71      *
     72      * @throws IllegalStateException
     73      *          If attempting to start a task which is already started (and not finished),
     74      *          or if attempting to start a task after draining has begun.
     75      */
     76     public void taskStarted() {
     77         mTaskDrainer.taskStarted(mSingleTask);
     78     }
     79 
     80     /**
     81      * Do not allow any more task re-starts; once the existing task is finished,
     82      * fire the {@link DrainListener#onDrained} callback asynchronously.
     83      *
     84      * <p>This operation is idempotent; calling it more than once has no effect.</p>
     85      */
     86     public void beginDrain() {
     87         mTaskDrainer.beginDrain();
     88     }
     89 
     90     /**
     91      * Mark this asynchronous task as having finished.
     92      *
     93      * <p>The task cannot be finished if it hasn't started. Once finished, a task
     94      * cannot be finished again (unless it's started again).</p>
     95      *
     96      * @see #taskStarted
     97      * @see #beginDrain
     98      *
     99      * @throws IllegalStateException
    100      *          If attempting to start a task which is already finished (and not re-started),
    101      */
    102     public void taskFinished() {
    103         mTaskDrainer.taskFinished(mSingleTask);
    104     }
    105 }
    106