From 10d40dd19d74e6beba198fc0e6a85c6583f5a4fc Mon Sep 17 00:00:00 2001 From: themode Date: Sat, 1 Jan 2022 03:40:42 +0100 Subject: [PATCH] Use opaque memory ordering for cached packets --- .../network/packet/server/CachedPacket.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) 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 eefb6290f..acee31c79 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,9 +5,10 @@ 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; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.function.Supplier; /** @@ -19,12 +20,17 @@ import java.util.function.Supplier; */ @ApiStatus.Internal public final class CachedPacket implements SendablePacket { - private static final AtomicIntegerFieldUpdater UPDATER = - AtomicIntegerFieldUpdater.newUpdater(CachedPacket.class, "updated"); + 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; - // 0 means that the reference needs to be updated - // Anything else (currently 1) means that the packet is up-to-date - private volatile int updated = 0; private SoftReference packet; public CachedPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) { @@ -36,12 +42,14 @@ public final class CachedPacket implements SendablePacket { } public void invalidate() { - this.updated = 0; + PACKET.setOpaque(this, null); } public @NotNull ServerPacket packet() { + @SuppressWarnings("unchecked") + SoftReference ref = (SoftReference) PACKET.getOpaque(this); FramedPacket cache; - if (updated == 1 && (cache = packet.get()) != null) + if (ref != null && (cache = ref.get()) != null) return cache.packet(); // Avoid potential packet allocation return packetSupplier.get(); } @@ -54,12 +62,12 @@ public final class CachedPacket implements SendablePacket { private @Nullable FramedPacket updatedCache() { if (!PacketUtils.CACHED_PACKET) return null; - SoftReference ref; + @SuppressWarnings("unchecked") + SoftReference ref = (SoftReference) PACKET.getOpaque(this); FramedPacket cache; - if (updated == 0 || ((ref = packet) == null || (cache = ref.get()) == null)) { + if (ref == null || (cache = ref.get()) == null) { cache = PacketUtils.allocateTrimmedPacket(packetSupplier.get()); - this.packet = new SoftReference<>(cache); - UPDATER.compareAndSet(this, 0, 1); + PACKET.setOpaque(this, new SoftReference<>(cache)); } return cache; }