From 6258f4c51b1f5632f092db93bbce1ef3eb10bd18 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Mon, 18 Nov 2024 10:57:34 -0500 Subject: rmulticast.ReceivedSet: optimize insertion and search --- .../java/derms/net/rmulticast/ReceivedSet.java | 74 ++++++++++++++-------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/src/main/java/derms/net/rmulticast/ReceivedSet.java b/src/main/java/derms/net/rmulticast/ReceivedSet.java index 5fd8ce5..c71a968 100644 --- a/src/main/java/derms/net/rmulticast/ReceivedSet.java +++ b/src/main/java/derms/net/rmulticast/ReceivedSet.java @@ -1,17 +1,15 @@ package derms.net.rmulticast; import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; class ReceivedSet { - private final Queue> received; + private final Map> received; ReceivedSet() { - this.received = new ConcurrentLinkedQueue>(); + this.received = new ConcurrentHashMap>(); } /** @@ -20,20 +18,15 @@ class ReceivedSet { * @param msg The message to add to the set. * @return True if the set did not already contain the specified message. */ - // TODO: faster insertion. boolean add(Message msg) { - if (contains(msg)) - return false; - received.add(msg); - return true; + return received.put(msg.id(), new Entry(msg)) == null; } - // TODO: faster search. Message getByID(MessageID mid) throws NoSuchElementException { - for (Message msg : received) - if (msg.id().equals(mid)) - return msg; - throw new NoSuchElementException("message " + mid + " not in received list."); + Entry e = received.get(mid); + if (e == null) + throw new NoSuchElementException("message " + mid + " not in received list."); + return e.msg; } boolean contains(MessageID mid) { @@ -51,31 +44,56 @@ class ReceivedSet { /** Remove the specified message from the set, if it is present. */ void remove(Message msg) { - received.remove(msg); + received.remove(msg.id()); } /** Retrieves, but does not remove, the oldest message, or returns null if the set is empty. */ Message peekOldest() { - return received.peek(); + Entry oldest = null; + for (Entry e : received.values()) + if (oldest == null || e.timestamp.isBefore(oldest.timestamp)) + oldest = e; + if (oldest == null) + return null; + return oldest.msg; } Message mostRecentSentBy(InetAddress member) throws NoSuchElementException { - Message recent = null; - for (Message msg : received) { - if (msg.sender.equals(member)) - recent = msg; - } + Entry recent = null; + for (Entry e : received.values()) + if (e.msg.sender.equals(member) && (recent == null || e.timestamp.isAfter(recent.timestamp))) + recent = e; if (recent == null) throw new NoSuchElementException("no message from " + member + " in received list."); - return recent; + return recent.msg; } List> allSentBy(InetAddress sender) { List> sent = new ArrayList>(); - for (Message msg : received) { - if (msg.sender.equals(sender)) - sent.add(msg); + for (Entry e : received.values()) { + if (e.msg.sender.equals(sender)) + sent.add(e.msg); } return sent; } + + private static class Entry { + private final Message msg; + private final Instant timestamp; // The time at which the entry was added to the set. + + private Entry(Message msg) { + this.msg = msg; + this.timestamp = Instant.now(); + } + + @Override + public int hashCode() { + return msg.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return msg.equals(obj); + } + } } -- cgit v1.2.3