Event system optimizations. Addresses BUKKIT-813

- Made the handlers field a simple array instead of an array of arrays.
- Got rid of the "baked" field.
This commit is contained in:
TomyLobo 2012-02-28 19:37:27 -06:00 committed by EvilSeph
parent 07f964813c
commit 93521af608
3 changed files with 38 additions and 51 deletions

View File

@ -37,11 +37,9 @@ public class TimingsCommand extends Command {
boolean separate = "separate".equals(args[0]); boolean separate = "separate".equals(args[0]);
if ("reset".equals(args[0])) { if ("reset".equals(args[0])) {
for (HandlerList handlerList : HandlerList.getHandlerLists()) { for (HandlerList handlerList : HandlerList.getHandlerLists()) {
for (RegisteredListener[] listeners : handlerList.getRegisteredListeners()) { for (RegisteredListener listener : handlerList.getRegisteredListeners()) {
for (RegisteredListener listener : listeners) { if (listener instanceof TimedRegisteredListener) {
if (listener instanceof TimedRegisteredListener) { ((TimedRegisteredListener)listener).reset();
((TimedRegisteredListener)listener).reset();
}
} }
} }
} }

View File

@ -14,7 +14,7 @@ public class HandlerList {
/** /**
* Handler array. This field being an array is the key to this system's speed. * Handler array. This field being an array is the key to this system's speed.
*/ */
private RegisteredListener[][] handlers = new RegisteredListener[EventPriority.values().length][]; private RegisteredListener[] handlers = null;
/** /**
* Dynamic handler lists. These are changed using register() and * Dynamic handler lists. These are changed using register() and
@ -23,15 +23,6 @@ public class HandlerList {
*/ */
private final EnumMap<EventPriority, ArrayList<RegisteredListener>> handlerslots; private final EnumMap<EventPriority, ArrayList<RegisteredListener>> handlerslots;
/**
* Whether the current HandlerList has been fully baked. When this is set
* to false, the Map<EventPriority, List<RegisteredListener>> will be baked to RegisteredListener[][]
* next time the event is called.
*
* @see org.bukkit.plugin.SimplePluginManager#callEvent
*/
private boolean baked = false;
/** /**
* List of all HandlerLists which have been created, for use in bakeAll() * List of all HandlerLists which have been created, for use in bakeAll()
*/ */
@ -56,7 +47,7 @@ public class HandlerList {
for (List<RegisteredListener> list : h.handlerslots.values()) { for (List<RegisteredListener> list : h.handlerslots.values()) {
list.clear(); list.clear();
} }
h.baked = false; h.handlers = null;
} }
} }
@ -102,7 +93,7 @@ public class HandlerList {
public void register(RegisteredListener listener) { public void register(RegisteredListener listener) {
if (handlerslots.get(listener.getPriority()).contains(listener)) if (handlerslots.get(listener.getPriority()).contains(listener))
throw new IllegalStateException("This listener is already registered to priority " + listener.getPriority().toString()); throw new IllegalStateException("This listener is already registered to priority " + listener.getPriority().toString());
baked = false; handlers = null;
handlerslots.get(listener.getPriority()).add(listener); handlerslots.get(listener.getPriority()).add(listener);
} }
@ -123,9 +114,8 @@ public class HandlerList {
* @param listener listener to remove * @param listener listener to remove
*/ */
public void unregister(RegisteredListener listener) { public void unregister(RegisteredListener listener) {
if (handlerslots.get(listener.getPriority()).contains(listener)) { if (handlerslots.get(listener.getPriority()).remove(listener)) {
baked = false; handlers = null;
handlerslots.get(listener.getPriority()).remove(listener);
} }
} }
@ -144,7 +134,7 @@ public class HandlerList {
} }
} }
} }
if (changed) baked = false; if (changed) handlers = null;
} }
/** /**
@ -162,18 +152,19 @@ public class HandlerList {
} }
} }
} }
if (changed) baked = false; if (changed) handlers = null;
} }
/** /**
* Bake HashMap and ArrayLists to 2d array - does nothing if not necessary * Bake HashMap and ArrayLists to 2d array - does nothing if not necessary
*/ */
public void bake() { public void bake() {
if (baked) return; // don't re-bake when still valid if (handlers != null) return; // don't re-bake when still valid
List<RegisteredListener> entries = new ArrayList<RegisteredListener>();
for (Entry<EventPriority, ArrayList<RegisteredListener>> entry : handlerslots.entrySet()) { for (Entry<EventPriority, ArrayList<RegisteredListener>> entry : handlerslots.entrySet()) {
handlers[entry.getKey().getSlot()] = (entry.getValue().toArray(new RegisteredListener[entry.getValue().size()])); entries.addAll(entry.getValue());
} }
baked = true; handlers = entries.toArray(new RegisteredListener[entries.size()]);
} }
/** /**
@ -181,7 +172,8 @@ public class HandlerList {
* *
* @return the array of registered listeners * @return the array of registered listeners
*/ */
public RegisteredListener[][] getRegisteredListeners() { public RegisteredListener[] getRegisteredListeners() {
bake();
return handlers; return handlers;
} }

View File

@ -431,38 +431,35 @@ public final class SimplePluginManager implements PluginManager {
*/ */
public synchronized void callEvent(Event event) { public synchronized void callEvent(Event event) {
HandlerList handlers = event.getHandlers(); HandlerList handlers = event.getHandlers();
handlers.bake(); RegisteredListener[] listeners = handlers.getRegisteredListeners();
RegisteredListener[][] listeners = handlers.getRegisteredListeners();
for (int i = 0; i < listeners.length; i++) { for (RegisteredListener registration : listeners) {
for (RegisteredListener registration : listeners[i]) { if (!registration.getPlugin().isEnabled()) {
if (!registration.getPlugin().isEnabled()) { continue;
continue; }
}
try { try {
registration.callEvent(event); registration.callEvent(event);
} catch (AuthorNagException ex) { } catch (AuthorNagException ex) {
Plugin plugin = registration.getPlugin(); Plugin plugin = registration.getPlugin();
if (plugin.isNaggable()) { if (plugin.isNaggable()) {
plugin.setNaggable(false); plugin.setNaggable(false);
String author = "<NoAuthorGiven>"; String author = "<NoAuthorGiven>";
if (plugin.getDescription().getAuthors().size() > 0) { if (plugin.getDescription().getAuthors().size() > 0) {
author = plugin.getDescription().getAuthors().get(0); author = plugin.getDescription().getAuthors().get(0);
}
server.getLogger().log(Level.SEVERE, String.format(
"Nag author: '%s' of '%s' about the following: %s",
author,
plugin.getDescription().getName(),
ex.getMessage()
));
} }
} catch (Throwable ex) { server.getLogger().log(Level.SEVERE, String.format(
server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getName(), ex); "Nag author: '%s' of '%s' about the following: %s",
author,
plugin.getDescription().getName(),
ex.getMessage()
));
} }
} catch (Throwable ex) {
server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getName(), ex);
} }
} }
} }