Inline TickThread tick method

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-09-16 06:21:45 +02:00
parent f1a1adc74f
commit 2589cc4f3e
3 changed files with 47 additions and 46 deletions

View File

@ -27,7 +27,7 @@ public interface Acquirable<T> {
final Thread currentThread = Thread.currentThread();
if (currentThread instanceof TickThread) {
return ((TickThread) currentThread).entries().stream()
.flatMap(chunkEntry -> chunkEntry.getEntities().stream());
.flatMap(chunkEntry -> chunkEntry.entities().stream());
}
return Stream.empty();
}
@ -162,7 +162,7 @@ public interface Acquirable<T> {
public TickThread getTickThread() {
final ThreadDispatcher.ChunkEntry entry = this.chunkEntry;
return entry != null ? entry.getThread() : null;
return entry != null ? entry.thread() : null;
}
}
}

View File

@ -5,13 +5,11 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Phaser;
import java.util.concurrent.locks.ReentrantLock;
/**
* Used to link chunks into multiple groups.
@ -98,37 +96,8 @@ public final class ThreadDispatcher {
}
// Execute tick
this.phaser.register();
final TickThread thread = entry.getKey();
thread.startTick(chunkEntries, () -> {
final ReentrantLock lock = thread.lock();
lock.lock();
for (ChunkEntry chunkEntry : chunkEntries) {
final Chunk chunk = chunkEntry.chunk;
if (!ChunkUtils.isLoaded(chunk)) return;
try {
chunk.tick(time);
} catch (Throwable e) {
MinecraftServer.getExceptionManager().handleException(e);
}
final List<Entity> entities = chunkEntry.entities;
if (!entities.isEmpty()) {
for (Entity entity : entities) {
if (lock.hasQueuedThreads()) {
lock.unlock();
// #acquire() callbacks should be called here
lock.lock();
}
try {
entity.tick(time);
} catch (Throwable e) {
MinecraftServer.getExceptionManager().handleException(e);
}
}
}
}
lock.unlock();
// #acquire() callbacks
});
TickThread thread = entry.getKey();
thread.startTick(chunkEntries, time);
}
this.phaser.arriveAndAwaitAdvance();
}
@ -268,15 +237,15 @@ public final class ThreadDispatcher {
this.chunk = chunk;
}
public @NotNull TickThread getThread() {
public @NotNull TickThread thread() {
return thread;
}
public @NotNull Chunk getChunk() {
public @NotNull Chunk chunk() {
return chunk;
}
public @NotNull List<Entity> getEntities() {
public @NotNull List<Entity> entities() {
return entities;
}

View File

@ -1,10 +1,14 @@
package net.minestom.server.thread;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Chunk;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Phaser;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
@ -14,12 +18,13 @@ import java.util.concurrent.locks.ReentrantLock;
* <p>
* Created in {@link ThreadDispatcher}, and awaken every tick with a task to execute.
*/
@ApiStatus.Internal
public final class TickThread extends Thread {
private final ReentrantLock lock = new ReentrantLock();
private final Phaser phaser;
private volatile boolean stop;
private Runnable tickRunnable;
private long tickTime;
private boolean isTicking;
private Collection<ThreadDispatcher.ChunkEntry> entries;
@ -33,16 +38,46 @@ public final class TickThread extends Thread {
LockSupport.park(this);
while (!stop) {
this.isTicking = true;
this.tickRunnable.run();
tick();
this.isTicking = false;
this.phaser.arriveAndDeregister();
LockSupport.park(this);
}
}
void startTick(Collection<ThreadDispatcher.ChunkEntry> entries, Runnable runnable) {
this.tickRunnable = runnable;
private void tick() {
this.lock.lock();
for (ThreadDispatcher.ChunkEntry entry : entries) {
final Chunk chunk = entry.chunk();
try {
chunk.tick(tickTime);
} catch (Throwable e) {
MinecraftServer.getExceptionManager().handleException(e);
}
final List<Entity> entities = entry.entities();
if (!entities.isEmpty()) {
for (Entity entity : entities) {
if (lock.hasQueuedThreads()) {
this.lock.unlock();
// #acquire() callbacks should be called here
this.lock.lock();
}
try {
entity.tick(tickTime);
} catch (Throwable e) {
MinecraftServer.getExceptionManager().handleException(e);
}
}
}
}
this.lock.unlock();
// #acquire() callbacks
}
void startTick(Collection<ThreadDispatcher.ChunkEntry> entries, long tickTime) {
this.tickTime = tickTime;
this.entries = entries;
this.stop = false;
LockSupport.unpark(this);
}
@ -59,10 +94,7 @@ public final class TickThread extends Thread {
return lock;
}
/**
* Shutdowns the thread. Cannot be undone.
*/
public void shutdown() {
void shutdown() {
this.stop = true;
LockSupport.unpark(this);
}