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