Use a COW list in Peer instead of protecting pendingPings under the peer lock.

This commit is contained in:
Mike Hearn 2012-12-24 23:57:28 +00:00
parent 22ff79dd8a
commit ac61578e8a

View file

@ -21,7 +21,6 @@ import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.utils.EventListenerInvoker; import com.google.bitcoin.utils.EventListenerInvoker;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import org.jboss.netty.channel.*; import org.jboss.netty.channel.*;
@ -86,8 +85,8 @@ public class Peer {
// simultaneously if we were to receive a newly solved block whilst parts of the chain are streaming to us. // simultaneously if we were to receive a newly solved block whilst parts of the chain are streaming to us.
private HashSet<Sha256Hash> pendingBlockDownloads = new HashSet<Sha256Hash>(); private HashSet<Sha256Hash> pendingBlockDownloads = new HashSet<Sha256Hash>();
// Outstanding pings against this peer and how long the last one took to complete. Locked under the Peer lock. // Outstanding pings against this peer and how long the last one took to complete.
private List<PendingPing> pendingPings; private CopyOnWriteArrayList<PendingPing> pendingPings;
private long[] lastPingTimes; private long[] lastPingTimes;
private static final int PING_MOVING_AVERAGE_WINDOW = 20; private static final int PING_MOVING_AVERAGE_WINDOW = 20;
@ -110,7 +109,7 @@ public class Peer {
this.fastCatchupTimeSecs = params.genesisBlock.getTimeSeconds(); this.fastCatchupTimeSecs = params.genesisBlock.getTimeSeconds();
this.isAcked = false; this.isAcked = false;
this.handler = new PeerHandler(); this.handler = new PeerHandler();
this.pendingPings = Lists.newLinkedList(); this.pendingPings = new CopyOnWriteArrayList<PendingPing>();
this.lastPingTimes = null; this.lastPingTimes = null;
} }
@ -848,14 +847,13 @@ public class Peer {
private void processPong(Pong m) { private void processPong(Pong m) {
PendingPing ping = null; PendingPing ping = null;
synchronized (this) { // Iterates over a snapshot of the list, so we can run unlocked here.
ListIterator<PendingPing> it = pendingPings.listIterator(); ListIterator<PendingPing> it = pendingPings.listIterator();
while (it.hasNext()) { while (it.hasNext()) {
ping = it.next(); ping = it.next();
if (m.getNonce() == ping.nonce) { if (m.getNonce() == ping.nonce) {
it.remove(); pendingPings.remove(ping);
break; break;
}
} }
} }
// This line may trigger an event listener being run on the same thread, if one is attached to the // This line may trigger an event listener being run on the same thread, if one is attached to the