Experimental and potentially unstable: async packet sending

This commit is contained in:
filoghost 2024-02-19 23:11:34 +01:00
parent ed3bbad1fb
commit 0754e0ac33
26 changed files with 248 additions and 93 deletions

View File

@ -24,6 +24,7 @@ import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlacehol
import me.filoghost.holographicdisplays.core.tick.TickClock; import me.filoghost.holographicdisplays.core.tick.TickClock;
import me.filoghost.holographicdisplays.core.tick.TickingTask; import me.filoghost.holographicdisplays.core.tick.TickingTask;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager; import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import me.filoghost.holographicdisplays.core.tracking.PacketSenderExecutor;
import me.filoghost.holographicdisplays.nms.common.NMSManager; import me.filoghost.holographicdisplays.nms.common.NMSManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -47,6 +48,8 @@ public class HolographicDisplaysCore {
throw new PluginEnableException(t, "Couldn't initialize the NMS manager."); throw new PluginEnableException(t, "Couldn't initialize the NMS manager.");
} }
PacketSenderExecutor.start();
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry(); PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
TickClock tickClock = new TickClock(); TickClock tickClock = new TickClock();
ActivePlaceholderTracker placeholderTracker = new ActivePlaceholderTracker(placeholderRegistry, tickClock); ActivePlaceholderTracker placeholderTracker = new ActivePlaceholderTracker(placeholderRegistry, tickClock);
@ -103,6 +106,8 @@ public class HolographicDisplaysCore {
nmsManager.uninjectPacketListener(player); nmsManager.uninjectPacketListener(player);
} }
} }
PacketSenderExecutor.stopGracefully();
} }
} }

View File

@ -85,7 +85,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override @Override
protected void sendSpawnPackets(Viewers<T> viewers) { protected void sendSpawnPackets(Viewers<T> viewers) {
if (spawnClickableEntity) { if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition())); // Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
});
} }
} }
@ -93,7 +97,9 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override @Override
protected void sendDestroyPackets(Viewers<T> viewers) { protected void sendDestroyPackets(Viewers<T> viewers) {
if (spawnClickableEntity) { if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newDestroyPackets()); PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newDestroyPackets());
});
} }
} }
@ -104,9 +110,15 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
if (spawnClickableEntityChanged) { if (spawnClickableEntityChanged) {
if (spawnClickableEntity) { if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition())); // Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
});
} else { } else {
viewers.sendPackets(clickableEntity.newDestroyPackets()); PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newDestroyPackets());
});
} }
} }
} }
@ -115,7 +127,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override @Override
protected void sendPositionChangePackets(Viewers<T> viewers) { protected void sendPositionChangePackets(Viewers<T> viewers) {
if (spawnClickableEntity) { if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newTeleportPackets(getClickableEntityPosition())); // Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newTeleportPackets(clickableEntityPosition));
});
} }
} }

View File

@ -5,6 +5,7 @@
*/ */
package me.filoghost.holographicdisplays.core.tracking; package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine; import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener; import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer; import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
@ -106,7 +107,12 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendSpawnPackets(viewers); super.sendSpawnPackets(viewers);
if (spawnItemEntity) { if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack)); // Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
});
} }
} }
@ -116,7 +122,9 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendDestroyPackets(viewers); super.sendDestroyPackets(viewers);
if (spawnItemEntity) { if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newDestroyPackets()); PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newDestroyPackets());
});
} }
} }
@ -127,13 +135,24 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
if (spawnItemEntityChanged) { if (spawnItemEntityChanged) {
if (spawnItemEntity) { if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack)); // Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
});
} else { } else {
viewers.sendPackets(itemEntity.newDestroyPackets()); PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newDestroyPackets());
});
} }
} else if (itemStackChanged) { } else if (itemStackChanged) {
// Only send item changes if full spawn/destroy packets were not sent // Only send item changes if full spawn/destroy packets were not sent
viewers.sendPackets(itemEntity.newChangePackets(itemStack)); // Copy for async use
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newChangePackets(itemStack));
});
} }
} }
@ -143,7 +162,11 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendPositionChangePackets(viewers); super.sendPositionChangePackets(viewers);
if (spawnItemEntity) { if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates)); // Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates));
});
} }
} }

View File

@ -14,14 +14,14 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.MustBeInvokedByOverriders;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public abstract class LineTracker<T extends Viewer> { public abstract class LineTracker<T extends Viewer> {
private final Map<Player, T> viewers; private final ConcurrentMap<Player, T> viewers;
private final Viewers<T> iterableViewers; private final Viewers<T> iterableViewers;
private String positionWorldName; private String positionWorldName;
@ -32,7 +32,7 @@ public abstract class LineTracker<T extends Viewer> {
private int lastVisibilitySettingsVersion; private int lastVisibilitySettingsVersion;
protected LineTracker() { protected LineTracker() {
this.viewers = new HashMap<>(); this.viewers = new ConcurrentHashMap<>();
this.iterableViewers = new DelegateViewers<>(viewers.values()); this.iterableViewers = new DelegateViewers<>(viewers.values());
} }

View File

@ -15,7 +15,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
private T viewer; private T viewer;
private List<T> additionalViewers; private List<T> additionalViewers;
public void add(T viewer) { public synchronized void add(T viewer) {
if (this.viewer == null) { if (this.viewer == null) {
this.viewer = viewer; this.viewer = viewer;
} else { } else {
@ -27,7 +27,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
} }
@Override @Override
public void forEach(Consumer<? super T> action) { public synchronized void forEach(Consumer<? super T> action) {
if (viewer != null) { if (viewer != null) {
action.accept(viewer); action.accept(viewer);
if (additionalViewers != null) { if (additionalViewers != null) {

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.fcommons.logging.Log;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* This is a quick but ugly helper class for creating and sending packets async.
* Static classes like this should be avoided.
*/
public class PacketSenderExecutor {
private static volatile BlockingQueue<Runnable> tasks;
private static volatile Thread thread;
private static final Runnable STOP_MARKER_TASK = () -> {};
static {
tasks = new LinkedBlockingQueue<>();
thread = new Thread(() -> {
while (true) {
try {
Runnable task = tasks.take();
task.run();
} catch (Throwable t) {
Log.severe("Error in packet sender task", t);
}
}
});
thread.setName("Holographic Displays async packets");
thread.start();
}
public static void execute(Runnable task) {
tasks.add(task);
}
public static void start() {
tasks = new LinkedBlockingQueue<>();
thread = new Thread(() -> {
while (true) {
try {
Runnable task = tasks.take();
if (task == STOP_MARKER_TASK) {
return;
}
task.run();
} catch (Throwable t) {
Log.severe("Error in packet sender task", t);
}
}
});
thread.setName("Holographic Displays packet sender");
thread.start();
}
public static void stopGracefully() {
if (tasks != null) {
tasks.add(STOP_MARKER_TASK);
}
}
}

View File

@ -5,6 +5,7 @@
*/ */
package me.filoghost.holographicdisplays.core.tracking; package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine; import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener; import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker; import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
@ -84,15 +85,22 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
protected void sendSpawnPackets(Viewers<TextLineViewer> viewers) { protected void sendSpawnPackets(Viewers<TextLineViewer> viewers) {
super.sendSpawnPackets(viewers); super.sendSpawnPackets(viewers);
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates); // Copy for async use
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets)); PositionCoordinates positionCoordinates = this.positionCoordinates;
viewers.forEach(TextLineViewer::updateNextTextToSend);
PacketSenderExecutor.execute(() -> {
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates);
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets));
});
} }
@MustBeInvokedByOverriders @MustBeInvokedByOverriders
@Override @Override
protected void sendDestroyPackets(Viewers<TextLineViewer> viewers) { protected void sendDestroyPackets(Viewers<TextLineViewer> viewers) {
super.sendDestroyPackets(viewers); super.sendDestroyPackets(viewers);
viewers.sendPackets(textEntity.newDestroyPackets()); PacketSenderExecutor.execute(() -> {
viewers.sendPackets(textEntity.newDestroyPackets());
});
} }
@Override @Override
@ -100,8 +108,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
super.sendChangesPackets(viewers); super.sendChangesPackets(viewers);
if (displayTextChanged) { if (displayTextChanged) {
IndividualTextPacketGroup changePackets = textEntity.newChangePackets(); viewers.forEach(TextLineViewer::updateNextTextToSend);
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets)); PacketSenderExecutor.execute(() -> {
IndividualTextPacketGroup changePackets = textEntity.newChangePackets();
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets));
});
} }
} }
@ -109,7 +120,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
@Override @Override
protected void sendPositionChangePackets(Viewers<TextLineViewer> viewers) { protected void sendPositionChangePackets(Viewers<TextLineViewer> viewers) {
super.sendPositionChangePackets(viewers); super.sendPositionChangePackets(viewers);
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates)); // Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates));
});
} }
@Override @Override

View File

@ -5,9 +5,8 @@
*/ */
package me.filoghost.holographicdisplays.core.tracking; package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer; import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
import org.jetbrains.annotations.Nullable; import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import java.util.Objects; import java.util.Objects;
@ -15,8 +14,10 @@ class TextLineViewer extends Viewer {
private final DisplayText displayText; private final DisplayText displayText;
// Access to these variables must be synchronized, they are accessed from multiple threads
private String individualText; private String individualText;
private String lastSentText; private String lastSentText;
private String nextTextToSend;
TextLineViewer(CachedPlayer player, DisplayText displayText) { TextLineViewer(CachedPlayer player, DisplayText displayText) {
super(player); super(player);
@ -24,39 +25,47 @@ class TextLineViewer extends Viewer {
} }
public void sendTextPackets(IndividualTextPacketGroup packets) { public void sendTextPackets(IndividualTextPacketGroup packets) {
String text = getOrComputeText(); String text;
this.lastSentText = text; synchronized (this) {
text = nextTextToSend;
this.lastSentText = text;
}
sendIndividualPackets(packets, text); sendIndividualPackets(packets, text);
} }
public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) { public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) {
String text = getOrComputeText(); String text;
if (Objects.equals(lastSentText, text)) { synchronized (this) {
return; // Avoid sending unnecessary packets text = nextTextToSend;
if (Objects.equals(lastSentText, text)) {
return; // Avoid sending unnecessary packets
}
this.lastSentText = text;
} }
this.lastSentText = text;
sendIndividualPackets(packets, text); sendIndividualPackets(packets, text);
} }
private @Nullable String getOrComputeText() { public synchronized void updateNextTextToSend() {
if (displayText.containsIndividualPlaceholders()) { if (displayText.containsIndividualPlaceholders()) {
if (individualText == null) { if (individualText == null) {
individualText = displayText.computeIndividualText(this); individualText = displayText.computeIndividualText(this);
} }
return individualText; nextTextToSend = individualText;
} else { } else {
individualText = null; individualText = null;
return displayText.getGlobalText(); nextTextToSend = displayText.getGlobalText();
} }
} }
public boolean updateIndividualText() { public boolean updateIndividualText() {
String individualText = displayText.computeIndividualText(this); String individualText = displayText.computeIndividualText(this);
if (!Objects.equals(this.individualText, individualText)) { synchronized (this) {
this.individualText = individualText; if (!Objects.equals(this.individualText, individualText)) {
return true; this.individualText = individualText;
} else { return true;
return false; } else {
return false;
}
} }
} }

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
void writeBoolean(boolean flag) { void writeBoolean(boolean flag) {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -12,13 +12,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.io.IOException;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {

View File

@ -14,13 +14,14 @@ import java.util.UUID;
class PacketByteBuffer { class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer(); private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer; private final PacketDataSerializer serializer;
static PacketByteBuffer get() { static PacketByteBuffer get() {
INSTANCE.clear(); PacketByteBuffer instance = LOCAL_INSTANCE.get();
return INSTANCE; instance.clear();
return instance;
} }
private PacketByteBuffer() { private PacketByteBuffer() {