ConcurrentState.java revision 9c94ab32a69a1ad3642a0f1e38e68bcfd97d3511
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 17package com.android.camera.async; 18 19import java.util.ArrayList; 20import java.util.HashSet; 21import java.util.List; 22import java.util.Set; 23import java.util.concurrent.Executor; 24 25import com.android.camera.util.Callback; 26 27/** 28 * Generic asynchronous state wrapper which supports two methods of interaction: 29 * polling for the latest value and listening for updates. 30 * <p> 31 * Note that this class only supports polling and using listeners. If 32 * synchronous consumption of state changes is required, see 33 * {@link FutureResult} or {@link BufferQueue} and its implementations. 34 * </p> 35 */ 36public class ConcurrentState<T> implements Updatable<T>, Pollable<T> { 37 38 private static class ExecutorListenerPair<T> { 39 private final Executor mExecutor; 40 private final Callback<T> mListener; 41 42 public ExecutorListenerPair(Executor executor, Callback<T> listener) { 43 mExecutor = executor; 44 mListener = listener; 45 } 46 47 /** 48 * Runs the callback on the executor with the given value. 49 */ 50 public void run(final T t) { 51 mExecutor.execute(new Runnable() { 52 public void run() { 53 mListener.onCallback(t); 54 } 55 }); 56 } 57 } 58 59 private final Object mLock; 60 private final Set<ExecutorListenerPair<T>> mListeners; 61 private boolean mValueSet; 62 private T mValue; 63 64 public ConcurrentState() { 65 mLock = new Object(); 66 mListeners = new HashSet<ExecutorListenerPair<T>>(); 67 mValueSet = false; 68 } 69 70 /** 71 * Updates the state to the latest value, notifying all listeners. 72 */ 73 @Override 74 public void update(T newValue) { 75 List<ExecutorListenerPair<T>> listeners = new ArrayList<ExecutorListenerPair<T>>(); 76 synchronized (mLock) { 77 mValueSet = true; 78 mValue = newValue; 79 // Copy listeners out here so we can iterate over the list outside 80 // the critical section. 81 listeners.addAll(mListeners); 82 } 83 for (ExecutorListenerPair<T> pair : listeners) { 84 pair.run(newValue); 85 } 86 } 87 88 /** 89 * Adds the given callback, returning a token to be closed when the callback 90 * is no longer needed. 91 * 92 * @param callback The callback to add. 93 * @param executor The executor on which the callback will be invoked. 94 * @return A {@link SafeCloseable} token to be closed when the callback must 95 * be removed. 96 */ 97 public SafeCloseable addCallback(Callback callback, Executor executor) { 98 synchronized (mLock) { 99 final ExecutorListenerPair<T> pair = new ExecutorListenerPair<>(executor, callback); 100 mListeners.add(pair); 101 102 return new SafeCloseable() { 103 @Override 104 public void close() { 105 synchronized (mLock) { 106 mListeners.remove(pair); 107 } 108 } 109 }; 110 } 111 } 112 113 /** 114 * Polls for the latest value. 115 * 116 * @return The latest state, or defaultValue if no state has been set yet. 117 */ 118 @Override 119 public T get(T defaultValue) { 120 try { 121 return get(); 122 } catch (Pollable.NoValueSetException e) { 123 return defaultValue; 124 } 125 } 126 127 /** 128 * Polls for the latest value. 129 * 130 * @return The latest state. 131 * @throws com.android.camera.async.Pollable.NoValueSetException If no value has been set yet. 132 */ 133 @Override 134 public T get() throws Pollable.NoValueSetException { 135 synchronized (mLock) { 136 if (mValueSet) { 137 return mValue; 138 } else { 139 throw new Pollable.NoValueSetException(); 140 } 141 } 142 } 143} 144