Make event registration thread safe ()

(cherry picked from commit be996d2566)
This commit is contained in:
Player 2021-02-14 17:41:08 +00:00 committed by modmuss50
parent 6692ae6057
commit 6d07a7c2fa
2 changed files with 20 additions and 11 deletions
fabric-api-base/src/main/java/net/fabricmc/fabric
api/event
impl/base/event

View file

@ -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.

View file

@ -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();
}
}
}