mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-24 19:46:33 +01:00
Use an atomic reference array instead of ConcurrentHashMap for listeners
This commit is contained in:
parent
e3cfa45607
commit
ed9b61fd11
@ -23,6 +23,7 @@ import java.util.PriorityQueue;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.Packets;
|
||||||
import com.comphenix.protocol.concurrency.AbstractConcurrentListenerMultimap;
|
import com.comphenix.protocol.concurrency.AbstractConcurrentListenerMultimap;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.injector.PrioritizedListener;
|
import com.comphenix.protocol.injector.PrioritizedListener;
|
||||||
@ -66,7 +67,7 @@ class PacketProcessingQueue extends AbstractConcurrentListenerMultimap<AsyncList
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PacketProcessingQueue(PlayerSendingHandler sendingHandler, int initialSize, int maximumSize, int maximumConcurrency) {
|
public PacketProcessingQueue(PlayerSendingHandler sendingHandler, int initialSize, int maximumSize, int maximumConcurrency) {
|
||||||
super();
|
super(Packets.MAXIMUM_PACKET_ID);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.processingQueue = Synchronization.queue(MinMaxPriorityQueue.
|
this.processingQueue = Synchronization.queue(MinMaxPriorityQueue.
|
||||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
|
||||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||||
import com.comphenix.protocol.injector.PrioritizedListener;
|
import com.comphenix.protocol.injector.PrioritizedListener;
|
||||||
@ -35,8 +36,13 @@ import com.google.common.collect.Iterables;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
||||||
// The core of our map
|
// The core of our map
|
||||||
private ConcurrentMap<Integer, SortedCopyOnWriteArray<PrioritizedListener<TListener>>> listeners =
|
private AtomicReferenceArray<SortedCopyOnWriteArray<PrioritizedListener<TListener>>> arrayListeners;
|
||||||
new ConcurrentHashMap<Integer, SortedCopyOnWriteArray<PrioritizedListener<TListener>>>();
|
private ConcurrentMap<Integer, SortedCopyOnWriteArray<PrioritizedListener<TListener>>> mapListeners;
|
||||||
|
|
||||||
|
public AbstractConcurrentListenerMultimap(int maximumPacketID) {
|
||||||
|
arrayListeners = new AtomicReferenceArray<SortedCopyOnWriteArray<PrioritizedListener<TListener>>>(maximumPacketID + 1);
|
||||||
|
mapListeners = new ConcurrentHashMap<Integer, SortedCopyOnWriteArray<PrioritizedListener<TListener>>>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener to its requested list of packet recievers.
|
* Adds a listener to its requested list of packet recievers.
|
||||||
@ -53,20 +59,20 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
|
|
||||||
// Add the listener to a specific packet notifcation list
|
// Add the listener to a specific packet notifcation list
|
||||||
private void addListener(Integer packetID, PrioritizedListener<TListener> listener) {
|
private void addListener(Integer packetID, PrioritizedListener<TListener> listener) {
|
||||||
SortedCopyOnWriteArray<PrioritizedListener<TListener>> list = listeners.get(packetID);
|
SortedCopyOnWriteArray<PrioritizedListener<TListener>> list = arrayListeners.get(packetID);
|
||||||
|
|
||||||
// We don't want to create this for every lookup
|
// We don't want to create this for every lookup
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
// It would be nice if we could use a PriorityBlockingQueue, but it doesn't preseve iterator order,
|
// It would be nice if we could use a PriorityBlockingQueue, but it doesn't preseve iterator order,
|
||||||
// which is a essential feature for our purposes.
|
// which is a essential feature for our purposes.
|
||||||
final SortedCopyOnWriteArray<PrioritizedListener<TListener>> value = new SortedCopyOnWriteArray<PrioritizedListener<TListener>>();
|
final SortedCopyOnWriteArray<PrioritizedListener<TListener>> value = new SortedCopyOnWriteArray<PrioritizedListener<TListener>>();
|
||||||
|
|
||||||
list = listeners.putIfAbsent(packetID, value);
|
// We may end up creating multiple multisets, but we'll agree on which to use
|
||||||
|
if (arrayListeners.compareAndSet(packetID, null, value)) {
|
||||||
// We may end up creating multiple multisets, but we'll agree
|
mapListeners.put(packetID, value);
|
||||||
// on the one to use.
|
|
||||||
if (list == null) {
|
|
||||||
list = value;
|
list = value;
|
||||||
|
} else {
|
||||||
|
list = arrayListeners.get(packetID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +91,7 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
|
|
||||||
// Again, not terribly efficient. But adding or removing listeners should be a rare event.
|
// Again, not terribly efficient. But adding or removing listeners should be a rare event.
|
||||||
for (Integer packetID : whitelist.getWhitelist()) {
|
for (Integer packetID : whitelist.getWhitelist()) {
|
||||||
|
SortedCopyOnWriteArray<PrioritizedListener<TListener>> list = arrayListeners.get(packetID);
|
||||||
SortedCopyOnWriteArray<PrioritizedListener<TListener>> list = listeners.get(packetID);
|
|
||||||
|
|
||||||
// Remove any listeners
|
// Remove any listeners
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
@ -96,7 +101,8 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
list.remove(new PrioritizedListener<TListener>(listener, whitelist.getPriority()));
|
list.remove(new PrioritizedListener<TListener>(listener, whitelist.getPriority()));
|
||||||
|
|
||||||
if (list.size() == 0) {
|
if (list.size() == 0) {
|
||||||
listeners.remove(packetID);
|
arrayListeners.set(packetID, null);
|
||||||
|
mapListeners.remove(packetID);
|
||||||
removedPackets.add(packetID);
|
removedPackets.add(packetID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +122,7 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
* @return Registered listeners.
|
* @return Registered listeners.
|
||||||
*/
|
*/
|
||||||
public Collection<PrioritizedListener<TListener>> getListener(int packetID) {
|
public Collection<PrioritizedListener<TListener>> getListener(int packetID) {
|
||||||
return listeners.get(packetID);
|
return arrayListeners.get(packetID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +130,7 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
* @return Every listener.
|
* @return Every listener.
|
||||||
*/
|
*/
|
||||||
public Iterable<PrioritizedListener<TListener>> values() {
|
public Iterable<PrioritizedListener<TListener>> values() {
|
||||||
return Iterables.concat(listeners.values());
|
return Iterables.concat(mapListeners.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,13 +138,15 @@ public abstract class AbstractConcurrentListenerMultimap<TListener> {
|
|||||||
* @return Registered packet ID.
|
* @return Registered packet ID.
|
||||||
*/
|
*/
|
||||||
public Set<Integer> keySet() {
|
public Set<Integer> keySet() {
|
||||||
return listeners.keySet();
|
return mapListeners.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all packet listeners.
|
* Remove all packet listeners.
|
||||||
*/
|
*/
|
||||||
protected void clearListeners() {
|
protected void clearListeners() {
|
||||||
listeners.clear();
|
arrayListeners = new AtomicReferenceArray<
|
||||||
|
SortedCopyOnWriteArray<PrioritizedListener<TListener>>>(arrayListeners.length());
|
||||||
|
mapListeners.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package com.comphenix.protocol.injector;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.Packets;
|
||||||
import com.comphenix.protocol.concurrency.AbstractConcurrentListenerMultimap;
|
import com.comphenix.protocol.concurrency.AbstractConcurrentListenerMultimap;
|
||||||
import com.comphenix.protocol.error.ErrorReporter;
|
import com.comphenix.protocol.error.ErrorReporter;
|
||||||
import com.comphenix.protocol.events.ListenerPriority;
|
import com.comphenix.protocol.events.ListenerPriority;
|
||||||
@ -31,6 +32,10 @@ import com.comphenix.protocol.events.PacketListener;
|
|||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
public final class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<PacketListener> {
|
public final class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<PacketListener> {
|
||||||
|
public SortedPacketListenerList() {
|
||||||
|
super(Packets.MAXIMUM_PACKET_ID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the given packet event for every registered listener.
|
* Invokes the given packet event for every registered listener.
|
||||||
* @param reporter - the error reporter that will be used to inform about listener exceptions.
|
* @param reporter - the error reporter that will be used to inform about listener exceptions.
|
||||||
|
Loading…
Reference in New Issue
Block a user