
org.hibernate.search.util.common.impl.CancellableExecutionCompletableFuture Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-search-util-common Show documentation
Show all versions of hibernate-search-util-common Show documentation
Hibernate Search common utilities
The newest version!
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.search.util.common.impl;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.hibernate.search.util.common.logging.impl.CommonMiscLog;
/**
* A {@link CompletableFuture} that, upon cancellation,
* will not only change its state, but also try to cancel (abort) the corresponding operation.
* @param The return type of the future.
*/
class CancellableExecutionCompletableFuture extends CompletableFuture {
private final Future> future;
CancellableExecutionCompletableFuture(Runnable runnable, ExecutorService executor) {
this.future = executor.submit( new CompletingRunnable<>( this, runnable ) );
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
/*
* Calling future.cancel() may trigger an exception in the operation that may
* end up setting 'this' as completed exceptionally because of the failure...
* Thus we mark 'this' as cancelled *first*, so that any exception in the operation
* from now on will be ignored.
*/
CommonMiscLog.INSTANCE.cancellingCompletableFuture( this, mayInterruptIfRunning );
super.cancel( mayInterruptIfRunning );
CommonMiscLog.INSTANCE.cancellingFuture( future, mayInterruptIfRunning );
boolean cancelled = future.cancel( mayInterruptIfRunning );
if ( !cancelled ) {
CommonMiscLog.INSTANCE.cancellingFutureFailed( future, mayInterruptIfRunning );
}
return cancelled;
}
private static class CompletingRunnable implements Runnable {
private final CompletableFuture future;
private final Runnable delegate;
private CompletingRunnable(CompletableFuture future, Runnable delegate) {
this.future = future;
this.delegate = delegate;
}
@Override
public String toString() {
return "CompletingRunnable[" +
"future=" + future +
", delegate=" + delegate +
']';
}
@Override
public void run() {
try {
delegate.run();
future.complete( null );
}
catch (Throwable t) {
if ( future.isCancelled() ) {
// The operation probably failed because of the cancellation,
// but try to keep track of the failure anyway.
Futures.getThrowableNow( future ).addSuppressed( t );
}
else {
future.completeExceptionally( t );
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy