Simplify CachedPacket

This commit is contained in:
themode 2021-12-22 07:53:54 +01:00 committed by TheMode
parent bb1b1e53d7
commit 7df51ef606
2 changed files with 8 additions and 31 deletions

View File

@ -11,36 +11,26 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* Represents a packet that is compute only when required (either due to memory demand or invalidated data) * Represents a packet that is only computed when required (either due to memory demand or invalidated data)
* <p> * <p>
* The {@link FramedPacket} is stored in a {@link SoftReference} and is invalidated when the {@link #invalidate()} method is called. * The cache is stored in a {@link SoftReference} and is invalidated when {@link #invalidate()} is called.
* <p> * <p>
* The {@link ServerPacket} may be computed dynamically in another thread, or be a constant to potentially * Packet supplier must be thread-safe.
* improve retrieval performance at the cost of the object staying in the heap.
*/ */
@ApiStatus.Internal @ApiStatus.Internal
public final class CachedPacket implements SendablePacket { public final class CachedPacket implements SendablePacket {
private static final AtomicIntegerFieldUpdater<CachedPacket> UPDATER = AtomicIntegerFieldUpdater.newUpdater(CachedPacket.class, "updated"); private static final AtomicIntegerFieldUpdater<CachedPacket> UPDATER =
AtomicIntegerFieldUpdater.newUpdater(CachedPacket.class, "updated");
private final Supplier<ServerPacket> packetSupplier; private final Supplier<ServerPacket> packetSupplier;
// 0 means that the reference needs to be updated // 0 means that the reference needs to be updated
// Anything else (currently 1) means that the packet is up-to-date // Anything else (currently 1) means that the packet is up-to-date
private volatile int updated = 0; private volatile int updated = 0;
private SoftReference<FramedPacket> packet; private SoftReference<FramedPacket> packet;
/**
* Creates a new cached packet that will force the allocation of a new {@link ServerPacket}
* during invalidation due to memory constraint or invalidation.
* <p>
* {@code packetSupplier} must be thread-safe.
*/
public CachedPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) { public CachedPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) {
this.packetSupplier = packetSupplier; this.packetSupplier = packetSupplier;
} }
/**
* Creates a new cached packet from a constant {@link ServerPacket}
* which will be the return value of {@link #packet()}.
*/
public CachedPacket(@NotNull ServerPacket packet) { public CachedPacket(@NotNull ServerPacket packet) {
this(() -> packet); this(() -> packet);
} }
@ -49,12 +39,6 @@ public final class CachedPacket implements SendablePacket {
this.updated = 0; this.updated = 0;
} }
/**
* Retrieves the packet object without allocating a buffer.
* <p>
* This method can be useful in case the payload is not important (e.g. for packet listening),
* but {@link #toBuffer()} and {@link #toFramedPacket()} should be privileged otherwise.
*/
public @NotNull ServerPacket packet() { public @NotNull ServerPacket packet() {
FramedPacket cache; FramedPacket cache;
if (updated == 1 && (cache = packet.get()) != null) if (updated == 1 && (cache = packet.get()) != null)
@ -62,24 +46,17 @@ public final class CachedPacket implements SendablePacket {
return packetSupplier.get(); return packetSupplier.get();
} }
public @NotNull ByteBuffer toBuffer() { public @NotNull ByteBuffer body() {
FramedPacket cache = updatedCache(); FramedPacket cache = updatedCache();
return cache != null ? cache.body() : PacketUtils.createFramedPacket(packet()); return cache != null ? cache.body() : PacketUtils.createFramedPacket(packet());
} }
public @NotNull FramedPacket toFramedPacket() {
FramedPacket cache = updatedCache();
return cache != null ? cache : PacketUtils.allocateTrimmedPacket(packet());
}
private @Nullable FramedPacket updatedCache() { private @Nullable FramedPacket updatedCache() {
if (!PacketUtils.CACHED_PACKET) if (!PacketUtils.CACHED_PACKET)
return null; return null;
SoftReference<FramedPacket> ref; SoftReference<FramedPacket> ref;
FramedPacket cache; FramedPacket cache;
if (updated == 0 || if (updated == 0 || ((ref = packet) == null || (cache = ref.get()) == null)) {
((ref = packet) == null ||
(cache = ref.get()) == null)) {
cache = PacketUtils.allocateTrimmedPacket(packet()); cache = PacketUtils.allocateTrimmedPacket(packet());
this.packet = new SoftReference<>(cache); this.packet = new SoftReference<>(cache);
UPDATER.compareAndSet(this, 0, 1); UPDATER.compareAndSet(this, 0, 1);

View File

@ -356,7 +356,7 @@ public class PlayerSocketConnection extends PlayerConnection {
} else if (packet instanceof FramedPacket framedPacket) { } else if (packet instanceof FramedPacket framedPacket) {
writeFramedPacketSync(framedPacket); writeFramedPacketSync(framedPacket);
} else if (packet instanceof CachedPacket cachedPacket) { } else if (packet instanceof CachedPacket cachedPacket) {
writeBufferSync(cachedPacket.toBuffer()); writeBufferSync(cachedPacket.body());
} else { } else {
throw new RuntimeException("Unknown packet type: " + packet.getClass().getName()); throw new RuntimeException("Unknown packet type: " + packet.getClass().getName());
} }