mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 14:07:43 +01:00
Explicit fences
This commit is contained in:
parent
0fc9cab6ab
commit
edabb19891
@ -7,7 +7,6 @@ import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -20,9 +19,9 @@ import java.util.function.Consumer;
|
||||
non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
static final Object GLOBAL_CHILD_LOCK = new Object();
|
||||
|
||||
private final ClassValue<ListenerHandle<T>> handleMap = new ClassValue<>() {
|
||||
private final ClassValue<Handle<T>> handleMap = new ClassValue<>() {
|
||||
@Override
|
||||
protected ListenerHandle<T> computeValue(Class<?> type) {
|
||||
protected Handle<T> computeValue(Class<?> type) {
|
||||
//noinspection unchecked
|
||||
return new Handle<>((Class<T>) type);
|
||||
}
|
||||
@ -274,8 +273,8 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
|
||||
private void invalidateEvent(Class<? extends T> eventClass) {
|
||||
forTargetEvents(eventClass, type -> {
|
||||
ListenerHandle<T> handle = getHandle((Class<T>) type);
|
||||
Handle.UPDATED.setRelease(handle, false);
|
||||
Handle<T> handle = handleMap.get(type);
|
||||
handle.invalidate();
|
||||
});
|
||||
final EventNodeImpl<? super T> parent = this.parent;
|
||||
if (parent != null) parent.invalidateEvent(eventClass);
|
||||
@ -307,20 +306,9 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final class Handle<E extends Event> implements ListenerHandle<E> {
|
||||
private static final VarHandle UPDATED;
|
||||
|
||||
static {
|
||||
try {
|
||||
UPDATED = MethodHandles.lookup().findVarHandle(EventNodeImpl.Handle.class, "updated", boolean.class);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Class<E> eventType;
|
||||
private Consumer<E> listener = null;
|
||||
@SuppressWarnings("unused")
|
||||
private boolean updated; // Use the UPDATED var handle
|
||||
private boolean updated;
|
||||
|
||||
Handle(Class<E> eventType) {
|
||||
this.eventType = eventType;
|
||||
@ -342,13 +330,20 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
return updatedListener() != null;
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
this.updated = false;
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
|
||||
@Nullable Consumer<E> updatedListener() {
|
||||
if ((boolean) UPDATED.getAcquire(this)) return listener;
|
||||
VarHandle.acquireFence();
|
||||
if (updated) return listener;
|
||||
synchronized (GLOBAL_CHILD_LOCK) {
|
||||
if ((boolean) UPDATED.getAcquire(this)) return listener;
|
||||
if (updated) return listener;
|
||||
final Consumer<E> listener = createConsumer();
|
||||
this.listener = listener;
|
||||
UPDATED.setRelease(this, true);
|
||||
this.updated = true;
|
||||
VarHandle.releaseFence();
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
@ -492,7 +487,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||
EventListener.Result result = listener.run(event);
|
||||
if (result == EventListener.Result.EXPIRED) {
|
||||
node.removeListener(listener);
|
||||
UPDATED.setRelease(this, false);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -20,18 +19,7 @@ import java.util.function.Supplier;
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public final class CachedPacket implements SendablePacket {
|
||||
private static final VarHandle PACKET;
|
||||
|
||||
static {
|
||||
try {
|
||||
PACKET = MethodHandles.lookup().findVarHandle(CachedPacket.class, "packet", SoftReference.class);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Supplier<ServerPacket> packetSupplier;
|
||||
@SuppressWarnings("unused")
|
||||
private SoftReference<FramedPacket> packet;
|
||||
|
||||
public CachedPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) {
|
||||
@ -43,7 +31,8 @@ public final class CachedPacket implements SendablePacket {
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
PACKET.setRelease(this, null);
|
||||
this.packet = null;
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
|
||||
public @NotNull ServerPacket packet() {
|
||||
@ -59,12 +48,13 @@ public final class CachedPacket implements SendablePacket {
|
||||
private @Nullable FramedPacket updatedCache() {
|
||||
if (!PacketUtils.CACHED_PACKET)
|
||||
return null;
|
||||
@SuppressWarnings("unchecked")
|
||||
SoftReference<FramedPacket> ref = (SoftReference<FramedPacket>) PACKET.getAcquire(this);
|
||||
VarHandle.acquireFence();
|
||||
SoftReference<FramedPacket> ref = packet;
|
||||
FramedPacket cache;
|
||||
if (ref == null || (cache = ref.get()) == null) {
|
||||
cache = PacketUtils.allocateTrimmedPacket(packetSupplier.get());
|
||||
PACKET.setRelease(this, new SoftReference<>(cache));
|
||||
this.packet = new SoftReference<>(cache);
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package net.minestom.server.network.packet.server;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -14,18 +13,7 @@ import java.util.function.Supplier;
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public final class LazyPacket implements SendablePacket {
|
||||
private static final VarHandle PACKET;
|
||||
|
||||
static {
|
||||
try {
|
||||
PACKET = MethodHandles.lookup().findVarHandle(LazyPacket.class, "packet", ServerPacket.class);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Supplier<ServerPacket> packetSupplier;
|
||||
@SuppressWarnings("unused")
|
||||
private ServerPacket packet;
|
||||
|
||||
public LazyPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) {
|
||||
@ -33,13 +21,14 @@ public final class LazyPacket implements SendablePacket {
|
||||
}
|
||||
|
||||
public @NotNull ServerPacket packet() {
|
||||
ServerPacket packet = (ServerPacket) PACKET.getAcquire(this);
|
||||
VarHandle.acquireFence();
|
||||
ServerPacket packet = this.packet;
|
||||
if (packet == null) {
|
||||
synchronized (this) {
|
||||
packet = (ServerPacket) PACKET.getAcquire(this);
|
||||
packet = this.packet;
|
||||
if (packet == null) {
|
||||
packet = packetSupplier.get();
|
||||
PACKET.setRelease(this, packet);
|
||||
this.packet = packet = packetSupplier.get();
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||
private static final class Entry<T> {
|
||||
final Tag<T> tag;
|
||||
final T value; // TagHandler type for path-able tags
|
||||
volatile NBT nbt;
|
||||
private NBT nbt;
|
||||
|
||||
Entry(Tag<T> tag, T value) {
|
||||
this.tag = tag;
|
||||
@ -174,8 +174,12 @@ final class TagHandlerImpl implements TagHandler {
|
||||
}
|
||||
|
||||
NBT updatedNbt() {
|
||||
VarHandle.acquireFence();
|
||||
NBT nbt = this.nbt;
|
||||
if (nbt == null) this.nbt = nbt = tag.writeFunction.apply(value);
|
||||
if (nbt == null) {
|
||||
this.nbt = nbt = tag.writeFunction.apply(value);
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
return nbt;
|
||||
}
|
||||
}
|
||||
|
@ -3,22 +3,12 @@ package net.minestom.server.thread;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
final class AcquirableImpl<T> implements Acquirable<T> {
|
||||
static final AtomicLong WAIT_COUNTER_NANO = new AtomicLong();
|
||||
private static final VarHandle ASSIGNED_THREAD;
|
||||
|
||||
static {
|
||||
try {
|
||||
ASSIGNED_THREAD = MethodHandles.lookup().findVarHandle(AcquirableImpl.class, "assignedThread", TickThread.class);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global lock used for synchronization.
|
||||
@ -26,7 +16,6 @@ final class AcquirableImpl<T> implements Acquirable<T> {
|
||||
private static final ReentrantLock GLOBAL_LOCK = new ReentrantLock();
|
||||
|
||||
private final T value;
|
||||
@SuppressWarnings("unused")
|
||||
private TickThread assignedThread;
|
||||
|
||||
public AcquirableImpl(@NotNull T value) {
|
||||
@ -40,11 +29,13 @@ final class AcquirableImpl<T> implements Acquirable<T> {
|
||||
|
||||
@Override
|
||||
public @NotNull TickThread assignedThread() {
|
||||
return (TickThread) ASSIGNED_THREAD.getAcquire(this);
|
||||
VarHandle.acquireFence();
|
||||
return assignedThread;
|
||||
}
|
||||
|
||||
void updateThread(@NotNull TickThread thread) {
|
||||
ASSIGNED_THREAD.setRelease(this, thread);
|
||||
this.assignedThread = thread;
|
||||
VarHandle.releaseFence();
|
||||
}
|
||||
|
||||
static @Nullable ReentrantLock enter(@NotNull Thread currentThread, @Nullable TickThread elementThread) {
|
||||
|
Loading…
Reference in New Issue
Block a user