mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-28 11:09:09 +00:00
181 lines
6.6 KiB
Diff
181 lines
6.6 KiB
Diff
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: AGPL-3.0 (https://www.gnu.org/licenses/agpl-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 5a85df87042a28ba6f7f5840fa80c5aaea62bbee..78a76b6f7bedf8aef94614fcb654c2cc3d6b3749 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
|
|
@@ -914,6 +914,11 @@ public class Metrics {
|
|
}));
|
|
// Gale end - SIMD support - include in metrics
|
|
|
|
+ // Gale start - virtual thread support - include in metrics
|
|
+ var virtualThreadSupport = String.valueOf(org.galemc.gale.util.VirtualThreads.areVirtualThreadsEnabled);
|
|
+ metrics.addCustomChart(new Metrics.SimplePie("virtual_thread_support", () -> virtualThreadSupport));
|
|
+ // Gale end - virtual thread support - include in metrics
|
|
+
|
|
}
|
|
|
|
}
|
|
diff --git a/src/main/java/org/galemc/gale/util/VirtualThreads.java b/src/main/java/org/galemc/gale/util/VirtualThreads.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..736cadd95a6ba3e2c4b6053b554e697d90f14d47
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/galemc/gale/util/VirtualThreads.java
|
|
@@ -0,0 +1,150 @@
|
|
+// Gale - virtual thread support
|
|
+
|
|
+package org.galemc.gale.util;
|
|
+
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+
|
|
+import java.lang.reflect.Method;
|
|
+import java.util.concurrent.ThreadFactory;
|
|
+
|
|
+/**
|
|
+ * A utility class to detect and provide the ability to use virtual threads when they are available,
|
|
+ * but compile against and run on Java versions that do not support virtual threads.
|
|
+ *
|
|
+ * @author Martijn Muijsers under AGPL-3.0
|
|
+ */
|
|
+@SuppressWarnings({"JavadocReference", "Since15"})
|
|
+public final class VirtualThreads {
|
|
+
|
|
+ private VirtualThreads() {
|
|
+ throw new RuntimeException();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * 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;
|
|
+
|
|
+ /**
|
|
+ * The {@link Thread#ofVirtual()} method, obtained via Reflection,
|
|
+ * or null if it could not be obtained.
|
|
+ */
|
|
+ private static final @Nullable Method Thread_ofVirtual_method;
|
|
+
|
|
+ /**
|
|
+ * The {@link Thread.Builder} class, obtained via Reflection,
|
|
+ * or null if it could not be obtained.
|
|
+ */
|
|
+ private static final @Nullable Class<?> Thread_Builder_class;
|
|
+
|
|
+ /**
|
|
+ * The {@link Thread.Builder#factory()} method, obtained via Reflection,
|
|
+ * or null if it could not be obtained.
|
|
+ */
|
|
+ private static final @Nullable Method Thread_Builder_factory_method;
|
|
+
|
|
+ /**
|
|
+ * The {@link Thread.Builder#start(Runnable)} method, obtained via Reflection,
|
|
+ * or null if it could not be obtained.
|
|
+ */
|
|
+ private static final @Nullable Method Thread_Builder_start_method;
|
|
+
|
|
+ /**
|
|
+ * Whether virtual threads are enabled.
|
|
+ */
|
|
+ public static final boolean areVirtualThreadsEnabled;
|
|
+
|
|
+ /**
|
|
+ * @return A {@link ThreadFactory} that produces {@link java.lang.VirtualThread}s,
|
|
+ * or null if {@link #areVirtualThreadsEnabled} is false.
|
|
+ */
|
|
+ public static @Nullable ThreadFactory createVirtualThreadFactory() {
|
|
+ if (!areVirtualThreadsEnabled) {
|
|
+ return null;
|
|
+ }
|
|
+ try {
|
|
+ //noinspection DataFlowIssue
|
|
+ return (ThreadFactory) Thread_Builder_factory_method.invoke(Thread_ofVirtual_method.invoke(null));
|
|
+ } catch (Exception e) {
|
|
+ // We assume this does not happen when areVirtualThreadsEnabled has been set to true
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @param task The runnable for the thread to execute.
|
|
+ * @return A {@link java.lang.VirtualThread} that has been started with the given task,
|
|
+ * or null if {@link #areVirtualThreadsEnabled} is false.
|
|
+ */
|
|
+ public static @Nullable Thread startVirtualThread(Runnable task) {
|
|
+ if (!areVirtualThreadsEnabled) {
|
|
+ return null;
|
|
+ }
|
|
+ try {
|
|
+ //noinspection DataFlowIssue
|
|
+ return (Thread) Thread_Builder_start_method.invoke(Thread_ofVirtual_method.invoke(null), task);
|
|
+ } catch (Exception e) {
|
|
+ // We assume this does not happen when areVirtualThreadsEnabled has been set to true
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static {
|
|
+ {
|
|
+ Method method;
|
|
+ try {
|
|
+ method = Thread.class.getMethod("ofVirtual");
|
|
+ } catch (Throwable ignored) {
|
|
+ method = null;
|
|
+ }
|
|
+ Thread_ofVirtual_method = method;
|
|
+ if (Thread_ofVirtual_method != null) {
|
|
+ Thread_ofVirtual_method.setAccessible(true);
|
|
+ }
|
|
+ }
|
|
+ {
|
|
+ Class<?> clazz;
|
|
+ try {
|
|
+ //noinspection DataFlowIssue
|
|
+ clazz = Thread_ofVirtual_method.invoke(null).getClass();
|
|
+ } catch (Throwable ignored) {
|
|
+ clazz = null;
|
|
+ }
|
|
+ Thread_Builder_class = clazz;
|
|
+ }
|
|
+ {
|
|
+ Method method;
|
|
+ try {
|
|
+ //noinspection DataFlowIssue
|
|
+ method = Thread_Builder_class.getMethod("factory");
|
|
+ } catch (Throwable ignored) {
|
|
+ method = null;
|
|
+ }
|
|
+ Thread_Builder_factory_method = method;
|
|
+ if (Thread_Builder_factory_method != null) {
|
|
+ Thread_Builder_factory_method.setAccessible(true);
|
|
+ }
|
|
+ }
|
|
+ {
|
|
+ Method method;
|
|
+ try {
|
|
+ method = Thread_Builder_class.getMethod("start");
|
|
+ } catch (Throwable ignored) {
|
|
+ method = null;
|
|
+ }
|
|
+ Thread_Builder_start_method = method;
|
|
+ if (Thread_Builder_start_method != null) {
|
|
+ Thread_Builder_start_method.setAccessible(true);
|
|
+ }
|
|
+ }
|
|
+ areVirtualThreadsEnabled = Thread_ofVirtual_method != null && Thread_Builder_class != null && Thread_Builder_factory_method != null && Thread_Builder_start_method != null;
|
|
+ }
|
|
+
|
|
+}
|