mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-22 08:19:31 +00:00
Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@681c013 Bundle spark (#11093) PaperMC/Paper@5fee9c6 Move configuration option to a system property PaperMC/Paper@aa3b356 Improve server startup logging (#11110) PaperMC/Paper@9aea240 Properly lookup plugin classes when looked up by spark PaperMC/Paper@7e91a2c Update the bundled spark version
This commit is contained in:
282
patches/server/0123-Virtual-thread-support.patch
Normal file
282
patches/server/0123-Virtual-thread-support.patch
Normal file
@@ -0,0 +1,282 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
Date: Wed, 9 Aug 2023 15:04:56 +0200
|
||||
Subject: [PATCH] Virtual thread support
|
||||
|
||||
License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://galemc.org
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
index 13a51c939b8bd17584a474217823150688af809f..ac23c85f17e0a5cd9702888a873cc470428b3e34 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
@@ -973,6 +973,22 @@ public class Metrics {
|
||||
}));
|
||||
// Gale end - SIMD support - include in metrics
|
||||
|
||||
+ // Gale start - virtual thread support - include in metrics
|
||||
+ Map<String, Map<String, Integer>> virtualThreadSupportMap = new HashMap<>(2);
|
||||
+ {
|
||||
+ Map<String, Integer> entry = new HashMap<>(2);
|
||||
+ boolean isSupported = org.galemc.gale.virtualthread.VirtualThreadService.isSupported();
|
||||
+ try {
|
||||
+ int javaMajorVersion = org.galemc.gale.virtualthread.VirtualThreadService.getJavaMajorVersion();
|
||||
+ entry.put(isSupported + " (Java " + javaMajorVersion + ")", 1);
|
||||
+ } catch (Exception ignored) {
|
||||
+ entry.put(String.valueOf(isSupported), 1);
|
||||
+ }
|
||||
+ virtualThreadSupportMap.put(String.valueOf(isSupported), entry);
|
||||
+ }
|
||||
+ metrics.addCustomChart(new Metrics.DrilldownPie("virtual_thread_support", () -> virtualThreadSupportMap));
|
||||
+ // Gale end - virtual thread support - include in metrics
|
||||
+
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java b/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..38d3b77f3f8d582ce6732afab7e6787d6d0a0ead
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java
|
||||
@@ -0,0 +1,50 @@
|
||||
+// Gale - virtual thread support
|
||||
+
|
||||
+package org.galemc.gale.virtualthread;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+import java.util.concurrent.ThreadFactory;
|
||||
+
|
||||
+/**
|
||||
+ * An implementation of {@link VirtualThreadService} that can create virtual threads directly.
|
||||
+ *
|
||||
+ * @author Martijn Muijsers
|
||||
+ */
|
||||
+final class DirectVirtualThreadService extends VirtualThreadService {
|
||||
+
|
||||
+ private DirectVirtualThreadService() {
|
||||
+ super();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ThreadFactory createFactory() {
|
||||
+ // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
|
||||
+ //throw new UnsupportedOperationException();
|
||||
+ return Thread.ofVirtual().factory();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Thread start(@NotNull Runnable task) {
|
||||
+ // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
|
||||
+ //throw new UnsupportedOperationException();
|
||||
+ Objects.requireNonNull(task, "The task to start a virtual thread cannot be null");
|
||||
+ return Thread.ofVirtual().start(task);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return A functional {@link DirectVirtualThreadService}.
|
||||
+ * @throws Throwable If creating virtual threads directly is not supported by the current runtime.
|
||||
+ * This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}.
|
||||
+ */
|
||||
+ static @NotNull DirectVirtualThreadService create() throws Throwable {
|
||||
+ // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
|
||||
+ //throw new UnsupportedOperationException();
|
||||
+ var service = new DirectVirtualThreadService();
|
||||
+ // Run some tests to verify
|
||||
+ service.runTest();
|
||||
+ // If we end up here, it works
|
||||
+ return service;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java b/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..19b83cf45034be57d11413361b1b0c8756b12a29
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java
|
||||
@@ -0,0 +1,75 @@
|
||||
+// Gale - virtual thread support
|
||||
+
|
||||
+package org.galemc.gale.virtualthread;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.util.Objects;
|
||||
+import java.util.concurrent.ThreadFactory;
|
||||
+
|
||||
+/**
|
||||
+ * An implementation of {@link VirtualThreadService} that can create virtual threads using Java reflection.
|
||||
+ *
|
||||
+ * @author Martijn Muijsers
|
||||
+ */
|
||||
+final class ReflectionVirtualThreadService extends VirtualThreadService {
|
||||
+
|
||||
+ /**
|
||||
+ * The {@link Thread}<code>#ofVirtual()</code> method.
|
||||
+ */
|
||||
+ private final @NotNull Method Thread_ofVirtual_method;
|
||||
+
|
||||
+ /**
|
||||
+ * The {@link Thread}<code>.Builder#factory()</code> method.
|
||||
+ */
|
||||
+ private final @NotNull Method Thread_Builder_factory_method;
|
||||
+
|
||||
+ /**
|
||||
+ * The {@link Thread}<code>.Builder#start(Runnable)</code> method.
|
||||
+ */
|
||||
+ private final @NotNull Method Thread_Builder_start_method;
|
||||
+
|
||||
+ private ReflectionVirtualThreadService() throws Throwable {
|
||||
+ this.Thread_ofVirtual_method = Objects.requireNonNull(Thread.class.getMethod("ofVirtual"));
|
||||
+ // The Thread.Builder class
|
||||
+ var Thread_Builder_class = Objects.requireNonNull(Class.forName("java.lang.Thread$Builder"));
|
||||
+ this.Thread_Builder_factory_method = Objects.requireNonNull(Thread_Builder_class.getMethod("factory"));
|
||||
+ this.Thread_Builder_start_method = Objects.requireNonNull(Thread_Builder_class.getMethod("start", Runnable.class));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ThreadFactory createFactory() {
|
||||
+ try {
|
||||
+ return (ThreadFactory) this.Thread_Builder_factory_method.invoke(this.Thread_ofVirtual_method.invoke(null));
|
||||
+ } catch (Exception e) {
|
||||
+ // This should not be possible because it was tested in create()
|
||||
+ throw new RuntimeException(e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Thread start(@NotNull Runnable task) {
|
||||
+ Objects.requireNonNull(task, "The task to start a virtual thread cannot be null");
|
||||
+ try {
|
||||
+ return (Thread) this.Thread_Builder_start_method.invoke(this.Thread_ofVirtual_method.invoke(null), task);
|
||||
+ } catch (Exception e) {
|
||||
+ // This should not be possible because it was tested in create()
|
||||
+ throw new RuntimeException(e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return A functional {@link ReflectionVirtualThreadService}.
|
||||
+ * @throws Throwable If creating virtual threads via reflection is not supported by the current runtime.
|
||||
+ * This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}.
|
||||
+ */
|
||||
+ static @NotNull ReflectionVirtualThreadService create() throws Throwable {
|
||||
+ // This will already throw something if the reflection fails
|
||||
+ var service = new ReflectionVirtualThreadService();
|
||||
+ // Run some tests to verify
|
||||
+ service.runTest();
|
||||
+ // If we end up here, it works
|
||||
+ return service;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java b/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e9757e8ade7198accb7cf34390ed70628a0f7e33
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java
|
||||
@@ -0,0 +1,104 @@
|
||||
+// Gale - virtual thread support
|
||||
+
|
||||
+package org.galemc.gale.virtualthread;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.concurrent.ThreadFactory;
|
||||
+
|
||||
+/**
|
||||
+ * An abstract service to create virtual threads.
|
||||
+ *
|
||||
+ * @author Martijn Muijsers
|
||||
+ */
|
||||
+public sealed abstract class VirtualThreadService permits ReflectionVirtualThreadService, DirectVirtualThreadService {
|
||||
+
|
||||
+ /**
|
||||
+ * @return A {@link ThreadFactory} that produces virtual threads.
|
||||
+ */
|
||||
+ public abstract @NotNull ThreadFactory createFactory();
|
||||
+
|
||||
+ /**
|
||||
+ * @param task The runnable for the thread to execute.
|
||||
+ * @return A virtual thread that has been started with the given task.
|
||||
+ */
|
||||
+ public abstract @NotNull Thread start(Runnable task);
|
||||
+
|
||||
+ /**
|
||||
+ * Runs a test on the {@link #createFactory} and {@link #start} methods,
|
||||
+ * which certainly throws some {@link Throwable} if something goes wrong.
|
||||
+ */
|
||||
+ protected void runTest() throws Throwable {
|
||||
+ // This will definitely throw something if it doesn't work
|
||||
+ try {
|
||||
+ this.start(() -> {}).join();
|
||||
+ } catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one
|
||||
+ try {
|
||||
+ var thread = this.createFactory().newThread(() -> {});
|
||||
+ thread.start();
|
||||
+ thread.join();
|
||||
+ } catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one
|
||||
+ // If we end up here, it works
|
||||
+ }
|
||||
+
|
||||
+ private static boolean initialized = false;
|
||||
+
|
||||
+ /**
|
||||
+ * The {@link VirtualThreadService} for the current runtime,
|
||||
+ * or null if virtual threads are not supported, or if not {@link #initialized} yet.
|
||||
+ */
|
||||
+ private static @Nullable VirtualThreadService implementation;
|
||||
+
|
||||
+ /**
|
||||
+ * @return Whether virtual threads are supported on the current runtime.
|
||||
+ */
|
||||
+ public static boolean isSupported() {
|
||||
+ return get() != null;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The {@link VirtualThreadService} for the current runtime,
|
||||
+ * or null if virtual threads are not {@linkplain #isSupported() supported}.
|
||||
+ *
|
||||
+ * This method is thread-safe only after the first time it has been fully run.
|
||||
+ */
|
||||
+ public static @Nullable VirtualThreadService get() {
|
||||
+ if (!initialized) {
|
||||
+ initialized = true;
|
||||
+ try {
|
||||
+ implementation = DirectVirtualThreadService.create();
|
||||
+ } catch (Throwable ignored) {
|
||||
+ try {
|
||||
+ implementation = ReflectionVirtualThreadService.create();
|
||||
+ } catch (Throwable ignored2) {}
|
||||
+ }
|
||||
+ }
|
||||
+ return implementation;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The minimum major version of Java that is known to support using virtual threads
|
||||
+ * (although possibly behind a feature preview flag).
|
||||
+ */
|
||||
+ public static final int minimumJavaMajorVersionWithFeaturePreview = 19;
|
||||
+
|
||||
+ /**
|
||||
+ * The minimum major version of Java that is known to support using virtual threads
|
||||
+ * even without any feature preview flags.
|
||||
+ */
|
||||
+ public static final int minimumJavaMajorVersionWithoutFeaturePreview = 21;
|
||||
+
|
||||
+ public static int getJavaMajorVersion() {
|
||||
+ var version = System.getProperty("java.version");
|
||||
+ if (version.startsWith("1.")) {
|
||||
+ return version.charAt(2) - '0';
|
||||
+ }
|
||||
+ if (version.contains("-")) {
|
||||
+ version = version.substring(0, version.indexOf("-"));
|
||||
+ }
|
||||
+
|
||||
+ int dotIndex = version.indexOf(".");
|
||||
+ return Integer.parseInt(dotIndex == -1 ? version : version.substring(0, dotIndex));
|
||||
+ }
|
||||
+}
|
||||
Reference in New Issue
Block a user