1.4 start, virtual threads support
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
group=net.gensokyoreimagined.nitori
|
||||
version=1.3-SNAPSHOT
|
||||
version=1.4-SNAPSHOT
|
||||
description=Converting patches into mixins, for the Ignite Framework
|
||||
|
||||
org.gradle.parallel=true
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.gensokyoreimagined.nitori.mixin.alloc;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
@Mixin(ResourceLocation.class)
|
||||
public class MixinIdentifier {
|
||||
|
||||
@Shadow @Final
|
||||
private String namespace;
|
||||
|
||||
@Shadow @Final
|
||||
private String path;
|
||||
|
||||
@Unique
|
||||
private String nitori$cachedString = null;
|
||||
|
||||
/**
|
||||
* @author ishland
|
||||
* @reason cache toString
|
||||
*/
|
||||
@Overwrite
|
||||
public String toString() {
|
||||
if (this.nitori$cachedString != null) return this.nitori$cachedString;
|
||||
final String s = this.namespace + ":" + this.path;
|
||||
this.nitori$cachedString = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
package net.gensokyoreimagined.nitori.mixin;
|
||||
package net.gensokyoreimagined.nitori.mixin.entity.micro_opts;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -0,0 +1,50 @@
|
||||
// Gale - virtual thread support
|
||||
|
||||
package net.gensokyoreimagined.nitori.mixin.virtual_thread;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Gale - virtual thread support
|
||||
|
||||
package net.gensokyoreimagined.nitori.mixin.virtual_thread;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Gale - virtual thread support
|
||||
|
||||
package net.gensokyoreimagined.nitori.mixin.virtual_thread;
|
||||
|
||||
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';
|
||||
}
|
||||
int dotIndex = version.indexOf(".");
|
||||
return Integer.parseInt(dotIndex == -1 ? version : version.substring(0, dotIndex));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "Nitori",
|
||||
"version": "1.3-SNAPSHOT",
|
||||
"version": "1.4-SNAPSHOT",
|
||||
"mixins": [
|
||||
"mixins.core.json"
|
||||
]
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"MixinGameRules",
|
||||
"MixinIteratorSafeOrderedReferenceSet",
|
||||
"MixinLevelStorageAccess",
|
||||
"MixinMob",
|
||||
"entity.micro_opts.MixinMob",
|
||||
"MixinNoiseBasedChunkGenerator",
|
||||
"MixinPlayer",
|
||||
"MixinPlayerList",
|
||||
@@ -31,6 +31,7 @@
|
||||
"alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin",
|
||||
"alloc.composter.ComposterMixin$ComposterBlockFullComposterInventoryMixin",
|
||||
"alloc.biome_temprature_leak.Biome_threadLocalMixin",
|
||||
"alloc.MixinIdentifier",
|
||||
"cached_hashcode.BlockNeighborGroupMixin",
|
||||
"collections.attributes.AttributeContainerMixin",
|
||||
"collections.block_entity_tickers.WorldChunkMixin",
|
||||
|
||||
Reference in New Issue
Block a user