Skip to content
This repository was archived by the owner on May 26, 2018. It is now read-only.

Commit 5365f5e

Browse files
committed
Add IEventExceptionHandler for EventBus to allow special handeling exceptions that are fired while running an event.
Events now track what 'phase' they are in during the execution process. Each EventPriority is a 'phase'. An exception is thrown if the event attempts to set its phase to a previous one.
1 parent 63b6448 commit 5365f5e

File tree

6 files changed

+97
-9
lines changed

6 files changed

+97
-9
lines changed

src/main/java/cpw/mods/fml/common/eventhandler/ASMEventHandler.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.lang.reflect.Method;
66
import java.util.HashMap;
77

8-
98
import org.apache.logging.log4j.ThreadContext;
109
import org.objectweb.asm.ClassWriter;
1110
import org.objectweb.asm.MethodVisitor;
@@ -27,11 +26,14 @@ public class ASMEventHandler implements IEventListener
2726
private final IEventListener handler;
2827
private final SubscribeEvent subInfo;
2928
private ModContainer owner;
29+
private String readable;
30+
3031
public ASMEventHandler(Object target, Method method, ModContainer owner) throws Exception
3132
{
3233
this.owner = owner;
3334
handler = (IEventListener)createWrapper(method).getConstructor(Object.class).newInstance(target);
3435
subInfo = method.getAnnotation(SubscribeEvent.class);
36+
readable = "ASM: " + target + " " + method.getName() + Type.getMethodDescriptor(method);
3537
}
3638

3739
@Override
@@ -142,4 +144,8 @@ public Class<?> define(String name, byte[] data)
142144
}
143145
}
144146

147+
public String toString()
148+
{
149+
return readable;
150+
}
145151
}

src/main/java/cpw/mods/fml/common/eventhandler/Event.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
import java.util.Map;
1010
import java.util.concurrent.ConcurrentHashMap;
1111

12+
import javax.annotation.Nonnull;
13+
import javax.annotation.Nullable;
14+
15+
import com.google.common.base.Preconditions;
16+
1217

