Allow a single low-priority worker thread when cause_lag_by_disabling_threads is enabled
On a system with few cores, we should still benefit from using one low-priority background thread for worldgen, because it avoids the server thread stopping to handle it itself. The thread will be blocked from progressing while higher-priority work (e.g. rendering or server ticking) is in progress.
This commit is contained in:
parent
db13f39b30
commit
4ff7d4c554
|
|
@ -1,7 +1,7 @@
|
|||
package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import org.embeddedt.modernfix.util.DirectExecutorService;
|
||||
import org.embeddedt.modernfix.util.SingleThreadedWorkerService;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
|
|
@ -12,5 +12,5 @@ import java.util.concurrent.ExecutorService;
|
|||
@Mixin(Util.class)
|
||||
public class UtilMixin {
|
||||
@Shadow @Final @Mutable
|
||||
private static final ExecutorService BACKGROUND_EXECUTOR = new DirectExecutorService();
|
||||
private static final ExecutorService BACKGROUND_EXECUTOR = new SingleThreadedWorkerService();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
package org.embeddedt.modernfix.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DirectExecutorService extends AbstractExecutorService {
|
||||
private boolean isShutdown;
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
isShutdown = true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
isShutdown = true;
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return isShutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return isShutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable command) {
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.embeddedt.modernfix.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Like {@link Executors#newSingleThreadExecutor()}, but handles the case where the background executor schedules
|
||||
* a task to itself and waits for it the way a direct executor would.
|
||||
*/
|
||||
public class SingleThreadedWorkerService extends AbstractExecutorService {
|
||||
private final AtomicReference<Thread> thread = new AtomicReference<>();
|
||||
private final ExecutorService executorService;
|
||||
|
||||
public SingleThreadedWorkerService() {
|
||||
this.executorService = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r, "Worker-Main");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
thread.set(t);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
return executorService.shutdownNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return executorService.isShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return executorService.isTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
|
||||
return executorService.awaitTermination(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable command) {
|
||||
if (Thread.currentThread() == thread.get()) {
|
||||
command.run();
|
||||
} else {
|
||||
executorService.execute(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user