Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit ab71e1b

Browse files
Implement a single-threaded emulation of DeferredWorkQueue (#104)
* Implement a single-threaded emulation of DeferredWorkQueue * Add main thread checks and docs
1 parent 827b734 commit ab71e1b

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.fml;
21+
22+
import java.util.concurrent.Callable;
23+
import java.util.concurrent.CompletableFuture;
24+
import java.util.function.Supplier;
25+
26+
import net.minecraft.util.thread.ThreadExecutor;
27+
28+
import net.fabricmc.loader.api.FabricLoader;
29+
30+
/**
31+
* A dummy version of DeferredWorkQueue which instantly completes futures on the same thread that calls it.
32+
*
33+
* <p>Forge mods use this during loading to defer calls back to the loading thread, but they are already loading
34+
* on the main thread under Patchwork.
35+
*/
36+
public class DeferredWorkQueue {
37+
private static void mainThreadCheck() {
38+
final Object gameInstance = FabricLoader.getInstance().getGameInstance();
39+
40+
if (!((ThreadExecutor) gameInstance).isOnThread()) {
41+
throw new IllegalStateException("Multiple threads during loading is not supported.");
42+
}
43+
}
44+
45+
public static CompletableFuture<Void> runLater(Runnable workToEnqueue) {
46+
mainThreadCheck();
47+
workToEnqueue.run();
48+
return CompletableFuture.completedFuture(null);
49+
}
50+
51+
public static CompletableFuture<Void> runLaterChecked(CheckedRunnable workToEnqueue) {
52+
mainThreadCheck();
53+
CompletableFuture<Void> future = new CompletableFuture<>();
54+
55+
try {
56+
workToEnqueue.run();
57+
future.complete(null);
58+
} catch (Throwable t) {
59+
future.completeExceptionally(t);
60+
}
61+
62+
return future;
63+
}
64+
65+
public static <T> CompletableFuture<T> getLater(Supplier<T> workToEnqueue) {
66+
mainThreadCheck();
67+
return CompletableFuture.completedFuture(workToEnqueue.get());
68+
}
69+
70+
public static <T> CompletableFuture<T> getLaterChecked(Callable<T> workToEnqueue) {
71+
mainThreadCheck();
72+
CompletableFuture<T> future = new CompletableFuture<>();
73+
74+
try {
75+
future.complete(workToEnqueue.call());
76+
} catch (Throwable t) {
77+
future.completeExceptionally(t);
78+
}
79+
80+
return future;
81+
}
82+
83+
@FunctionalInterface
84+
public interface CheckedRunnable {
85+
void run() throws Exception;
86+
}
87+
}

0 commit comments

Comments
 (0)