mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-30 21:17:53 +01:00
Merge pull request #436 from Minestom/feature/thread-bound-tasks
Fix GLFW-based framebuffers not using the proper threads
This commit is contained in:
commit
7b046c2225
@ -4,6 +4,7 @@ import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.map.Framebuffer;
|
||||
import net.minestom.server.map.MapColors;
|
||||
import net.minestom.server.timer.Task;
|
||||
import net.minestom.server.utils.thread.ThreadBindingExecutor;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
@ -27,6 +28,8 @@ public abstract class GLFWCapableBuffer {
|
||||
private final ByteBuffer colorsBuffer;
|
||||
private boolean onlyMapColors;
|
||||
|
||||
private static ThreadBindingExecutor threadBindingPool;
|
||||
|
||||
protected GLFWCapableBuffer(int width, int height) {
|
||||
this(width, height, GLFW_NATIVE_CONTEXT_API, GLFW_OPENGL_API);
|
||||
}
|
||||
@ -60,6 +63,12 @@ public abstract class GLFWCapableBuffer {
|
||||
throw new RuntimeException("("+errcode+") Failed to create GLFW Window.");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(GLFWCapableBuffer.class) {
|
||||
if(threadBindingPool == null) {
|
||||
threadBindingPool = new ThreadBindingExecutor(MinecraftServer.THREAD_COUNT_SCHEDULER, MinecraftServer.THREAD_NAME_SCHEDULER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GLFWCapableBuffer unbindContextFromThread() {
|
||||
@ -80,14 +89,17 @@ public abstract class GLFWCapableBuffer {
|
||||
return MinecraftServer.getSchedulerManager()
|
||||
.buildTask(new Runnable() {
|
||||
private boolean first = true;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
private final Runnable subAction = () -> {
|
||||
if(first) {
|
||||
changeRenderingThreadToCurrent();
|
||||
first = false;
|
||||
}
|
||||
render(rendering);
|
||||
};
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
threadBindingPool.execute(subAction);
|
||||
}
|
||||
})
|
||||
.repeat(period)
|
||||
|
@ -0,0 +1,92 @@
|
||||
package net.minestom.server.utils.thread;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Executor service which will always give the same thread to a given Runnable.
|
||||
* Uses {@link Runnable#hashCode()} to determine the thread to assign.
|
||||
*/
|
||||
public class ThreadBindingExecutor extends AbstractExecutorService {
|
||||
|
||||
private MinestomThread[] threadExecutors;
|
||||
|
||||
/**
|
||||
* Creates a non-local thread-binding executor
|
||||
*
|
||||
* @param nThreads the number of threads
|
||||
* @param name the name of the thread pool
|
||||
*/
|
||||
public ThreadBindingExecutor(int nThreads, String name) {
|
||||
this(nThreads, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nThreads the number of threads
|
||||
* @param name the name of the thread pool
|
||||
* @param local set to true if this executor is only used inside a method and should *not* be kept in the internal list of executors
|
||||
*/
|
||||
public ThreadBindingExecutor(int nThreads, String name, boolean local) {
|
||||
threadExecutors = new MinestomThread[nThreads];
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
threadExecutors[i] = new MinestomThread(1, name, local);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
for (MinestomThread t : threadExecutors) {
|
||||
t.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
List<Runnable> allTasks = new LinkedList<>();
|
||||
for (MinestomThread t : threadExecutors) {
|
||||
allTasks.addAll(t.shutdownNow());
|
||||
}
|
||||
return allTasks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
for (MinestomThread t : threadExecutors) {
|
||||
if(!t.isShutdown())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
for (MinestomThread t : threadExecutors) {
|
||||
if(!t.isShutdown())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
|
||||
boolean terminated = true;
|
||||
for (MinestomThread t : threadExecutors) {
|
||||
terminated &= t.awaitTermination(timeout, unit);
|
||||
}
|
||||
return terminated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable command) {
|
||||
int hash = command.hashCode();
|
||||
if(hash < 0) hash = -hash;
|
||||
int bucket = hash % threadExecutors.length;
|
||||
|
||||
threadExecutors[bucket].execute(command);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user