diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index e7b91404d..2e077f64d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -102,8 +102,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { /** * A collection of PacketCollectors which collects packets for a specified filter * and perform blocking and polling operations on the result queue. + *

+ * We use a ConcurrentLinkedQueue here, because its Iterator is weakly + * consistent and we want {@link #invokePacketCollectors(Packet)} for-each + * loop to be lock free. As drawback, removing a PacketCollector is O(n). + * The alternative would be a synchronized HashSet, but this would mean a + * synchronized block around every usage of collectors. + *

*/ - protected final Collection collectors = new ConcurrentLinkedQueue(); + private final Collection collectors = new ConcurrentLinkedQueue(); /** * List of PacketListeners that will be notified when a new packet was received. @@ -658,15 +665,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { collectors.remove(collector); } - /** - * Get the collection of all packet collectors for this connection. - * - * @return a collection of packet collectors for this connection. - */ - protected Collection getPacketCollectors() { - return collectors; - } - @Override public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) { if (packetListener == null) { @@ -804,6 +802,19 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { packetReplyTimeout = timeout; } + /** + * Invoke {@link PacketCollector#processPacket(Packet)} for every + * PacketCollector with the given packet. + * + * @param packet the packet to notify the PacketCollectors about. + */ + protected void invokePacketCollectors(Packet packet) { + // Loop through all collectors and notify the appropriate ones. + for (PacketCollector collector: collectors) { + collector.processPacket(packet); + } + } + /** * Processes a packet after it's been fully parsed by looping through the installed * packet collectors and listeners and letting them examine the packet to see if @@ -816,10 +827,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { return; } - // Loop through all collectors and notify the appropriate ones. - for (PacketCollector collector: getPacketCollectors()) { - collector.processPacket(packet); - } + invokePacketCollectors(packet); // Deliver the incoming packet to listeners. executorService.submit(new ListenerNotification(packet)); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java b/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java index deb02e445..5689ead96 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java @@ -240,10 +240,7 @@ public class DummyConnection extends AbstractXMPPConnection { return; } - // Loop through all collectors and notify the appropriate ones. - for (PacketCollector collector: getPacketCollectors()) { - collector.processPacket(packet); - } + invokePacketCollectors(packet); if (SmackConfiguration.DEBUG_ENABLED) { System.out.println("[RECV]: " + packet.toXML());