mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +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.Framebuffer;
|
||||||
import net.minestom.server.map.MapColors;
|
import net.minestom.server.map.MapColors;
|
||||||
import net.minestom.server.timer.Task;
|
import net.minestom.server.timer.Task;
|
||||||
|
import net.minestom.server.utils.thread.ThreadBindingExecutor;
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||||
@ -27,6 +28,8 @@ public abstract class GLFWCapableBuffer {
|
|||||||
private final ByteBuffer colorsBuffer;
|
private final ByteBuffer colorsBuffer;
|
||||||
private boolean onlyMapColors;
|
private boolean onlyMapColors;
|
||||||
|
|
||||||
|
private static ThreadBindingExecutor threadBindingPool;
|
||||||
|
|
||||||
protected GLFWCapableBuffer(int width, int height) {
|
protected GLFWCapableBuffer(int width, int height) {
|
||||||
this(width, height, GLFW_NATIVE_CONTEXT_API, GLFW_OPENGL_API);
|
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.");
|
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() {
|
public GLFWCapableBuffer unbindContextFromThread() {
|
||||||
@ -80,14 +89,17 @@ public abstract class GLFWCapableBuffer {
|
|||||||
return MinecraftServer.getSchedulerManager()
|
return MinecraftServer.getSchedulerManager()
|
||||||
.buildTask(new Runnable() {
|
.buildTask(new Runnable() {
|
||||||
private boolean first = true;
|
private boolean first = true;
|
||||||
|
private final Runnable subAction = () -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if(first) {
|
if(first) {
|
||||||
changeRenderingThreadToCurrent();
|
changeRenderingThreadToCurrent();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
render(rendering);
|
render(rendering);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
threadBindingPool.execute(subAction);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.repeat(period)
|
.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