9
0
mirror of https://github.com/Dreeam-qwq/Gale.git synced 2025-12-23 16:59:23 +00:00
Files
Gale/patches/server/0145-Virtual-threads-utility.patch
2023-03-22 16:49:11 +01:00

159 lines
5.5 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martijn Muijsers <martijnmuijsers@live.nl>
Date: Mon, 13 Feb 2023 21:40:20 +0100
Subject: [PATCH] Virtual threads utility
License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html)
Gale - https://galemc.org
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..0ae0cde2ed65939f84d0f843e2c2b89beb76ed3f
--- /dev/null
+++ b/src/main/java/org/galemc/gale/util/VirtualThreads.java
@@ -0,0 +1,144 @@
+// Gale - virtual threads utility
+
+package org.galemc.gale.util;
+
+import org.galemc.gale.executor.annotation.YieldFree;
+import org.galemc.gale.executor.annotation.thread.AnyThreadSafe;
+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.
+ *
+ * @author Martijn Muijsers under AGPL-3.0
+ */
+@SuppressWarnings({"JavadocReference", "Since15"})
+@AnyThreadSafe
+@YieldFree
+public final class VirtualThreads {
+
+ private VirtualThreads() {}
+
+ /**
+ * The minimum major version of Java that is known to support using virtual threads.
+ */
+ public static final int minimumJavaMajorVersion = 19;
+
+ /**
+ * The {@link Thread#ofVirtual()} method, obtained via Reflection,
+ * or null if it could not be obtained.
+ */
+ public static final @Nullable Method Thread_ofVirtual_method;
+
+ /**
+ * The {@link Thread.Builder} class, obtained via Reflection,
+ * or null if it could not be obtained.
+ */
+ public static final @Nullable Class<?> Thread_Builder_class;
+
+ /**
+ * The {@link Thread.Builder#factory()} method, obtained via Reflection,
+ * or null if it could not be obtained.
+ */
+ public 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.
+ */
+ public 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;
+ }
+
+}