• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 
17 package com.android.camera.async;
18 
19 import com.google.common.util.concurrent.AsyncFunction;
20 import com.google.common.util.concurrent.ForwardingListenableFuture;
21 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import com.google.common.util.concurrent.MoreExecutors;
24 
25 import java.util.List;
26 
27 import javax.annotation.Nullable;
28 
29 /**
30  * TODO Replace with Guava's com.google.common.util.concurrent.Futures once we
31  * can build with v. 15+
32  */
33 public class Futures2 {
34     /**
35      * 2 parameter async function for joined async results.
36      */
37     public interface AsyncFunction2<T1, T2, TResult> {
apply(T1 value1, T2 value2)38         ListenableFuture<TResult> apply(T1 value1, T2 value2) throws Exception;
39     }
40 
41     /**
42      * 3 parameter async function for joined async results.
43      */
44     public interface AsyncFunction3<T1, T2, T3, TResult> {
apply(T1 value1, T2 value2, T3 value3)45         ListenableFuture<TResult> apply(T1 value1, T2 value2, T3 value3) throws Exception;
46     }
47 
48     /**
49      * 2 parameter function for joining multiple results into a single value.
50      */
51     public interface Function2<T1, T2, TResult> {
apply(T1 value1, T2 value2)52         TResult apply(T1 value1, T2 value2);
53     }
54 
55     /**
56      * 3 parameter function for joining multiple results into a single value.
57      */
58     public interface Function3<T1, T2, T3, TResult> {
apply(T1 value1, T2 value2, T3 value3)59         TResult apply(T1 value1, T2 value2, T3 value3);
60     }
61 
Futures2()62     private Futures2() {
63     }
64 
65     /**
66      * Creates a new ListenableFuture whose result is set from the supplied
67      * future when it completes. Cancelling the supplied future will also cancel
68      * the returned future, but cancelling the returned future will have no
69      * effect on the supplied future.
70      */
nonCancellationPropagating( final ListenableFuture<T> future)71     public static <T> ListenableFuture<T> nonCancellationPropagating(
72             final ListenableFuture<T> future) {
73         return new ForwardingListenableFuture.SimpleForwardingListenableFuture<T>(future) {
74             @Override
75             public boolean cancel(boolean mayInterruptIfNecessary) {
76                 return false;
77             }
78         };
79     }
80 
81     /**
82      * Create a new joined future from two existing futures and a joining function
83      * that combines the resulting outputs of the previous functions into a single
84      * result. The resulting future will fail if any of the dependent futures also
85      * fail.
86      */
87     public static <T1, T2, TResult> ListenableFuture<TResult> joinAll(
88           final ListenableFuture<T1> f1,
89           final ListenableFuture<T2> f2,
90           final AsyncFunction2<T1, T2, TResult> fn) {
91         ListenableFuture<?>[] futures = new ListenableFuture<?>[2];
92 
93         futures[0] = f1;
94         futures[1] = f2;
95 
96         // Futures.allAsList is used instead of Futures.successfulAsList because
97         // allAsList will propagate the failures instead of null values to the
98         // parameters of the supplied function.
99         ListenableFuture<List<Object>> result = Futures.<Object>allAsList(futures);
100         return Futures.transformAsync(result, new AsyncFunction<List<Object>, TResult>() {
101             @Override
102             public ListenableFuture<TResult> apply(@Nullable List<Object> list) throws Exception {
103                 T1 value1 = (T1) list.get(0);
104                 T2 value2 = (T2) list.get(1);
105 
106                 return fn.apply(value1, value2);
107             }
108         }, MoreExecutors.directExecutor());
109     }
110 
111     /**
112      * Create a new joined future from two existing futures and an async function
113      * that combines the resulting outputs of the previous functions into a single
114      * result. The resulting future will fail if any of the dependent futures also
115      * fail.
116      */
117     public static <T1, T2, TResult> ListenableFuture<TResult> joinAll(
118           final ListenableFuture<T1> f1,
119           final ListenableFuture<T2> f2,
120           final Function2<T1, T2, TResult> fn) {
121         return joinAll(f1, f2, new ImmediateAsyncFunction2<>(fn));
122     }
123 
124     /**
125      * Create a new joined future from three existing futures and a joining function
126      * that combines the resulting outputs of the previous functions into a single
127      * result. The resulting future will fail if any of the dependent futures also
128      * fail.
129      */
130     public static <T1, T2, T3, TResult> ListenableFuture<TResult> joinAll(
131           final ListenableFuture<T1> f1,
132           final ListenableFuture<T2> f2,
133           final ListenableFuture<T3> f3,
134           final AsyncFunction3<T1, T2, T3, TResult> fn) {
135         ListenableFuture<?>[] futures = new ListenableFuture<?>[3];
136 
137         futures[0] = f1;
138         futures[1] = f2;
139         futures[2] = f3;
140 
141         // Futures.allAsList is used instead of Futures.successfulAsList because
142         // allAsList will propagate the failures instead of null values to the
143         // parameters of the supplied function.
144         ListenableFuture<List<Object>> result = Futures.<Object>allAsList(futures);
145         return Futures.transformAsync(result, new AsyncFunction<List<Object>, TResult>() {
146             @Override
147             public ListenableFuture<TResult> apply(@Nullable List<Object> list) throws Exception {
148                 T1 value1 = (T1) list.get(0);
149                 T2 value2 = (T2) list.get(1);
150                 T3 value3 = (T3) list.get(2);
151 
152                 return fn.apply(value1, value2, value3);
153             }
154         }, MoreExecutors.directExecutor());
155     }
156 
157     /**
158      * Create a new joined future from three existing futures and an async function
159      * that combines the resulting outputs of the previous functions into a single
160      * result. The resulting future will fail if any of the dependent futures also
161      * fail.
162      */
163     public static <T1, T2, T3, TResult> ListenableFuture<TResult> joinAll(
164           final ListenableFuture<T1> f1,
165           final ListenableFuture<T2> f2,
166           final ListenableFuture<T3> f3,
167           final Function3<T1, T2, T3, TResult> fn) {
168         return joinAll(f1, f2, f3, new ImmediateAsyncFunction3<>(fn));
169     }
170 
171     /**
172      * Wrapper class for turning a Function2 into an AsyncFunction2 by returning
173      * an immediate future when the function is applied.
174      */
175     private static final class ImmediateAsyncFunction2<T1, T2, TResult> implements
176           AsyncFunction2<T1, T2, TResult> {
177         private final Function2<T1, T2, TResult> mFn;
178 
179         public ImmediateAsyncFunction2(Function2<T1, T2, TResult> fn) {
180             mFn = fn;
181         }
182 
183         @Override
184         public ListenableFuture<TResult> apply(T1 value1, T2 value2) throws Exception {
185             return Futures.immediateFuture(mFn.apply(value1, value2));
186         }
187     }
188 
189     /**
190      * Wrapper class for turning a Function3 into an AsyncFunction3 by returning
191      * an immediate future when the function is applied.
192      */
193     private static final class ImmediateAsyncFunction3<T1, T2, T3, TResult> implements
194           AsyncFunction3<T1, T2, T3, TResult> {
195         private final Function3<T1, T2, T3, TResult> mFn;
196 
197         public ImmediateAsyncFunction3(Function3<T1, T2, T3, TResult> fn) {
198             mFn = fn;
199         }
200 
201         @Override
202         public ListenableFuture<TResult> apply(T1 value1, T2 value2, T3 value3) throws Exception {
203             return Futures.immediateFuture(mFn.apply(value1, value2, value3));
204         }
205     }
206 }
207