InternalUtils: new helper getUninterruptibly() to replace Guava method

Update usages in `PeerGroup` and `PeerTest`.
This commit is contained in:
Sean Gilligan 2023-10-01 12:24:39 -07:00 committed by Andreas Schildbach
parent 04a783282d
commit 5513f7dff0
3 changed files with 33 additions and 4 deletions

View File

@ -19,6 +19,8 @@ package org.bitcoinj.base.internal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
/**
@ -93,4 +95,30 @@ public class InternalUtils {
public static String commaJoin(String... strings) {
return Arrays.stream(strings).filter(Objects::nonNull).collect(Collectors.joining(", "));
}
/**
* Get a future's value <q>uninterruptibly</q> by temporarily ignoring {@link InterruptedException}, but making
* sure we re-set the thread's interrupt status, so higher-level code on the thread can handle the
* interruption properly. Based upon the Guava implementation.
* @param future future with value to get
* @param <V> type of value
* @return the value
* @throws ExecutionException if the computation through an exception
*/
public static <V> V getUninterruptibly(Future<V> future) throws ExecutionException {
boolean interrupted = false;
try {
while (true) {
try {
return future.get();
} catch (InterruptedException e) {
interrupted = true;
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
}

View File

@ -25,6 +25,7 @@ import com.google.common.util.concurrent.Runnables;
import com.google.common.util.concurrent.Uninterruptibles;
import net.jcip.annotations.GuardedBy;
import org.bitcoinj.base.Network;
import org.bitcoinj.base.internal.InternalUtils;
import org.bitcoinj.base.internal.PlatformUtils;
import org.bitcoinj.base.internal.Stopwatch;
import org.bitcoinj.base.internal.TimeUtils;
@ -1528,7 +1529,7 @@ public class PeerGroup implements TransactionBroadcaster {
peers.size(), pendingPeers.size(), maxConnections);
CompletableFuture<SocketAddress> future = channels.openConnection(address.toSocketAddress(), peer);
if (future.isDone())
Uninterruptibles.getUninterruptibly(future);
InternalUtils.getUninterruptibly(future);
} catch (ExecutionException e) {
Throwable cause = Throwables.getRootCause(e);
log.warn("Failed to connect to " + address + ": " + cause.getMessage());

View File

@ -17,11 +17,11 @@
package org.bitcoinj.core;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Uninterruptibles;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Coin;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.base.Sha256Hash;
import org.bitcoinj.base.internal.InternalUtils;
import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.core.listeners.BlocksDownloadedEventListener;
import org.bitcoinj.core.listeners.PreMessageReceivedEventListener;
@ -779,8 +779,8 @@ public class PeerTest extends TestWithNetworkConnections {
connectWithVersion(500, Services.NODE_NETWORK);
// We must wait uninterruptibly here because connect[WithVersion] generates a peer that interrupts the current
// thread when it disconnects.
Uninterruptibles.getUninterruptibly(connectedFuture);
Uninterruptibles.getUninterruptibly(disconnectedFuture);
InternalUtils.getUninterruptibly(connectedFuture);
InternalUtils.getUninterruptibly(disconnectedFuture);
try {
peer.writeTarget.writeBytes(new byte[1]);
fail();