- java.lang.Object
-
- com.google.common.util.concurrent.ClosingFuture<V>
-
- Type Parameters:
V
- the type of the value of this step
@Beta @DoNotMock("Use ClosingFuture.from(Futures.immediate*Future)") public final class ClosingFuture<V extends @Nullable Object> extends Object
A step in a pipeline of an asynchronous computation. When the last step in the computation is complete, some objects captured during the computation are closed.A pipeline of
ClosingFuture
s 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.- A pipeline starts at its leaf step (or steps), which is created from either a callable
block or a
ListenableFuture
. - Each other step is derived from one or more input steps. At each step, zero or more objects can be captured for later closing.
- There is one last step (the root of the tree), from which you can extract the final result of the computation. After that result is available (or the computation fails), all objects captured by any of the steps in the pipeline are closed.
Starting a pipeline
Start aClosingFuture
pipeline from a callable block that may capture objects for later closing. To start a pipeline from aListenableFuture
that doesn't create resources that should be closed later, you can usefrom(ListenableFuture)
instead.Derived steps
AClosingFuture
step can be derived from one or more inputClosingFuture
steps in ways similar toFluentFuture
s:- by transforming the value from a successful input step,
- by catching the exception from a failed input step, or
- by combining the results of several input steps.
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.
Transforming
To derive the next step by asynchronously applying a function to an input step's value, calltransform(ClosingFunction, Executor)
ortransformAsync(AsyncClosingFunction, Executor)
on the input step.Catching
To derive the next step from a failed input step, callcatching(Class, ClosingFunction, Executor)
orcatchingAsync(Class, AsyncClosingFunction, Executor)
on the input step.Combining
To derive aClosingFuture
from two or more input steps, pass the input steps towhenAllComplete(Iterable)
orwhenAllSucceed(Iterable)
or its overloads.Cancelling
Any step in a pipeline can be cancelled, even after another step has been derived, with the same semantics as cancelling aFuture
. In addition, a successfully cancelled step will immediately start closing all objects captured for later closing by it and by its input steps.Ending a pipeline
EachClosingFuture
pipeline must be ended. To end a pipeline, decide whether you want to close the captured objects automatically or manually.Automatically closing
You can extract aFuture
that represents the result of the last step in the pipeline by callingfinishToFuture()
. All objects the pipeline has captured for closing will begin to be closed asynchronously after the returnedFuture
is done: the future completes before closing starts, rather than once it has finished.
In this example, when theFluentFuture<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();
userName
Future
is done, the transaction and the query result cursor will both be closed, even if the operation is cancelled or fails.Manually closing
If you want to close the captured objects manually, after you've used the final result, callfinishToValueAndCloser(ValueAndCloserConsumer, Executor)
to get an object that holds the final result. You then callClosingFuture.ValueAndCloser.closeAsync()
to close the captured objects.
In this example, whenClosingFuture.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(); }
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.- Since:
- 30.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
ClosingFuture.AsyncClosingCallable<V extends @Nullable Object>
An operation that computes aClosingFuture
of a result.static interface
ClosingFuture.AsyncClosingFunction<T extends @Nullable Object,U extends @Nullable Object>
A function from an input to aClosingFuture
of a result.static interface
ClosingFuture.ClosingCallable<V extends @Nullable Object>
An operation that computes a result.static interface
ClosingFuture.ClosingFunction<T extends @Nullable Object,U extends @Nullable Object>
A function from an input to a result.static class
ClosingFuture.Combiner
A builder of aClosingFuture
step that is derived from more than one input step.static class
ClosingFuture.Combiner2<V1 extends @Nullable Object,V2 extends @Nullable Object>
A genericClosingFuture.Combiner
that lets you use a lambda or method reference to combine twoClosingFuture
s.static class
ClosingFuture.Combiner3<V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object>
A genericClosingFuture.Combiner
that lets you use a lambda or method reference to combine threeClosingFuture
s.static class
ClosingFuture.Combiner4<V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object>
A genericClosingFuture.Combiner
that lets you use a lambda or method reference to combine fourClosingFuture
s.static class
ClosingFuture.Combiner5<V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object,V5 extends @Nullable Object>
A genericClosingFuture.Combiner
that lets you use a lambda or method reference to combine fiveClosingFuture
s.static class
ClosingFuture.DeferredCloser
An object that can capture objects to be closed later, when aClosingFuture
pipeline is done.static class
ClosingFuture.Peeker
An object that can return the value of theClosingFuture
s that are passed towhenAllComplete(Iterable)
orwhenAllSucceed(Iterable)
.static class
ClosingFuture.ValueAndCloser<V extends @Nullable Object>
An object that holds the final result of an asynchronousClosingFuture
operation and allows the user to close all the closeable objects that were captured during it for later closing.static interface
ClosingFuture.ValueAndCloserConsumer<V extends @Nullable Object>
Represents an operation that accepts aClosingFuture.ValueAndCloser
for the last step in aClosingFuture
pipeline.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description boolean
cancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this step.<X extends Throwable>
ClosingFuture<V>catching(Class<X> exceptionType, ClosingFuture.ClosingFunction<? super X,? extends V> fallback, Executor executor)
Returns a newClosingFuture
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 Throwable>
ClosingFuture<V>catchingAsync(Class<X> exceptionType, ClosingFuture.AsyncClosingFunction<? super X,? extends V> fallback, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function that returns aClosingFuture
to its exception if it is an instance of a given exception type.static <C extends @Nullable Object & @Nullable AutoCloseable>
ClosingFuture<C>eventuallyClosing(ListenableFuture<C> future, Executor closingExecutor)
protected void
finalize()
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.FluentFuture<V>
finishToFuture()
Marks this step as the last step in theClosingFuture
pipeline.void
finishToValueAndCloser(ClosingFuture.ValueAndCloserConsumer<? super V> consumer, Executor executor)
Marks this step as the last step in theClosingFuture
pipeline.static <V extends @Nullable Object>
ClosingFuture<V>from(ListenableFuture<V> future)
Starts aClosingFuture
pipeline with aListenableFuture
.ListenableFuture<?>
statusFuture()
Returns a future that finishes when this step does.static <V extends @Nullable Object>
ClosingFuture<V>submit(ClosingFuture.ClosingCallable<V> callable, Executor executor)
Starts aClosingFuture
pipeline by submitting a callable block to an executor.static <V extends @Nullable Object>
ClosingFuture<V>submitAsync(ClosingFuture.AsyncClosingCallable<V> callable, Executor executor)
Starts aClosingFuture
pipeline by submitting a callable block to an executor.String
toString()
Returns a string representation of the object.<U extends @Nullable Object>
ClosingFuture<U>transform(ClosingFuture.ClosingFunction<? super V,U> function, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function to its value.<U extends @Nullable Object>
ClosingFuture<U>transformAsync(ClosingFuture.AsyncClosingFunction<? super V,U> function, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function that returns aClosingFuture
to its value.static ClosingFuture.Combiner
whenAllComplete(ClosingFuture<?> future1, ClosingFuture<?>... moreFutures)
Starts specifying how to combineClosingFuture
s into a single pipeline.static ClosingFuture.Combiner
whenAllComplete(Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combineClosingFuture
s 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 combineClosingFuture
s into a single pipeline, assuming they all succeed.static <V1 extends @Nullable Object,V2 extends @Nullable Object>
ClosingFuture.Combiner2<V1,V2>whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2)
Starts specifying how to combine twoClosingFuture
s into a single pipeline, assuming they all succeed.static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object>
ClosingFuture.Combiner3<V1,V2,V3>whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3)
Starts specifying how to combine threeClosingFuture
s into a single pipeline, assuming they all succeed.static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object>
ClosingFuture.Combiner4<V1,V2,V3,V4>whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3, ClosingFuture<V4> future4)
Starts specifying how to combine fourClosingFuture
s into a single pipeline, assuming they all succeed.static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object,V5 extends @Nullable Object>
ClosingFuture.Combiner5<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 fiveClosingFuture
s into a single pipeline, assuming they all succeed.static ClosingFuture.Combiner
whenAllSucceed(Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combineClosingFuture
s into a single pipeline, assuming they all succeed.static <V extends @Nullable Object,U extends @Nullable Object>
ClosingFuture.AsyncClosingFunction<V,U>withoutCloser(AsyncFunction<V,U> function)
Returns anClosingFuture.AsyncClosingFunction
that applies anAsyncFunction
to an input, ignoring the DeferredCloser and returning aClosingFuture
derived from the returnedListenableFuture
.
-
-
-
Method Detail
-
submit
public static <V extends @Nullable Object> ClosingFuture<V> submit(ClosingFuture.ClosingCallable<V> callable, Executor executor)
Starts aClosingFuture
pipeline by submitting a callable block to an executor.- Throws:
RejectedExecutionException
- if the task cannot be scheduled for execution
-
submitAsync
public static <V extends @Nullable Object> ClosingFuture<V> submitAsync(ClosingFuture.AsyncClosingCallable<V> callable, Executor executor)
Starts aClosingFuture
pipeline by submitting a callable block to an executor.- Throws:
RejectedExecutionException
- if the task cannot be scheduled for execution- Since:
- 30.1
-
from
public static <V extends @Nullable Object> ClosingFuture<V> from(ListenableFuture<V> future)
Starts aClosingFuture
pipeline with aListenableFuture
.future
's value will not be closed when the pipeline is done even ifV
implementsCloseable
. In order to start a pipeline with a value that will be closed when the pipeline is done, usesubmit(ClosingCallable, Executor)
instead.
-
eventuallyClosing
@Deprecated public static <C extends @Nullable Object & @Nullable AutoCloseable> ClosingFuture<C> eventuallyClosing(ListenableFuture<C> future, Executor closingExecutor)
Deprecated.CreatingFuture
s of closeable types is dangerous in general because the underlying value may never be closed if theFuture
is canceled after its operation begins. Consider replacing code that createsListenableFuture
s of closeable types, including those that pass them to this method, withsubmit(ClosingCallable, Executor)
in order to ensure that resources do not leak. Or, to start a pipeline with aListenableFuture
that doesn't create values that should be closed, usefrom(com.google.common.util.concurrent.ListenableFuture<V>)
.Starts aClosingFuture
pipeline with aListenableFuture
.If
future
succeeds, its value will be closed (usingclosingExecutor)
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.- Parameters:
future
- the future to create theClosingFuture
from. For discussion of the future's result typeC
, seeDeferredCloser#eventuallyClose(Closeable, Executor)
.closingExecutor
- the future's result will be closed on this executor
-
whenAllComplete
public static ClosingFuture.Combiner whenAllComplete(Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combineClosingFuture
s into a single pipeline.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of thefutures
, or if any has already been finished
-
whenAllComplete
public static ClosingFuture.Combiner whenAllComplete(ClosingFuture<?> future1, ClosingFuture<?>... moreFutures)
Starts specifying how to combineClosingFuture
s into a single pipeline.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
whenAllSucceed
public static ClosingFuture.Combiner whenAllSucceed(Iterable<? extends ClosingFuture<?>> futures)
Starts specifying how to combineClosingFuture
s into a single pipeline, assuming they all succeed. If any fail, the resulting pipeline will fail.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of thefutures
, or if any has already been finished
-
whenAllSucceed
public static <V1 extends @Nullable Object,V2 extends @Nullable Object> ClosingFuture.Combiner2<V1,V2> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2)
Starts specifying how to combine twoClosingFuture
s 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
ClosingFuture
s.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
whenAllSucceed
public static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object> ClosingFuture.Combiner3<V1,V2,V3> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3)
Starts specifying how to combine threeClosingFuture
s 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
ClosingFuture
s.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
whenAllSucceed
public static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object> ClosingFuture.Combiner4<V1,V2,V3,V4> whenAllSucceed(ClosingFuture<V1> future1, ClosingFuture<V2> future2, ClosingFuture<V3> future3, ClosingFuture<V4> future4)
Starts specifying how to combine fourClosingFuture
s 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
ClosingFuture
s.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
whenAllSucceed
public static <V1 extends @Nullable Object,V2 extends @Nullable Object,V3 extends @Nullable Object,V4 extends @Nullable Object,V5 extends @Nullable Object> ClosingFuture.Combiner5<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 fiveClosingFuture
s 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
ClosingFuture
s.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
whenAllSucceed
public static ClosingFuture.Combiner whenAllSucceed(ClosingFuture<?> future1, ClosingFuture<?> future2, ClosingFuture<?> future3, ClosingFuture<?> future4, ClosingFuture<?> future5, ClosingFuture<?> future6, ClosingFuture<?>... moreFutures)
Starts specifying how to combineClosingFuture
s into a single pipeline, assuming they all succeed. If any fail, the resulting pipeline will fail.- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from any of the arguments, or if any has already been finished
-
statusFuture
public ListenableFuture<?> statusFuture()
Returns a future that finishes when this step does. Callingget()
on the returned future returnsnull
if the step is successful or throws the same exception that would be thrown by callingfinishToFuture().get()
if this were the last step. Callingcancel()
on the returned future has no effect on theClosingFuture
pipeline.statusFuture
differs from most methods onClosingFuture
: You can make calls tostatusFuture
in addition to the call you make tofinishToFuture()
or a derivation method on the same instance. This is important because callingstatusFuture
alone does not provide a way to close the pipeline.
-
transform
public <U extends @Nullable Object> ClosingFuture<U> transform(ClosingFuture.ClosingFunction<? super V,U> function, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function to its value. The function can use aClosingFuture.DeferredCloser
to capture objects to be closed when the pipeline is done.If this
ClosingFuture
fails, the function will not be called, and the derivedClosingFuture
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 theListenableFuture.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 thisClosingFuture
.- Parameters:
function
- transforms the value of this step to the value of the derived stepexecutor
- executor to run the function in- Returns:
- the derived step
- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from this one, or if thisClosingFuture
has already been finished
-
transformAsync
public <U extends @Nullable Object> ClosingFuture<U> transformAsync(ClosingFuture.AsyncClosingFunction<? super V,U> function, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function that returns aClosingFuture
to its value. The function can use aClosingFuture.DeferredCloser
to capture objects to be closed when the pipeline is done (other than those captured by the returnedClosingFuture
).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 derivedClosingFuture
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 aClosingFuture
, then none of the closeable objects in thatClosingFuture
will be closed.Usage guidelines for this method:
- Use this method only when calling an API that returns a
ListenableFuture
or aClosingFuture
. If possible, prefer callingtransform(ClosingFunction, Executor)
instead, with a function that returns the next value directly. - Call
closer.eventuallyClose()
for every closeable object this step creates in order to capture it for later closing. - Return a
ClosingFuture
. To turn aListenableFuture
into aClosingFuture
callfrom(ListenableFuture)
. - In case this step doesn't create new closeables, you can adapt an API that returns a
ListenableFuture
to return aClosingFuture
by wrapping it with a call towithoutCloser(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 theListenableFuture.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 insideAsyncClosingFunction.apply
. Any heavyweight operations should occur in other threads responsible for completing the returnedClosingFuture
.)After calling this method, you may not call
finishToFuture()
,finishToValueAndCloser(ValueAndCloserConsumer, Executor)
, or any other derivation method on thisClosingFuture
.- Parameters:
function
- transforms the value of this step to aClosingFuture
with the value of the derived stepexecutor
- executor to run the function in- Returns:
- the derived step
- Throws:
IllegalStateException
- if aClosingFuture
has already been derived from this one, or if thisClosingFuture
has already been finished
- Use this method only when calling an API that returns a
-
withoutCloser
public static <V extends @Nullable Object,U extends @Nullable Object> ClosingFuture.AsyncClosingFunction<V,U> withoutCloser(AsyncFunction<V,U> function)
Returns anClosingFuture.AsyncClosingFunction
that applies anAsyncFunction
to an input, ignoring the DeferredCloser and returning aClosingFuture
derived from the returnedListenableFuture
.Use this method to pass a transformation to
transformAsync(AsyncClosingFunction, Executor)
or tocatchingAsync(Class, AsyncClosingFunction, Executor)
as long as it meets these conditions:- It does not need to capture any
Closeable
objects by callingDeferredCloser#eventuallyClose(Closeable, Executor)
. - It returns a
ListenableFuture
.
Example usage:
// Result.getRowsFuture() returns a ListenableFuture. ClosingFuture<List<Row>> rowsFuture = queryFuture.transformAsync(withoutCloser(Result::getRowsFuture), executor);
- Parameters:
function
- transforms the value of aClosingFuture
step to aListenableFuture
with the value of a derived step
- It does not need to capture any
-
catching
public <X extends Throwable> ClosingFuture<V> catching(Class<X> exceptionType, ClosingFuture.ClosingFunction<? super X,? extends V> fallback, Executor executor)
Returns a newClosingFuture
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 aClosingFuture.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 derivedClosingFuture
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 theListenableFuture.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 thisClosingFuture
.- Parameters:
exceptionType
- the exception type that triggers use offallback
. The exception type is matched against this step's exception. "This step's exception" means the cause of theExecutionException
thrown byFuture.get()
on theFuture
underlying this step or, ifget()
throws a different kind of exception, that exception itself. To avoid hiding bugs and other unrecoverable errors, callers should prefer more specific types, avoidingThrowable.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 theExecutionException
thrown byFuture.get()
on theFuture
underlying this step or, ifget()
throws a different kind of exception, that exception itself.executor
- the executor that runsfallback
if the input fails
-
catchingAsync
public <X extends Throwable> ClosingFuture<V> catchingAsync(Class<X> exceptionType, ClosingFuture.AsyncClosingFunction<? super X,? extends V> fallback, Executor executor)
Returns a newClosingFuture
pipeline step derived from this one by applying a function that returns aClosingFuture
to its exception if it is an instance of a given exception type. The function can use aClosingFuture.DeferredCloser
to capture objects to be closed when the pipeline is done (other than those captured by the returnedClosingFuture
).If this
ClosingFuture
fails with an exception of the given type, the derivedClosingFuture
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 derivedClosingFuture
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 aClosingFuture
, then none of the closeable objects in thatClosingFuture
will be closed.Usage guidelines for this method:
- Use this method only when calling an API that returns a
ListenableFuture
or aClosingFuture
. If possible, prefer callingcatching(Class, ClosingFunction, Executor)
instead, with a function that returns the next value directly. - Call
closer.eventuallyClose()
for every closeable object this step creates in order to capture it for later closing. - Return a
ClosingFuture
. To turn aListenableFuture
into aClosingFuture
callfrom(ListenableFuture)
. - In case this step doesn't create new closeables, you can adapt an API that returns a
ListenableFuture
to return aClosingFuture
by wrapping it with a call towithoutCloser(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 theListenableFuture.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 insideAsyncClosingFunction.apply
. Any heavyweight operations should occur in other threads responsible for completing the returnedClosingFuture
.)After calling this method, you may not call
finishToFuture()
,finishToValueAndCloser(ValueAndCloserConsumer, Executor)
, or any other derivation method on thisClosingFuture
.- Parameters:
exceptionType
- the exception type that triggers use offallback
. The exception type is matched against this step's exception. "This step's exception" means the cause of theExecutionException
thrown byFuture.get()
on theFuture
underlying this step or, ifget()
throws a different kind of exception, that exception itself. To avoid hiding bugs and other unrecoverable errors, callers should prefer more specific types, avoidingThrowable.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 theExecutionException
thrown byFuture.get()
on theFuture
underlying this step or, ifget()
throws a different kind of exception, that exception itself.executor
- the executor that runsfallback
if the input fails
- Use this method only when calling an API that returns a
-
finishToFuture
public FluentFuture<V> finishToFuture()
Marks this step as the last step in theClosingFuture
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 thisClosingFuture
.- Returns:
- a
Future
that represents the final value or exception of the pipeline
-
finishToValueAndCloser
public void finishToValueAndCloser(ClosingFuture.ValueAndCloserConsumer<? super V> consumer, Executor executor)
Marks this step as the last step in theClosingFuture
pipeline. When this step is done,receiver
will be called with an object that contains the result of the operation. The receiver can store theClosingFuture.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 thisClosingFuture
.- Parameters:
consumer
- a callback whose method will be called (usingexecutor
) when this operation is done
-
cancel
@CanIgnoreReturnValue public boolean cancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this step. This attempt will fail if the step has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this step has not started whencancel
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
Executor
s. If any such calls specifiedMoreExecutors.directExecutor()
, those objects will be closed synchronously.- Parameters:
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 regardless- Returns:
false
if the step could not be cancelled, typically because it has already completed normally;true
otherwise
-
toString
public String toString()
Description copied from class:java.lang.Object
Returns a string representation of the object. In general, thetoString
method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.The
toString
method for classObject
returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@
', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:getClass().getName() + '@' + Integer.toHexString(hashCode())
-
finalize
protected void finalize()
Description copied from class:java.lang.Object
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides thefinalize
method to dispose of system resources or to perform other cleanup.The general contract of
finalize
is that it is invoked if and when the Java™ virtual machine has determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, except as a result of an action taken by the finalization of some other object or class which is ready to be finalized. Thefinalize
method may take any action, including making this object available again to other threads; the usual purpose offinalize
, however, is to perform cleanup actions before the object is irrevocably discarded. For example, the finalize method for an object that represents an input/output connection might perform explicit I/O transactions to break the connection before the object is permanently discarded.The
finalize
method of classObject
performs no special action; it simply returns normally. Subclasses ofObject
may override this definition.The Java programming language does not guarantee which thread will invoke the
finalize
method for any given object. It is guaranteed, however, that the thread that invokes finalize will not be holding any user-visible synchronization locks when finalize is invoked. If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates.After the
finalize
method has been invoked for an object, no further action is taken until the Java virtual machine has again determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, including possible actions by other objects or classes which are ready to be finalized, at which point the object may be discarded.The
finalize
method is never invoked more than once by a Java virtual machine for any given object.Any exception thrown by the
finalize
method causes the finalization of this object to be halted, but is otherwise ignored.- Overrides:
finalize
in classObject
- See Also:
WeakReference
,PhantomReference
-
-