19c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall/* 29c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Copyright (C) 2014 The Android Open Source Project 39c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * 49c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Licensed under the Apache License, Version 2.0 (the "License"); 59c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * you may not use this file except in compliance with the License. 69c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * You may obtain a copy of the License at 79c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * 89c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * http://www.apache.org/licenses/LICENSE-2.0 99c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * 109c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Unless required by applicable law or agreed to in writing, software 119c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * distributed under the License is distributed on an "AS IS" BASIS, 129c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * See the License for the specific language governing permissions and 149c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * limitations under the License. 159c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */ 169c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 179c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallpackage com.android.camera.async; 189c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 199c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallimport java.util.Set; 20e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lallimport java.util.concurrent.CopyOnWriteArraySet; 219c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallimport java.util.concurrent.Executor; 229c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 23e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lallimport javax.annotation.CheckReturnValue; 244961ad31d9a877e3a68566fb5d4b33b7f79ce44ePuneet Lallimport javax.annotation.Nonnull; 25e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lallimport javax.annotation.ParametersAreNonnullByDefault; 264961ad31d9a877e3a68566fb5d4b33b7f79ce44ePuneet Lall 279c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall/** 289c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Generic asynchronous state wrapper which supports two methods of interaction: 299c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * polling for the latest value and listening for updates. 309c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */ 31e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lall@ParametersAreNonnullByDefault 3217fc13a74ff71e3c721218624815c244dccc33f7Puneet Lallpublic class ConcurrentState<T> implements Updatable<T>, Observable<T> { 33e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall private static class ExecutorListenerPair implements Runnable { 349c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall private final Executor mExecutor; 35e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall private final Runnable mListener; 369c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 37e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall public ExecutorListenerPair(Executor executor, Runnable listener) { 389c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall mExecutor = executor; 399c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall mListener = listener; 409c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 419c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 429c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall /** 43e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall * Runs the callback on the executor. 449c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */ 45e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall @Override 46e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall public void run() { 47e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall mExecutor.execute(mListener); 489c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 499c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 509c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 51e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall private final Set<ExecutorListenerPair> mListeners; 52e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall private volatile T mValue; 539c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 549ad0984f36ff9cd133c61c4e979032988b77a995Puneet Lall public ConcurrentState(T initialValue) { 55e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall // Callbacks are typically only added and removed at startup/shutdown, 56e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall // but {@link #update} is often called at high-frequency. So, using a 57e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall // read-optimized data structure is appropriate here. 58e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall mListeners = new CopyOnWriteArraySet<>(); 599ad0984f36ff9cd133c61c4e979032988b77a995Puneet Lall mValue = initialValue; 609c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 619c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 629c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall /** 639c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Updates the state to the latest value, notifying all listeners. 649c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */ 659c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall @Override 66e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lall public void update(T newValue) { 67e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall mValue = newValue; 68e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall for (ExecutorListenerPair pair : mListeners) { 69e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall pair.run(); 709c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 719c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 729c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 73e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lall @CheckReturnValue 74e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lall @Nonnull 7517fc13a74ff71e3c721218624815c244dccc33f7Puneet Lall @Override 76e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall public SafeCloseable addCallback(Runnable callback, Executor executor) { 77e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall final ExecutorListenerPair pair = new ExecutorListenerPair(executor, callback); 78e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall mListeners.add(pair); 79e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall return new SafeCloseable() { 80e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall @Override 81e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall public void close() { 82e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall mListeners.remove(pair); 83e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall } 84e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall }; 859c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 869c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall 879c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall /** 889c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Polls for the latest value. 899c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * 909c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * @return The latest state. 919c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */ 92e919a48fb40b9d6c698a495acf40adbc0e320431Puneet Lall @Nonnull 939c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall @Override 949ad0984f36ff9cd133c61c4e979032988b77a995Puneet Lall public T get() { 95e606c4d68b74293e7d7725aecbaa9c915751cd43Puneet Lall return mValue; 969c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall } 979c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall} 98