V - the type of the value of this steppublic final class ClosingFuture<V>
extends java.lang.Object
A pipeline of ClosingFutures is a tree of steps. Each step represents either an
asynchronously-computed intermediate value, or else an exception that indicates the failure or
cancellation of the operation so far. The only way to extract the value or exception from a step
is by declaring that step to be the last step of the pipeline. Nevertheless, we refer to the
"value" of a successful step or the "result" (value or exception) of any step.
ListenableFuture.
ClosingFuture pipeline from a
callable block that may capture objects for later closing. To start a pipeline from a ListenableFuture that doesn't create resources that should be closed later, you can use from(ListenableFuture) instead.
ClosingFuture step can be derived from one or more input ClosingFuture steps in
ways similar to FluentFutures:
A step can be the input to at most one derived step. Once you transform its value, catch its exception, or combine it with others, you cannot do anything else with it, including declare it to be the last step of the pipeline.
transform(ClosingFunction, Executor) or transformAsync(AsyncClosingFunction,
Executor) on the input step.
catching(Class, ClosingFunction,
Executor) or catchingAsync(Class, AsyncClosingFunction, Executor) on the input step.
ClosingFuture from two or more input steps, pass the input steps to whenAllComplete(Iterable) or whenAllSucceed(Iterable) or its overloads.
Future. In addition, a
successfully cancelled step will immediately start closing all objects captured for later closing
by it and by its input steps.
ClosingFuture pipeline must be ended. To end a pipeline, decide whether you want to
close the captured objects automatically or manually.
Future that represents the result of the last step in the pipeline by
calling finishToFuture(). All objects the pipeline has captured for closing will begin
to be closed asynchronously after the returned Future is done: the future
completes before closing starts, rather than once it has finished.
FluentFuture<UserName> userName =
ClosingFuture.submit(
closer -> closer.eventuallyClose(database.newTransaction(), closingExecutor),
executor)
.transformAsync((closer, transaction) -> transaction.queryClosingFuture("..."), executor)
.transform((closer, result) -> result.get("userName"), directExecutor())
.catching(DBException.class, e -> "no user", directExecutor())
.finishToFuture();
In this example, when the userName Future is done, the transaction and the query
result cursor will both be closed, even if the operation is cancelled or fails.
finishToValueAndCloser(ValueAndCloserConsumer, Executor) to get an object that holds the
final result. You then call ClosingFuture.ValueAndCloser.closeAsync() to close the captured objects.
ClosingFuture.submit(
closer -> closer.eventuallyClose(database.newTransaction(), closingExecutor),
executor)
.transformAsync((closer, transaction) -> transaction.queryClosingFuture("..."), executor)
.transform((closer, result) -> result.get("userName"), directExecutor())
.catching(DBException.class, e -> "no user", directExecutor())
.finishToValueAndCloser(
valueAndCloser -> this.userNameValueAndCloser = valueAndCloser, executor);
// later
try { // get() will throw if the operation failed or was cancelled.
UserName userName = userNameValueAndCloser.get();
// do something with userName
} finally {
userNameValueAndCloser.closeAsync();
}
In this example, when userNameValueAndCloser.closeAsync() is called, the transaction and
the query result cursor will both be closed, even if the operation is cancelled or fails.
Note that if you don't call closeAsync(), the captured objects will not be closed. The
automatic-closing approach described above is safer.
| Modifier and Type | Class and Description |
|---|---|
static interface |
ClosingFuture.AsyncClosingCallable<V>
An operation that computes a
ClosingFuture of a result. |
static interface |
ClosingFuture.AsyncClosingFunction<T,U>
A function from an input to a
ClosingFuture of a result. |
private static class |
ClosingFuture.CloseableList |
static interface |
ClosingFuture.ClosingCallable<V>
An operation that computes a result.
|
static interface |
ClosingFuture.ClosingFunction<T,U>
A function from an input to a result.
|
static class |
ClosingFuture.Combiner
A builder of a
ClosingFuture step that is derived from more than one input step. |
static class |
ClosingFuture.Combiner2<V1,V2>
A generic
ClosingFuture.Combiner that lets you use a lambda or method reference to combine two ClosingFutures. |
static class |
ClosingFuture.Combiner3<V1,V2,V3>
A generic
ClosingFuture.Combiner that lets you use a lambda or method reference to combine three
ClosingFutures. |
static class |
ClosingFuture.Combiner4<V1,V2,V3,V4>
A generic
ClosingFuture.Combiner that lets you use a lambda or method reference to combine four
ClosingFutures. |
static class |
ClosingFuture.Combiner5<V1,V2,V3,V4,V5>
A generic
ClosingFuture.Combiner that lets you use a lambda or method reference to combine five
ClosingFutures. |
static class |
ClosingFuture.DeferredCloser
An object that can capture objects to be closed later, when a
ClosingFuture pipeline is
done. |
static class |
ClosingFuture.Peeker
An object that can return the value of the
ClosingFutures that are passed to whenAllComplete(Iterable) or whenAllSucceed(Iterable). |
(package private) static class |
ClosingFuture.State
The state of a
ClosingFuture.CloseableList. |
static class |
ClosingFuture.ValueAndCloser<V>
An object that holds the final result of an asynchronous
ClosingFuture operation and
allows the user to close all the closeable objects that were captured during it for later
closing. |
static interface |
ClosingFuture.ValueAndCloserConsumer<V>
Represents an operation that accepts a
ClosingFuture.ValueAndCloser for the last step in a ClosingFuture pipeline. |
| Modifier and Type | Field and Description |
|---|---|
private ClosingFuture.CloseableList |
closeables |
private FluentFuture<V> |
future |
private static java.util.logging.Logger |
logger |
private java.util.concurrent.atomic.AtomicReference<ClosingFuture.State> |
state |
| Modifier | Constructor and Description |
|---|---|
private |
ClosingFuture(ClosingFuture.AsyncClosingCallable<V> callable,
java.util.concurrent.Executor executor) |
private |
ClosingFuture(ClosingFuture.ClosingCallable<V> callable,
java.util.concurrent.Executor executor) |
private |
ClosingFuture(ListenableFuture<V> future) |
| Modifier and Type | Method and Description |
|---|---|
private void |
becomeSubsumedInto(ClosingFuture.CloseableList otherCloseables) |
boolean |
cancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this step.
|
<X extends java.lang.Throwable> |
catching(java.lang.Class<X> exceptionType,
ClosingFuture.ClosingFunction<? super X,? extends V> fallback,
java.util.concurrent.Executor executor)
Returns a new
ClosingFuture pipeline step derived from this one by applying a function
to its exception if it is an instance of a given exception type. |
<X extends java.lang.Throwable> |
catchingAsync(java.lang.Class<X> exceptionType,
ClosingFuture.AsyncClosingFunction<? super X,? extends V> fallback,
java.util.concurrent.Executor executor)
Returns a new
ClosingFuture pipeline step derived from this one by applying a function
that returns a ClosingFuture to its exception if it is an instance of a given exception
type. |
private <X extends java.lang.Throwable,W extends V> |
catchingAsyncMoreGeneric(java.lang.Class<X> exceptionType,
ClosingFuture.AsyncClosingFunction<? super X,W> fallback,
java.util.concurrent.Executor executor) |
private <X extends java.lang.Throwable,W extends V> |
catchingMoreGeneric(java.lang.Class<X> exceptionType,
ClosingFuture.ClosingFunction<? super X,W> fallback,
java.util.concurrent.Executor executor) |
private void |
checkAndUpdateState(ClosingFuture.State oldState,
ClosingFuture.State newState) |
private void |
close() |
private static void |
closeQuietly(java.lang.AutoCloseable closeable,
java.util.concurrent.Executor executor) |
private boolean |
compareAndUpdateState(ClosingFuture.State oldState,
ClosingFuture.State newState) |
private <U> ClosingFuture<U> |
derive(FluentFuture<U> future) |
static <C extends java.lang.Object & java.lang.AutoCloseable> |
eventuallyClosing(ListenableFuture<C> future,
java.util.concurrent.Executor closingExecutor)
Deprecated.
Creating
Futures of closeable types is dangerous in general because the
underlying value may never be closed if the Future is canceled after its operation
begins. Consider replacing code that creates ListenableFutures of closeable types,
including those that pass them to this method, with submit(ClosingCallable,
Executor) in order to ensure that resources do not leak. Or, to start a pipeline with a
ListenableFuture that doesn't create values that should be closed, use from(com.google.common.util.concurrent.ListenableFuture<V>). |
protected void |
finalize() |
FluentFuture<V> |
finishToFuture()
Marks this step as the last step in the
ClosingFuture pipeline. |
void |
finishToValueAndCloser(ClosingFuture.ValueAndCloserConsumer<? super V> consumer,
java.util.concurrent.Executor executor)
Marks this step as the last step in the
ClosingFuture pipeline. |
static <V> ClosingFuture<V> |
from(ListenableFuture<V> future)
Starts a
ClosingFuture pipeline with a ListenableFuture. |
private static <C,V extends C> |
provideValueAndCloser(ClosingFuture.ValueAndCloserConsumer<C> consumer,
ClosingFuture<V> closingFuture) |
ListenableFuture<?> |
statusFuture()
Returns a future that finishes when this step does.
|
static <V> ClosingFuture<V> |
submit(ClosingFuture.ClosingCallable<V> callable,
java.util.concurrent.Executor executor)
Starts a
ClosingFuture pipeline by submitting a callable block to an executor. |
static <V> ClosingFuture<V> |
submitAsync(ClosingFuture.AsyncClosingCallable<V> callable,
java.util.concurrent.Executor executor)
Starts a
ClosingFuture pipeline by submitting a callable block to an executor. |
java.lang.String |
toString() |
<U> ClosingFuture<U> |
transform(ClosingFuture.ClosingFunction<? super V,U> function,
java.util.concurrent.Executor executor)
Returns a new
ClosingFuture pipeline step derived from this one by applying a function
to its value. |
<U> ClosingFuture<U> |
transformAsync(ClosingFuture.AsyncClosingFunction<? super V,U> function,
java.util.concurrent.Executor executor)
Returns a new
ClosingFuture pipeline step derived from this one by applying a function
that returns a ClosingFuture to its value. |
static ClosingFuture.Combiner |
whenAllComplete(ClosingFuture<?> future1,
ClosingFuture<?>... moreFutures)
Starts specifying how to combine
ClosingFutures into a single pipeline. |
static ClosingFuture.Combiner |
whenAllComplete(java.lang.Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combine
ClosingFutures into a single pipeline. |
static ClosingFuture.Combiner |
whenAllSucceed(ClosingFuture<?> future1,
ClosingFuture<?> future2,
ClosingFuture<?> future3,
ClosingFuture<?> future4,
ClosingFuture<?> future5,
ClosingFuture<?> future6,
ClosingFuture<?>... moreFutures)
Starts specifying how to combine
ClosingFutures into a single pipeline, assuming they
all succeed. |
static <V1,V2> ClosingFuture.Combiner2<V1,V2> |
whenAllSucceed(ClosingFuture<V1> future1,
ClosingFuture<V2> future2)
Starts specifying how to combine two
ClosingFutures into a single pipeline, assuming
they all succeed. |
static <V1,V2,V3> ClosingFuture.Combiner3<V1,V2,V3> |
whenAllSucceed(ClosingFuture<V1> future1,
ClosingFuture<V2> future2,
ClosingFuture<V3> future3)
Starts specifying how to combine three
ClosingFutures into a single pipeline, assuming
they all succeed. |
static <V1,V2,V3,V4> |
whenAllSucceed(ClosingFuture<V1> future1,
ClosingFuture<V2> future2,
ClosingFuture<V3> future3,
ClosingFuture<V4> future4)
Starts specifying how to combine four
ClosingFutures into a single pipeline, assuming
they all succeed. |
static <V1,V2,V3,V4,V5> |
whenAllSucceed(ClosingFuture<V1> future1,
ClosingFuture<V2> future2,
ClosingFuture<V3> future3,
ClosingFuture<V4> future4,
ClosingFuture<V5> future5)
Starts specifying how to combine five
ClosingFutures into a single pipeline, assuming
they all succeed. |
static ClosingFuture.Combiner |
whenAllSucceed(java.lang.Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combine
ClosingFutures into a single pipeline, assuming they
all succeed. |
(package private) java.util.concurrent.CountDownLatch |
whenClosedCountDown()
Returns an object that can be used to wait until this objects' deferred closeables have all had
Runnables that close them submitted to each one's closing Executor. |
static <V,U> ClosingFuture.AsyncClosingFunction<V,U> |
withoutCloser(AsyncFunction<V,U> function)
Returns an
ClosingFuture.AsyncClosingFunction that applies an AsyncFunction to an input,
ignoring the DeferredCloser and returning a ClosingFuture derived from the returned
ListenableFuture. |
private static final java.util.logging.Logger logger
private final java.util.concurrent.atomic.AtomicReference<ClosingFuture.State> state
private final ClosingFuture.CloseableList closeables
private final FluentFuture<V> future
private ClosingFuture(ListenableFuture<V> future)
private ClosingFuture(ClosingFuture.ClosingCallable<V> callable, java.util.concurrent.Executor executor)
private ClosingFuture(ClosingFuture.AsyncClosingCallable<V> callable, java.util.concurrent.Executor executor)
public static <V> ClosingFuture<V> submit(ClosingFuture.ClosingCallable<V> callable, java.util.concurrent.Executor executor)
ClosingFuture pipeline by submitting a callable block to an executor.java.util.concurrent.RejectedExecutionException - if the task cannot be scheduled for
executionpublic static <V> ClosingFuture<V> submitAsync(ClosingFuture.AsyncClosingCallable<V> callable, java.util.concurrent.Executor executor)
ClosingFuture pipeline by submitting a callable block to an executor.java.util.concurrent.RejectedExecutionException - if the task cannot be scheduled for
executionpublic static <V> ClosingFuture<V> from(ListenableFuture<V> future)
ClosingFuture pipeline with a ListenableFuture.
future's value will not be closed when the pipeline is done even if V
implements Closeable. In order to start a pipeline with a value that will be closed
when the pipeline is done, use submit(ClosingCallable, Executor) instead.
@Deprecated public static <C extends java.lang.Object & java.lang.AutoCloseable> ClosingFuture<C> eventuallyClosing(ListenableFuture<C> future, java.util.concurrent.Executor closingExecutor)
Futures of closeable types is dangerous in general because the
underlying value may never be closed if the Future is canceled after its operation
begins. Consider replacing code that creates ListenableFutures of closeable types,
including those that pass them to this method, with submit(ClosingCallable,
Executor) in order to ensure that resources do not leak. Or, to start a pipeline with a
ListenableFuture that doesn't create values that should be closed, use from(com.google.common.util.concurrent.ListenableFuture<V>).ClosingFuture pipeline with a ListenableFuture.
If future succeeds, its value will be closed (using closingExecutor) when
the pipeline is done, even if the pipeline is canceled or fails.
Cancelling the pipeline will not cancel future, so that the pipeline can access its
value in order to close it.
future - the future to create the ClosingFuture from. For discussion of the
future's result type C, see DeferredCloser#eventuallyClose(Closeable,
Executor).closingExecutor - the future's result will be closed on this executorpublic static ClosingFuture.Combiner whenAllComplete(java.lang.Iterable<? extends ClosingFuture<?>> futures)
ClosingFutures into a single pipeline.java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the futures, or if any has already been finishedpublic static ClosingFuture.Combiner whenAllComplete(ClosingFuture<?> future1, ClosingFuture<?>... moreFutures)
ClosingFutures into a single pipeline.java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic static ClosingFuture.Combiner whenAllSucceed(java.lang.Iterable<? extends ClosingFuture<?>> futures)
ClosingFutures into a single pipeline, assuming they
all succeed. If any fail, the resulting pipeline will fail.java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the futures, or if any has already been finishedpublic static <V1,V2> ClosingFuture.Combiner2<V1,V2> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2)
ClosingFutures into a single pipeline, assuming
they all succeed. If any fail, the resulting pipeline will fail.
Calling this method allows you to use lambdas or method references typed with the types of
the input ClosingFutures.
java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic static <V1,V2,V3> ClosingFuture.Combiner3<V1,V2,V3> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3)
ClosingFutures into a single pipeline, assuming
they all succeed. If any fail, the resulting pipeline will fail.
Calling this method allows you to use lambdas or method references typed with the types of
the input ClosingFutures.
java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic static <V1,V2,V3,V4> ClosingFuture.Combiner4<V1,V2,V3,V4> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3, ClosingFuture<V4> future4)
ClosingFutures into a single pipeline, assuming
they all succeed. If any fail, the resulting pipeline will fail.
Calling this method allows you to use lambdas or method references typed with the types of
the input ClosingFutures.
java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic static <V1,V2,V3,V4,V5> ClosingFuture.Combiner5<V1,V2,V3,V4,V5> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3, ClosingFuture<V4> future4, ClosingFuture<V5> future5)
ClosingFutures into a single pipeline, assuming
they all succeed. If any fail, the resulting pipeline will fail.
Calling this method allows you to use lambdas or method references typed with the types of
the input ClosingFutures.
java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic static ClosingFuture.Combiner whenAllSucceed(ClosingFuture<?> future1, ClosingFuture<?> future2, ClosingFuture<?> future3, ClosingFuture<?> future4, ClosingFuture<?> future5, ClosingFuture<?> future6, ClosingFuture<?>... moreFutures)
ClosingFutures into a single pipeline, assuming they
all succeed. If any fail, the resulting pipeline will fail.java.lang.IllegalStateException - if a ClosingFuture has already been derived from any of
the arguments, or if any has already been finishedpublic ListenableFuture<?> statusFuture()
get() on the returned
future returns null if the step is successful or throws the same exception that would
be thrown by calling finishToFuture().get() if this were the last step. Calling cancel() on the returned future has no effect on the ClosingFuture pipeline.
statusFuture differs from most methods on ClosingFuture: You can make calls
to statusFuture in addition to the call you make to finishToFuture() or
a derivation method on the same instance. This is important because calling statusFuture alone does not provide a way to close the pipeline.
public <U> ClosingFuture<U> transform(ClosingFuture.ClosingFunction<? super V,U> function, java.util.concurrent.Executor executor)
ClosingFuture pipeline step derived from this one by applying a function
to its value. The function can use a ClosingFuture.DeferredCloser to capture objects to be closed
when the pipeline is done.
If this ClosingFuture fails, the function will not be called, and the derived ClosingFuture will be equivalent to this one.
If the function throws an exception, that exception is used as the result of the derived
ClosingFuture.
Example usage:
ClosingFuture<List<Row>> rowsFuture =
queryFuture.transform((closer, result) -> result.getRows(), executor);
When selecting an executor, note that directExecutor is dangerous in some cases. See
the discussion in the ListenableFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor) documentation. All its warnings
about heavyweight listeners are also applicable to heavyweight functions passed to this method.
After calling this method, you may not call finishToFuture(), finishToValueAndCloser(ValueAndCloserConsumer, Executor), or any other derivation method on
this ClosingFuture.
function - transforms the value of this step to the value of the derived stepexecutor - executor to run the function injava.lang.IllegalStateException - if a ClosingFuture has already been derived from this
one, or if this ClosingFuture has already been finishedpublic <U> ClosingFuture<U> transformAsync(ClosingFuture.AsyncClosingFunction<? super V,U> function, java.util.concurrent.Executor executor)
ClosingFuture pipeline step derived from this one by applying a function
that returns a ClosingFuture to its value. The function can use a ClosingFuture.DeferredCloser to capture objects to be closed when the pipeline is done (other than those
captured by the returned ClosingFuture).
If this ClosingFuture succeeds, the derived one will be equivalent to the one
returned by the function.
If this ClosingFuture fails, the function will not be called, and the derived ClosingFuture will be equivalent to this one.
If the function throws an exception, that exception is used as the result of the derived
ClosingFuture. But if the exception is thrown after the function creates a ClosingFuture, then none of the closeable objects in that ClosingFuture will be
closed.
Usage guidelines for this method:
ListenableFuture or a
ClosingFuture. If possible, prefer calling transform(ClosingFunction,
Executor) instead, with a function that returns the next value directly.
closer.eventuallyClose()
for every closeable object this step creates in order to capture it for later closing.
ClosingFuture. To turn a ListenableFuture into a ClosingFuture call from(ListenableFuture).
ListenableFuture to return a ClosingFuture by wrapping it with a call to
withoutCloser(AsyncFunction)
Example usage:
// Result.getRowsClosingFuture() returns a ClosingFuture.
ClosingFuture<List<Row>> rowsFuture =
queryFuture.transformAsync((closer, result) -> result.getRowsClosingFuture(), executor);
// Result.writeRowsToOutputStreamFuture() returns a ListenableFuture that resolves to the
// number of written rows. openOutputFile() returns a FileOutputStream (which implements
// Closeable).
ClosingFuture<Integer> rowsFuture2 =
queryFuture.transformAsync(
(closer, result) -> {
FileOutputStream fos = closer.eventuallyClose(openOutputFile(), closingExecutor);
return ClosingFuture.from(result.writeRowsToOutputStreamFuture(fos));
},
executor);
// Result.getRowsFuture() returns a ListenableFuture (no new closeables are created).
ClosingFuture<List<Row>> rowsFuture3 =
queryFuture.transformAsync(withoutCloser(Result::getRowsFuture), executor);
When selecting an executor, note that directExecutor is dangerous in some cases. See
the discussion in the ListenableFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor) documentation. All its warnings
about heavyweight listeners are also applicable to heavyweight functions passed to this method.
(Specifically, directExecutor functions should avoid heavyweight operations inside
AsyncClosingFunction.apply. Any heavyweight operations should occur in other threads
responsible for completing the returned ClosingFuture.)
After calling this method, you may not call finishToFuture(), finishToValueAndCloser(ValueAndCloserConsumer, Executor), or any other derivation method on
this ClosingFuture.
function - transforms the value of this step to a ClosingFuture with the value of
the derived stepexecutor - executor to run the function injava.lang.IllegalStateException - if a ClosingFuture has already been derived from this
one, or if this ClosingFuture has already been finishedpublic static <V,U> ClosingFuture.AsyncClosingFunction<V,U> withoutCloser(AsyncFunction<V,U> function)
ClosingFuture.AsyncClosingFunction that applies an AsyncFunction to an input,
ignoring the DeferredCloser and returning a ClosingFuture derived from the returned
ListenableFuture.
Use this method to pass a transformation to transformAsync(AsyncClosingFunction,
Executor) or to catchingAsync(Class, AsyncClosingFunction, Executor) as long as it
meets these conditions:
Closeable objects by calling DeferredCloser#eventuallyClose(Closeable, Executor).
ListenableFuture.
Example usage:
// Result.getRowsFuture() returns a ListenableFuture.
ClosingFuture<List<Row>> rowsFuture =
queryFuture.transformAsync(withoutCloser(Result::getRowsFuture), executor);
function - transforms the value of a ClosingFuture step to a ListenableFuture with the value of a derived steppublic <X extends java.lang.Throwable> ClosingFuture<V> catching(java.lang.Class<X> exceptionType, ClosingFuture.ClosingFunction<? super X,? extends V> fallback, java.util.concurrent.Executor executor)
ClosingFuture pipeline step derived from this one by applying a function
to its exception if it is an instance of a given exception type. The function can use a ClosingFuture.DeferredCloser to capture objects to be closed when the pipeline is done.
If this ClosingFuture succeeds or fails with a different exception type, the
function will not be called, and the derived ClosingFuture will be equivalent to this
one.
If the function throws an exception, that exception is used as the result of the derived
ClosingFuture.
Example usage:
ClosingFuture<QueryResult> queryFuture =
queryFuture.catching(
QueryException.class, (closer, x) -> Query.emptyQueryResult(), executor);
When selecting an executor, note that directExecutor is dangerous in some cases. See
the discussion in the ListenableFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor) documentation. All its warnings
about heavyweight listeners are also applicable to heavyweight functions passed to this method.
After calling this method, you may not call finishToFuture(), finishToValueAndCloser(ValueAndCloserConsumer, Executor), or any other derivation method on
this ClosingFuture.
exceptionType - the exception type that triggers use of fallback. The exception
type is matched against this step's exception. "This step's exception" means the cause of
the ExecutionException thrown by Future.get() on the Future
underlying this step or, if get() throws a different kind of exception, that
exception itself. To avoid hiding bugs and other unrecoverable errors, callers should
prefer more specific types, avoiding Throwable.class in particular.fallback - the function to be called if this step fails with the expected exception type.
The function's argument is this step's exception. "This step's exception" means the cause
of the ExecutionException thrown by Future.get() on the Future
underlying this step or, if get() throws a different kind of exception, that
exception itself.executor - the executor that runs fallback if the input failsprivate <X extends java.lang.Throwable,W extends V> ClosingFuture<V> catchingMoreGeneric(java.lang.Class<X> exceptionType, ClosingFuture.ClosingFunction<? super X,W> fallback, java.util.concurrent.Executor executor)
public <X extends java.lang.Throwable> ClosingFuture<V> catchingAsync(java.lang.Class<X> exceptionType, ClosingFuture.AsyncClosingFunction<? super X,? extends V> fallback, java.util.concurrent.Executor executor)
ClosingFuture pipeline step derived from this one by applying a function
that returns a ClosingFuture to its exception if it is an instance of a given exception
type. The function can use a ClosingFuture.DeferredCloser to capture objects to be closed when the
pipeline is done (other than those captured by the returned ClosingFuture).
If this ClosingFuture fails with an exception of the given type, the derived ClosingFuture will be equivalent to the one returned by the function.
If this ClosingFuture succeeds or fails with a different exception type, the
function will not be called, and the derived ClosingFuture will be equivalent to this
one.
If the function throws an exception, that exception is used as the result of the derived
ClosingFuture. But if the exception is thrown after the function creates a ClosingFuture, then none of the closeable objects in that ClosingFuture will be
closed.
Usage guidelines for this method:
ListenableFuture or a
ClosingFuture. If possible, prefer calling catching(Class,
ClosingFunction, Executor) instead, with a function that returns the next value
directly.
closer.eventuallyClose()
for every closeable object this step creates in order to capture it for later closing.
ClosingFuture. To turn a ListenableFuture into a ClosingFuture call from(ListenableFuture).
ListenableFuture to return a ClosingFuture by wrapping it with a call to
withoutCloser(AsyncFunction)
Example usage:
// Fall back to a secondary input stream in case of IOException.
ClosingFuture<InputStream> inputFuture =
firstInputFuture.catchingAsync(
IOException.class, (closer, x) -> secondaryInputStreamClosingFuture(), executor);
}
When selecting an executor, note that directExecutor is dangerous in some cases. See
the discussion in the ListenableFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor) documentation. All its warnings
about heavyweight listeners are also applicable to heavyweight functions passed to this method.
(Specifically, directExecutor functions should avoid heavyweight operations inside
AsyncClosingFunction.apply. Any heavyweight operations should occur in other threads
responsible for completing the returned ClosingFuture.)
After calling this method, you may not call finishToFuture(), finishToValueAndCloser(ValueAndCloserConsumer, Executor), or any other derivation method on
this ClosingFuture.
exceptionType - the exception type that triggers use of fallback. The exception
type is matched against this step's exception. "This step's exception" means the cause of
the ExecutionException thrown by Future.get() on the Future
underlying this step or, if get() throws a different kind of exception, that
exception itself. To avoid hiding bugs and other unrecoverable errors, callers should
prefer more specific types, avoiding Throwable.class in particular.fallback - the function to be called if this step fails with the expected exception type.
The function's argument is this step's exception. "This step's exception" means the cause
of the ExecutionException thrown by Future.get() on the Future
underlying this step or, if get() throws a different kind of exception, that
exception itself.executor - the executor that runs fallback if the input failsprivate <X extends java.lang.Throwable,W extends V> ClosingFuture<V> catchingAsyncMoreGeneric(java.lang.Class<X> exceptionType, ClosingFuture.AsyncClosingFunction<? super X,W> fallback, java.util.concurrent.Executor executor)
public FluentFuture<V> finishToFuture()
ClosingFuture pipeline.
The returned Future is completed when the pipeline's computation completes, or when
the pipeline is cancelled.
All objects the pipeline has captured for closing will begin to be closed asynchronously
after the returned Future is done: the future completes before closing starts,
rather than once it has finished.
After calling this method, you may not call finishToValueAndCloser(ValueAndCloserConsumer, Executor), this method, or any other
derivation method on this ClosingFuture.
Future that represents the final value or exception of the pipelinepublic void finishToValueAndCloser(ClosingFuture.ValueAndCloserConsumer<? super V> consumer, java.util.concurrent.Executor executor)
ClosingFuture pipeline. When this step is done,
receiver will be called with an object that contains the result of the operation. The
receiver can store the ClosingFuture.ValueAndCloser outside the receiver for later synchronous use.
After calling this method, you may not call finishToFuture(), this method again, or
any other derivation method on this ClosingFuture.
consumer - a callback whose method will be called (using executor) when this
operation is doneprivate static <C,V extends C> void provideValueAndCloser(ClosingFuture.ValueAndCloserConsumer<C> consumer, ClosingFuture<V> closingFuture)
public boolean cancel(boolean mayInterruptIfRunning)
cancel is called, this step should never
run.
If successful, causes the objects captured by this step (if already started) and its input
step(s) for later closing to be closed on their respective Executors. If any such calls
specified MoreExecutors.directExecutor(), those objects will be closed synchronously.
mayInterruptIfRunning - true if the thread executing this task should be
interrupted; otherwise, in-progress tasks are allowed to complete, but the step will be
cancelled regardlessfalse if the step could not be cancelled, typically because it has already
completed normally; true otherwiseprivate void close()
private <U> ClosingFuture<U> derive(FluentFuture<U> future)
private void becomeSubsumedInto(ClosingFuture.CloseableList otherCloseables)
public java.lang.String toString()
toString in class java.lang.Objectprotected void finalize()
finalize in class java.lang.Objectprivate static void closeQuietly(@CheckForNull
java.lang.AutoCloseable closeable,
java.util.concurrent.Executor executor)
private void checkAndUpdateState(ClosingFuture.State oldState, ClosingFuture.State newState)
private boolean compareAndUpdateState(ClosingFuture.State oldState, ClosingFuture.State newState)
java.util.concurrent.CountDownLatch whenClosedCountDown()
Runnables that close them submitted to each one's closing Executor.