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