mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Added preliminary support for keeping track of which thread is currently running. This implementation simply overrides setTimeout() to keep track of the thread that is running. It restores it to the main thread after a thread finishes running. May need to override other async methods e.g. XMLHTTPRequest, but not sure yet. This change may be sufficient if all of our async methods meant to emulate threads use the setTimeout construction.
This commit is contained in:
parent
b37c92b02d
commit
e6e52d1be5
|
@ -24,7 +24,11 @@ import org.teavm.runtime.Async;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TThread extends TObject implements TRunnable {
|
||||
private static TThread currentThread = new TThread(TString.wrap("main"));
|
||||
private static TThread mainThread = new TThread(TString.wrap("main"));
|
||||
private static TThread currentThread = mainThread;
|
||||
private static long nextId = 1;
|
||||
private static int activeCount = 1;
|
||||
private long id;
|
||||
private TString name;
|
||||
private TRunnable target;
|
||||
|
||||
|
@ -33,16 +37,17 @@ public class TThread extends TObject implements TRunnable {
|
|||
}
|
||||
|
||||
public TThread(TString name) {
|
||||
this(name, null);
|
||||
this(null, name);
|
||||
}
|
||||
|
||||
public TThread(TRunnable target) {
|
||||
this(null, target);
|
||||
this(target, null );
|
||||
}
|
||||
|
||||
public TThread(TString name, TRunnable target) {
|
||||
public TThread(TRunnable target, TString name ) {
|
||||
this.name = name;
|
||||
this.target = target;
|
||||
id=nextId++;
|
||||
}
|
||||
|
||||
@PluggableDependency(ThreadNativeGenerator.class)
|
||||
|
@ -50,7 +55,23 @@ public class TThread extends TObject implements TRunnable {
|
|||
public native void start();
|
||||
|
||||
private static void launch(TThread thread) {
|
||||
try {
|
||||
activeCount++;
|
||||
setCurrentThread(thread);
|
||||
thread.run();
|
||||
} finally {
|
||||
activeCount--;
|
||||
setCurrentThread(mainThread);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void setCurrentThread(TThread thread){
|
||||
currentThread = thread;
|
||||
}
|
||||
private static TThread getMainThread(){
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,11 +105,11 @@ public class TThread extends TObject implements TRunnable {
|
|||
}
|
||||
|
||||
public static int activeCount() {
|
||||
return 1;
|
||||
return activeCount;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
public static boolean holdsLock(@SuppressWarnings("unused") TObject obj) {
|
||||
|
|
|
@ -71,7 +71,6 @@ public class ThreadNativeGenerator implements Generator, DependencyPlugin {
|
|||
|
||||
private void generateStart(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String obj = context.getParameterName(0);
|
||||
|
||||
writer.append("setTimeout(function() { $rt_rootInvocationAdapter(").appendMethodBody(launchRef).append(")(")
|
||||
.append(obj).append(");},0);").softNewLine();
|
||||
}
|
||||
|
|
|
@ -344,6 +344,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
internDep.use();
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "length", int.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Thread.class, "currentThread", Thread.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Thread.class, "getMainThread", Thread.class), null).use();
|
||||
dependencyChecker.linkMethod(
|
||||
new MethodReference(Thread.class, "setCurrentThread", Thread.class, void.class), null).use();
|
||||
MethodDependency exceptionCons = dependencyChecker.linkMethod(new MethodReference(
|
||||
NoClassDefFoundError.class, "<init>", String.class, void.class), null);
|
||||
exceptionCons.use();
|
||||
|
@ -422,6 +426,29 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
listener.begin(renderer, target);
|
||||
}
|
||||
sourceWriter.append("\"use strict\";").newLine();
|
||||
|
||||
|
||||
// Keep track of current running thread by overriding setTimeout
|
||||
sourceWriter.append("self.old_setTimeout=self.setTimeout;").softNewLine();
|
||||
sourceWriter.append("self.setTimeout=function(f,interval){").indent().softNewLine();
|
||||
MethodReference currentThreadRef = new MethodReference(
|
||||
Thread.class, "currentThread", Thread.class);
|
||||
MethodReference setCurrentThreadRef = new MethodReference(
|
||||
Thread.class, "setCurrentThread", Thread.class, void.class);
|
||||
MethodReference getMainThreadRef = new MethodReference(Thread.class, "getMainThread", Thread.class);
|
||||
|
||||
sourceWriter.append("var currThread = ").appendMethodBody(currentThreadRef).append("();").softNewLine();
|
||||
sourceWriter.append("var callback = function(){").indent().softNewLine();
|
||||
sourceWriter.appendMethodBody(setCurrentThreadRef).append("(currThread);").softNewLine();
|
||||
sourceWriter.append("try{f();} finally {").softNewLine();
|
||||
sourceWriter.appendMethodBody(setCurrentThreadRef).append("(").
|
||||
appendMethodBody(getMainThreadRef).append("());}").softNewLine();
|
||||
sourceWriter.outdent().append("};").softNewLine();
|
||||
sourceWriter.append("self.old_setTimeout(callback, interval);").softNewLine();
|
||||
sourceWriter.outdent().append("};").softNewLine();
|
||||
|
||||
// END Thread stuff
|
||||
|
||||
renderer.renderRuntime();
|
||||
for (ClassNode clsNode : clsNodes) {
|
||||
ClassReader cls = classSet.get(clsNode.getName());
|
||||
|
|
|
@ -46,9 +46,9 @@ public final class AsyncProgram {
|
|||
}
|
||||
}
|
||||
|
||||
});
|
||||
}, "Test Thread");
|
||||
t.start();
|
||||
|
||||
System.out.println("Should be main -> Current thread is "+Thread.currentThread().getName());
|
||||
System.out.println("Now trying wait...");
|
||||
|
||||
lock.wait(20000);
|
||||
|
@ -57,12 +57,16 @@ public final class AsyncProgram {
|
|||
}
|
||||
|
||||
private static void doRun(Object lock) throws InterruptedException {
|
||||
System.out.println("Current thread is "+Thread.currentThread().getName());
|
||||
System.out.println("Executing timer task");
|
||||
Thread.sleep(2000);
|
||||
System.out.println("Current thread is "+Thread.currentThread().getName());
|
||||
System.out.println("Calling lock.notify()");
|
||||
lock.notify();
|
||||
System.out.println("Current thread is "+Thread.currentThread().getName());
|
||||
System.out.println("Finished calling lock.notify()");
|
||||
Thread.sleep(5000);
|
||||
System.out.println("Current thread is "+Thread.currentThread().getName());
|
||||
System.out.println("Finished another 5 second sleep");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user