1318
/**
1419
* Base Event class that all other events are derived from
@@ -31,6 +36,7 @@ public enum Result
3136
private Result result = Result.DEFAULT;
3237
private final boolean hasResult;
3338
private static ListenerList listeners = new ListenerList();
39+
private EventPriority phase = null;
3440

3541
private static final Map<Class<?>, Map<Class<?>, Boolean>> annotationMap = new ConcurrentHashMap<Class<?>, Map<Class<?>, Boolean>>();
3642

@@ -153,4 +159,18 @@ public ListenerList getListenerList()
153159
{
154160
return listeners;
155161
}
162+
163+
@Nullable
164+
public EventPriority getPhase()
165+
{
166+
return this.phase;
167+
}
168+
169+
public void setPhase(@Nonnull EventPriority value)
170+
{
171+
Preconditions.checkArgument(value != null, "setPhase argument must not be null");
172+
int prev = phase == null ? -1 : phase.ordinal();
173+
Preconditions.checkArgument(prev < value.ordinal(), "Attempted to set event phase to %s when already %s", value, phase);
174+
phase = value;
175+
}
156176
}

src/main/java/cpw/mods/fml/common/eventhandler/EventBus.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,41 @@
66
import java.util.Map;
77
import java.util.Set;
88
import java.util.concurrent.ConcurrentHashMap;
9-
import org.apache.logging.log4j.Level;
109

10+
import javax.annotation.Nonnull;
1111

12+
import org.apache.logging.log4j.Level;
1213

14+
import com.google.common.base.Preconditions;
15+
import com.google.common.base.Throwables;
1316
import com.google.common.collect.MapMaker;
1417
import com.google.common.reflect.TypeToken;
18+
1519
import cpw.mods.fml.common.FMLLog;
1620
import cpw.mods.fml.common.Loader;
1721
import cpw.mods.fml.common.ModContainer;
1822

19-
public class EventBus
23+
public class EventBus implements IEventExceptionHandler
2024
{
2125
private static int maxID = 0;
2226

2327
private ConcurrentHashMap<Object, ArrayList<IEventListener>> listeners = new ConcurrentHashMap<Object, ArrayList<IEventListener>>();
2428
private Map<Object,ModContainer> listenerOwners = new MapMaker().weakKeys().weakValues().makeMap();
2529
private final int busID = maxID++;
30+
private IEventExceptionHandler exceptionHandler;
2631

2732
public EventBus()
2833
{
2934
ListenerList.resize(busID + 1);
35+
exceptionHandler = this;
36+
register(this);
37+
}
38+
39+
public EventBus(@Nonnull IEventExceptionHandler handler)
40+
{
41+
this();
42+
Preconditions.checkArgument(handler != null, "EventBus exception handler can not be null");
43+
exceptionHandler = handler;
3044
}
3145

3246
public void register(Object target)
@@ -117,10 +131,30 @@ public void unregister(Object object)
117131
public boolean post(Event event)
118132
{
119133
IEventListener[] listeners = event.getListenerList().getListeners(busID);
120-
for (IEventListener listener : listeners)
134+
int index = 0;
135+
try
136+
{
137+
for (; index < listeners.length; index++)
138+
{
139+
listeners[index].invoke(event);
140+
}
141+
}
142+
catch (Throwable throwable)
121143
{
122-
listener.invoke(event);
144+
exceptionHandler.handleException(this, event, listeners, index, throwable);
145+
Throwables.propagate(throwable);
123146
}
124147
return (event.isCancelable() ? event.isCanceled() : false);
125148
}
149+
150+
@Override
151+
public void handleException(EventBus bus, Event event, IEventListener[] listeners, int index, Throwable throwable)
152+
{
153+
FMLLog.log(Level.ERROR, throwable, "Exception caught during firing event %s:", event);
154+
FMLLog.log(Level.ERROR, "Index: %d Listeners:", index);
155+
for (int x = 0; x < listeners.length; x++)
156+
{
157+
FMLLog.log(Level.ERROR, "%d: %s", x, listeners[x]);
158+
}
159+
}
126160
}
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
package cpw.mods.fml.common.eventhandler;
22

3-
public enum EventPriority
3+
public enum EventPriority implements IEventListener
44
{
55
/*Priority of event listeners, listeners will be sorted with respect to this priority level.
6-
*
6+
*
77
* Note:
88
* Due to using a ArrayList in the ListenerList,
9-
* these need to stay in a contiguous index starting at 0. {Default ordinal}
9+
* these need to stay in a contiguous index starting at 0. {Default ordinal}
1010
*/
1111
HIGHEST, //First to execute
1212
HIGH,
1313
NORMAL,
1414
LOW,
1515
LOWEST //Last to execute
16+
;
17+
18+
@Override
19+
public void invoke(Event event)
20+
{
21+
event.setPhase(this);
22+
}
1623
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package cpw.mods.fml.common.eventhandler;
2+
3+
public interface IEventExceptionHandler
4+
{
5+
/**
6+
* Fired when a EventListener throws an exception for the specified event on the event bus.
7+
* After this function returns, the original Throwable will be propogated upwards.
8+
*
9+
* @param bus The bus the event is being fired on
10+
* @param event The event that is being fired
11+
* @param listeners All listeners that are listening for this event, in order
12+
* @param index Index for the current listener being fired.
13+
* @param throwable The throwable being thrown
14+
*/
15+
void handleException(EventBus bus, Event event, IEventListener[] listeners, int index, Throwable throwable);
16+
}

src/main/java/cpw/mods/fml/common/eventhandler/ListenerList.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,12 @@ private void buildCache()
202202
ArrayList<IEventListener> ret = new ArrayList<IEventListener>();
203203
for (EventPriority value : EventPriority.values())
204204
{
205-
ret.addAll(getListeners(value));
205+
List<IEventListener> listeners = getListeners(value);
206+
if (listeners.size() > 0)
207+
{
208+
ret.add(value); //Add the priority to notify the event of it's current phase.
209+
ret.addAll(listeners);
210+
}
206211
}
207212
listeners = ret.toArray(new IEventListener[ret.size()]);
208213
rebuild = false;

0 commit comments

Comments
 (0)