mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Added some implementations for Object.wait(), Object.notify(), Object.notifyAll(), and Thread.start() to try to emulate the behaviour of multithreaded environments.
This commit is contained in:
parent
7c084effb0
commit
72cb3973d6
|
@ -43,6 +43,15 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
|
|||
case "clone":
|
||||
generateClone(context, writer);
|
||||
break;
|
||||
case "wait":
|
||||
generateWait(context, writer);
|
||||
break;
|
||||
case "notify":
|
||||
generateNotify(context, writer);
|
||||
break;
|
||||
case "notifyAll":
|
||||
generateNotifyAll(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +79,10 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
|
|||
case "wrap":
|
||||
method.getVariable(1).connect(method.getResult());
|
||||
break;
|
||||
//case "wait":
|
||||
// method.getVariable(0).connect(method.getResult());
|
||||
// break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,4 +120,66 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
|
|||
private void generateWrap(InjectorContext context) throws IOException {
|
||||
context.writeExpr(context.getArgument(0));
|
||||
}
|
||||
|
||||
private void generateWait(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String pname = context.getParameterName(1);
|
||||
String obj = context.getParameterName(0);
|
||||
writer.append("(function(){").indent().softNewLine();
|
||||
writer.append("var completed = false;").softNewLine();
|
||||
writer.append("var retCallback = ").append(context.getCompleteContinuation()).append(";").softNewLine();
|
||||
writer.append("console.log(retCallback);").softNewLine();
|
||||
writer.append("var callback = function(){").indent().softNewLine();
|
||||
writer.append("if (completed){return;} completed=true;").softNewLine();
|
||||
writer.append("retCallback();").softNewLine();
|
||||
writer.outdent().append("};").softNewLine();
|
||||
writer.append("if (").append(pname).append(">0){").indent().softNewLine();
|
||||
writer.append("setTimeout(callback, ").append(pname).append(");").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
addNotifyListener(context, writer, "callback");
|
||||
writer.outdent().append("})();").softNewLine();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void generateNotify(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
sendNotify(context, writer);
|
||||
}
|
||||
|
||||
private void generateNotifyAll(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
sendNotifyAll(context, writer);
|
||||
}
|
||||
|
||||
private String getNotifyListeners(GeneratorContext context){
|
||||
return context.getParameterName(0)+".__notifyListeners";
|
||||
}
|
||||
|
||||
private void addNotifyListener(GeneratorContext context, SourceWriter writer, String callback) throws IOException {
|
||||
String lArr = getNotifyListeners(context);
|
||||
writer.append(lArr).append("=").append(lArr).append("||[];").softNewLine();
|
||||
writer.append(lArr).append(".push(").append(callback).append(");").softNewLine();
|
||||
}
|
||||
|
||||
private void sendNotify(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String lArr = getNotifyListeners(context);
|
||||
writer.append("setTimeout(function(){").indent().softNewLine();
|
||||
writer.append("if (!").append(lArr).append(" || ").append(lArr).append(".length===0){return;}").softNewLine();
|
||||
writer.append("var m = ").append(lArr).append(".shift();").softNewLine();
|
||||
writer.append("console.log('Notify callback : '+m);").softNewLine();
|
||||
writer.append("m.apply(null);").softNewLine();
|
||||
writer.outdent().append("}, 0);").softNewLine();
|
||||
}
|
||||
|
||||
private void sendNotifyAll(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String obj = context.getParameterName(0);
|
||||
String lArr = getNotifyListeners(context);
|
||||
writer.append("setTimeout(function(){").indent().softNewLine();
|
||||
writer.append("if (!").append(lArr).append("){return;}").softNewLine();
|
||||
writer.append("while (").append(lArr).append(".length>0){").indent().softNewLine();
|
||||
writer.append(lArr).append(".shift().call(null);").softNewLine();
|
||||
writer.outdent().append("}");
|
||||
writer.outdent().append("}, 0);").softNewLine();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.InjectedBy;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
import org.teavm.javascript.ni.Superclass;
|
||||
import org.teavm.runtime.Async;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -62,26 +64,37 @@ public class TObject {
|
|||
@Override
|
||||
protected native Object clone() throws TCloneNotSupportedException;
|
||||
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@Rename("notify")
|
||||
public final void notify0() {
|
||||
}
|
||||
public native final void notify0();
|
||||
|
||||
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@Rename("notifyAll")
|
||||
public final void notifyAll0() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public native final void notifyAll0();
|
||||
|
||||
|
||||
@Rename("wait")
|
||||
public final void wait0(long timeout) throws TInterruptedException {
|
||||
public final void wait0(long timeout) throws TInterruptedException{
|
||||
try {
|
||||
wait(timeout, 0);
|
||||
} catch ( InterruptedException ex){
|
||||
throw new TInterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@Async
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@Rename("wait")
|
||||
public final void wait0(long timeout, int nanos) throws TInterruptedException {
|
||||
}
|
||||
public native final void wait0(long timeout, int nanos) throws TInterruptedException;
|
||||
|
||||
@Rename("wait")
|
||||
public final void wait0() throws TInterruptedException {
|
||||
try {
|
||||
wait(0l);
|
||||
} catch (InterruptedException ex) {
|
||||
throw new TInterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.runtime.Async;
|
||||
|
||||
|
@ -44,6 +45,11 @@ public class TThread extends TObject implements TRunnable {
|
|||
this.target = target;
|
||||
}
|
||||
|
||||
@PluggableDependency(ThreadNativeGenerator.class)
|
||||
@GeneratedBy(ThreadNativeGenerator.class)
|
||||
public native void start();
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (target != null) {
|
||||
|
|
|
@ -17,24 +17,45 @@ package org.teavm.classlib.java.lang;
|
|||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ThreadNativeGenerator implements Generator {
|
||||
public class ThreadNativeGenerator implements Generator, DependencyPlugin {
|
||||
|
||||
private static final MethodReference runRef = new MethodReference(Thread.class,
|
||||
"run", void.class);
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
if (methodRef.getName().equals("sleep")) {
|
||||
generateSleep(context, writer);
|
||||
} else if (methodRef.getName().equals("yield")) {
|
||||
generateYield(context, writer);
|
||||
} else if ( methodRef.getName().equals("start")){
|
||||
generateStart(context, writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "start": {
|
||||
MethodDependency performMethod = agent.linkMethod(runRef, null);
|
||||
performMethod.use();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void generateSleep(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("setTimeout(function() {").indent().softNewLine();
|
||||
writer.append(context.getCompleteContinuation()).append("();").softNewLine();
|
||||
|
@ -46,4 +67,10 @@ public class ThreadNativeGenerator implements Generator {
|
|||
writer.append(context.getCompleteContinuation()).append("();").softNewLine();
|
||||
writer.outdent().append("},").ws().append("0);").softNewLine();
|
||||
}
|
||||
|
||||
private void generateStart(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String obj = context.getParameterName(0);
|
||||
|
||||
writer.append("setTimeout(function() {").append(obj).append(".").appendMethod(runRef).append("();},0);").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.samples.async;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
|
@ -27,8 +28,44 @@ public final class AsyncProgram {
|
|||
withoutAsync();
|
||||
System.out.println();
|
||||
withAsync();
|
||||
|
||||
System.out.println();
|
||||
|
||||
|
||||
|
||||
final Object lock = new Object();
|
||||
|
||||
Thread t = new Thread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
doRun(lock);
|
||||
} catch (InterruptedException ex){
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
t.start();
|
||||
|
||||
System.out.println("Now trying wait...");
|
||||
|
||||
lock.wait(20000);
|
||||
System.out.println("Finished waiting");
|
||||
|
||||
}
|
||||
|
||||
private static void doRun(Object lock) throws InterruptedException {
|
||||
System.out.println("Executing timer task");
|
||||
Thread.sleep(2000);
|
||||
System.out.println("Calling lock.notify()");
|
||||
lock.notify();
|
||||
System.out.println("Finished calling lock.notify()");
|
||||
Thread.sleep(5000);
|
||||
System.out.println("Finished another 5 second sleep");
|
||||
}
|
||||
|
||||
private static void withoutAsync() {
|
||||
System.out.println("Start sync");
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
|
@ -54,6 +91,9 @@ public final class AsyncProgram {
|
|||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
System.out.println("2nd Thread.sleep in same method");
|
||||
Thread.sleep(1000);
|
||||
|
||||
System.out.println("Complete async");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user