mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-05 11:39:57 -04:00
Make event registration thread safe (#1305)
(cherry picked from commit be996d2566
)
This commit is contained in:
parent
6692ae6057
commit
6d07a7c2fa
2 changed files with 20 additions and 11 deletions
fabric-api-base/src/main/java/net/fabricmc/fabric
|
@ -28,7 +28,7 @@ public abstract class Event<T> {
|
|||
* always refer to an instance containing all code that should be
|
||||
* executed upon event emission.
|
||||
*/
|
||||
protected T invoker;
|
||||
protected volatile T invoker;
|
||||
|
||||
/**
|
||||
* Returns the invoker instance.
|
||||
|
|
|
@ -18,6 +18,8 @@ package net.fabricmc.fabric.impl.base.event;
|
|||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
|
@ -26,6 +28,7 @@ class ArrayBackedEvent<T> extends Event<T> {
|
|||
private final Class<? super T> type;
|
||||
private final Function<T[], T> invokerFactory;
|
||||
private final T dummyInvoker;
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private T[] handlers;
|
||||
|
||||
ArrayBackedEvent(Class<? super T> type, T dummyInvoker, Function<T[], T> invokerFactory) {
|
||||
|
@ -35,12 +38,12 @@ class ArrayBackedEvent<T> extends Event<T> {
|
|||
update();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void update() {
|
||||
if (handlers == null) {
|
||||
if (dummyInvoker != null) {
|
||||
invoker = dummyInvoker;
|
||||
} else {
|
||||
//noinspection unchecked
|
||||
invoker = invokerFactory.apply((T[]) Array.newInstance(type, 0));
|
||||
}
|
||||
} else if (handlers.length == 1) {
|
||||
|
@ -50,21 +53,27 @@ class ArrayBackedEvent<T> extends Event<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void register(T listener) {
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("Tried to register a null listener!");
|
||||
}
|
||||
|
||||
if (handlers == null) {
|
||||
//noinspection unchecked
|
||||
handlers = (T[]) Array.newInstance(type, 1);
|
||||
handlers[0] = listener;
|
||||
} else {
|
||||
handlers = Arrays.copyOf(handlers, handlers.length + 1);
|
||||
handlers[handlers.length - 1] = listener;
|
||||
}
|
||||
lock.lock();
|
||||
|
||||
update();
|
||||
try {
|
||||
if (handlers == null) {
|
||||
handlers = (T[]) Array.newInstance(type, 1);
|
||||
handlers[0] = listener;
|
||||
} else {
|
||||
handlers = Arrays.copyOf(handlers, handlers.length + 1);
|
||||
handlers[handlers.length - 1] = listener;
|
||||
}
|
||||
|
||||
update();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue