Improve TickThread

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-09-12 23:20:22 +02:00
parent 06d8586f7f
commit d9c32fe198
2 changed files with 27 additions and 58 deletions

View File

@ -39,8 +39,7 @@ public final class ThreadDispatcher {
this.threads = new ArrayList<>(threadCount);
for (int i = 0; i < threadCount; i++) {
final TickThread.BatchRunnable batchRunnable = new TickThread.BatchRunnable();
final TickThread tickThread = new TickThread(batchRunnable, i);
final TickThread tickThread = new TickThread(phaser, i);
this.threads.add(tickThread);
tickThread.start();
}
@ -98,7 +97,7 @@ public final class ThreadDispatcher {
}
// Execute tick
this.phaser.register();
thread.runnable.startTick(phaser, () -> {
thread.startTick(() -> {
Acquirable.refreshEntries(chunkEntries);
final ReentrantLock lock = thread.getLock();

View File

@ -1,11 +1,9 @@
package net.minestom.server.thread;
import net.minestom.server.MinecraftServer;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Phaser;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
@ -14,16 +12,33 @@ import java.util.concurrent.locks.ReentrantLock;
* <p>
* Created in {@link ThreadDispatcher}, and awaken every tick with a task to execute.
*/
public class TickThread extends Thread {
protected final BatchRunnable runnable;
public final class TickThread extends Thread {
private final ReentrantLock lock = new ReentrantLock();
private final Phaser phaser;
private volatile boolean stop;
private Runnable tickRunnable;
public TickThread(@NotNull BatchRunnable runnable, int number) {
super(runnable, MinecraftServer.THREAD_NAME_TICK + "-" + number);
this.runnable = runnable;
public TickThread(Phaser phaser, int number) {
super(MinecraftServer.THREAD_NAME_TICK + "-" + number);
this.phaser = phaser;
}
this.runnable.setLinkedThread(this);
@Override
public void run() {
while (!stop) {
final Runnable localRunnable = tickRunnable;
if (localRunnable != null) {
localRunnable.run();
this.tickRunnable = null;
this.phaser.arriveAndDeregister();
}
LockSupport.park(this);
}
}
void startTick(@NotNull Runnable runnable) {
this.tickRunnable = runnable;
LockSupport.unpark(this);
}
/**
@ -39,52 +54,7 @@ public class TickThread extends Thread {
* Shutdowns the thread. Cannot be undone.
*/
public void shutdown() {
this.runnable.stop = true;
this.stop = true;
LockSupport.unpark(this);
}
protected static class BatchRunnable implements Runnable {
private static final AtomicReferenceFieldUpdater<BatchRunnable, TickContext> CONTEXT_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(BatchRunnable.class, TickContext.class, "tickContext");
private volatile boolean stop;
private TickThread tickThread;
private volatile TickContext tickContext;
@Override
public void run() {
Check.notNull(tickThread, "The linked BatchThread cannot be null!");
while (!stop) {
final TickContext localContext = tickContext;
// The context is necessary to control the tick rates
if (localContext != null) {
// Execute tick
CONTEXT_UPDATER.compareAndSet(this, localContext, null);
localContext.runnable.run();
localContext.phaser.arriveAndDeregister();
}
LockSupport.park(this);
}
}
protected void startTick(@NotNull Phaser phaser, @NotNull Runnable runnable) {
this.tickContext = new TickContext(phaser, runnable);
LockSupport.unpark(tickThread);
}
private void setLinkedThread(TickThread tickThread) {
this.tickThread = tickThread;
}
}
private static class TickContext {
private final Phaser phaser;
private final Runnable runnable;
private TickContext(@NotNull Phaser phaser, @NotNull Runnable runnable) {
this.phaser = phaser;
this.runnable = runnable;
}
}
}