From edabb19891233163288bea0e123b95ef86bb5e70 Mon Sep 17 00:00:00 2001 From: themode Date: Fri, 25 Mar 2022 10:12:04 +0100 Subject: [PATCH] Explicit fences --- .../minestom/server/event/EventNodeImpl.java | 37 ++++++++----------- .../network/packet/server/CachedPacket.java | 22 +++-------- .../network/packet/server/LazyPacket.java | 21 +++-------- .../minestom/server/tag/TagHandlerImpl.java | 8 +++- .../server/thread/AcquirableImpl.java | 17 ++------- 5 files changed, 37 insertions(+), 68 deletions(-) diff --git a/src/main/java/net/minestom/server/event/EventNodeImpl.java b/src/main/java/net/minestom/server/event/EventNodeImpl.java index d24ed22f8..42a98802d 100644 --- a/src/main/java/net/minestom/server/event/EventNodeImpl.java +++ b/src/main/java/net/minestom/server/event/EventNodeImpl.java @@ -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 implements EventNode { static final Object GLOBAL_CHILD_LOCK = new Object(); - private final ClassValue> handleMap = new ClassValue<>() { + private final ClassValue> handleMap = new ClassValue<>() { @Override - protected ListenerHandle computeValue(Class type) { + protected Handle computeValue(Class type) { //noinspection unchecked return new Handle<>((Class) type); } @@ -274,8 +273,8 @@ non-sealed class EventNodeImpl implements EventNode { private void invalidateEvent(Class eventClass) { forTargetEvents(eventClass, type -> { - ListenerHandle handle = getHandle((Class) type); - Handle.UPDATED.setRelease(handle, false); + Handle handle = handleMap.get(type); + handle.invalidate(); }); final EventNodeImpl parent = this.parent; if (parent != null) parent.invalidateEvent(eventClass); @@ -307,20 +306,9 @@ non-sealed class EventNodeImpl implements EventNode { @SuppressWarnings("unchecked") final class Handle implements ListenerHandle { - 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 eventType; private Consumer listener = null; - @SuppressWarnings("unused") - private boolean updated; // Use the UPDATED var handle + private boolean updated; Handle(Class eventType) { this.eventType = eventType; @@ -342,13 +330,20 @@ non-sealed class EventNodeImpl implements EventNode { return updatedListener() != null; } + void invalidate() { + this.updated = false; + VarHandle.releaseFence(); + } + @Nullable Consumer 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 listener = createConsumer(); this.listener = listener; - UPDATED.setRelease(this, true); + this.updated = true; + VarHandle.releaseFence(); return listener; } } @@ -492,7 +487,7 @@ non-sealed class EventNodeImpl implements EventNode { EventListener.Result result = listener.run(event); if (result == EventListener.Result.EXPIRED) { node.removeListener(listener); - UPDATED.setRelease(this, false); + invalidate(); } } } diff --git a/src/main/java/net/minestom/server/network/packet/server/CachedPacket.java b/src/main/java/net/minestom/server/network/packet/server/CachedPacket.java index e9d49279f..4571d5c58 100644 --- a/src/main/java/net/minestom/server/network/packet/server/CachedPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/CachedPacket.java @@ -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 packetSupplier; - @SuppressWarnings("unused") private SoftReference 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 ref = (SoftReference) PACKET.getAcquire(this); + VarHandle.acquireFence(); + SoftReference 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; } diff --git a/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java b/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java index 6a5672944..5a9ef1a65 100644 --- a/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java @@ -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 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(); } } } diff --git a/src/main/java/net/minestom/server/tag/TagHandlerImpl.java b/src/main/java/net/minestom/server/tag/TagHandlerImpl.java index 8b5ae0fd5..b0c626a40 100644 --- a/src/main/java/net/minestom/server/tag/TagHandlerImpl.java +++ b/src/main/java/net/minestom/server/tag/TagHandlerImpl.java @@ -166,7 +166,7 @@ final class TagHandlerImpl implements TagHandler { private static final class Entry { final Tag tag; final T value; // TagHandler type for path-able tags - volatile NBT nbt; + private NBT nbt; Entry(Tag 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; } } diff --git a/src/main/java/net/minestom/server/thread/AcquirableImpl.java b/src/main/java/net/minestom/server/thread/AcquirableImpl.java index f506f2cd7..f6c0f90c5 100644 --- a/src/main/java/net/minestom/server/thread/AcquirableImpl.java +++ b/src/main/java/net/minestom/server/thread/AcquirableImpl.java @@ -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 implements Acquirable { 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 implements Acquirable { 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 implements Acquirable { @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) {