| /* |
| * Copyright (C) 2006 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.google.common.util.concurrent; |
| |
| import static com.google.common.collect.Lists.newArrayListWithCapacity; |
| import static java.util.Collections.unmodifiableList; |
| |
| import com.google.common.annotations.GwtCompatible; |
| import com.google.common.collect.ImmutableCollection; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import java.util.List; |
| import java.util.concurrent.Future; |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| |
| /** Aggregate future that collects (stores) results of each future. */ |
| @GwtCompatible(emulated = true) |
| abstract class CollectionFuture<V, C> extends AggregateFuture<V, C> { |
| /* |
| * We access this field racily but safely. For discussion of a similar situation, see the comments |
| * on the fields of TimeoutFuture. This field is slightly different than the fields discussed |
| * there: cancel() never reads this field, only writes to it. That makes the race here completely |
| * harmless, rather than just 99.99% harmless. |
| */ |
| private List<Present<V>> values; |
| |
| CollectionFuture( |
| ImmutableCollection<? extends ListenableFuture<? extends V>> futures, |
| boolean allMustSucceed) { |
| super(futures, allMustSucceed, true); |
| |
| List<Present<V>> values = |
| futures.isEmpty() |
| ? ImmutableList.<Present<V>>of() |
| : Lists.<Present<V>>newArrayListWithCapacity(futures.size()); |
| |
| // Populate the results list with null initially. |
| for (int i = 0; i < futures.size(); ++i) { |
| values.add(null); |
| } |
| |
| this.values = values; |
| } |
| |
| @Override |
| final void collectOneValue(int index, @Nullable V returnValue) { |
| List<Present<V>> localValues = values; |
| if (localValues != null) { |
| localValues.set(index, new Present<>(returnValue)); |
| } |
| } |
| |
| @Override |
| final void handleAllCompleted() { |
| List<Present<V>> localValues = values; |
| if (localValues != null) { |
| set(combine(localValues)); |
| } |
| } |
| |
| @Override |
| void releaseResources(ReleaseResourcesReason reason) { |
| super.releaseResources(reason); |
| this.values = null; |
| } |
| |
| abstract C combine(List<Present<V>> values); |
| |
| /** Used for {@link Futures#allAsList} and {@link Futures#successfulAsList}. */ |
| static final class ListFuture<V> extends CollectionFuture<V, List<V>> { |
| ListFuture( |
| ImmutableCollection<? extends ListenableFuture<? extends V>> futures, |
| boolean allMustSucceed) { |
| super(futures, allMustSucceed); |
| init(); |
| } |
| |
| @Override |
| public List<V> combine(List<Present<V>> values) { |
| List<V> result = newArrayListWithCapacity(values.size()); |
| for (Present<V> element : values) { |
| result.add(element != null ? element.value : null); |
| } |
| return unmodifiableList(result); |
| } |
| } |
| |
| /** The result of a successful {@code Future}. */ |
| private static final class Present<V> { |
| V value; |
| |
| Present(V value) { |
| this.value = value; |
| } |
| } |
| } |