mirror of
https://github.com/ParkerTenBroeck/coroutines.git
synced 2026-06-07 05:08:51 -04:00
so many small issues all at once
This commit is contained in:
parent
21412f4670
commit
b0d6737b07
8 changed files with 167 additions and 57 deletions
|
|
@ -1,8 +1,6 @@
|
|||
import async_example.Delay;
|
||||
import async_example.Jokio;
|
||||
import generator.future.Future;
|
||||
import generator.future.Waker;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class Examples {
|
||||
// public static Gen<String, Void> parse(String str){
|
||||
|
|
@ -69,49 +67,24 @@ public class Examples {
|
|||
// return Gen.ret();
|
||||
// }
|
||||
|
||||
public static class Delay implements Future<String>{
|
||||
private final static Timer timer;
|
||||
static{
|
||||
timer = new Timer(true);
|
||||
}
|
||||
private int delay;
|
||||
private boolean ready;
|
||||
public Delay(int ms){
|
||||
if(ms<0)throw new IllegalArgumentException("Delay cannot be negative");
|
||||
delay = ms;
|
||||
}
|
||||
@Override
|
||||
public synchronized Object poll(Waker waker) {
|
||||
if(delay==0){
|
||||
ready=true;
|
||||
delay=-1;
|
||||
return null;
|
||||
}
|
||||
if(delay != -1){
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
ready = true;
|
||||
waker.wake();
|
||||
}
|
||||
}, delay);
|
||||
delay = -1;
|
||||
}
|
||||
|
||||
if(ready)return null;
|
||||
return Pending.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
public static Future<String> awaitTest2(int number){
|
||||
((Future<?>)new Delay(number)).await();
|
||||
return Future.ret(number+"ms");
|
||||
}
|
||||
|
||||
public Future<String> awaitTest(int number){
|
||||
var result = awaitTest2(number).await();
|
||||
var rt = Jokio.runtime().await();
|
||||
rt.spawn(awaitTest2(5000));
|
||||
// closing(100);
|
||||
// closing(10).await();
|
||||
return Future.ret("Result: " + result);
|
||||
}
|
||||
|
||||
public Future<String> closing(int number){
|
||||
try(var m = new Meow()){
|
||||
var result = awaitTest2(number).await();
|
||||
return Future.ret("Result: " + result);
|
||||
return Future.ret(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import async_example.Jokio;
|
||||
import generator.RT;
|
||||
import generator.future.Future;
|
||||
import generator.future.Waker;
|
||||
import generator.gen.Gen;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Main implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
RT.runWithGeneratorSupport(Main.class);
|
||||
|
|
@ -58,7 +57,7 @@ public class Main implements Runnable {
|
|||
}
|
||||
|
||||
void await(){
|
||||
System.out.println(simple_async_rt(new Examples().awaitTest(2000)));
|
||||
new Jokio().blocking(new Examples().awaitTest(2000));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
52
src/async_example/Delay.java
Normal file
52
src/async_example/Delay.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package async_example;
|
||||
|
||||
import generator.future.Future;
|
||||
import generator.future.Waker;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class Delay implements Future<String> {
|
||||
private final static Timer timer;
|
||||
private TimerTask task;
|
||||
|
||||
static {
|
||||
timer = new Timer(true);
|
||||
}
|
||||
|
||||
private int delay;
|
||||
private boolean ready;
|
||||
|
||||
public Delay(int ms) {
|
||||
if (ms < 0) throw new IllegalArgumentException("async_example.Delay cannot be negative");
|
||||
delay = ms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (task != null) task.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object poll(Waker waker) {
|
||||
if (delay == 0) {
|
||||
ready = true;
|
||||
delay = -1;
|
||||
return null;
|
||||
}
|
||||
if (delay != -1) {
|
||||
task = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
ready = true;
|
||||
waker.wake();
|
||||
}
|
||||
};
|
||||
timer.schedule(task, delay);
|
||||
delay = -1;
|
||||
}
|
||||
|
||||
if (ready) return null;
|
||||
return Pending.INSTANCE;
|
||||
}
|
||||
}
|
||||
73
src/async_example/Jokio.java
Normal file
73
src/async_example/Jokio.java
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package async_example;
|
||||
|
||||
import generator.future.Future;
|
||||
import generator.future.Waker;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Queue;
|
||||
|
||||
public class Jokio implements Runnable{
|
||||
|
||||
private class Task<T> implements Waker{
|
||||
public final Future<T> future;
|
||||
|
||||
private Task(Future<T> future) {
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wake() {
|
||||
synchronized (Jokio.this){
|
||||
woke.add(this);
|
||||
Jokio.this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public Jokio runtime(){
|
||||
return Jokio.this;
|
||||
}
|
||||
}
|
||||
|
||||
public static Future<Jokio> runtime(){
|
||||
return new Future<>() {
|
||||
@Override
|
||||
public Jokio poll(Waker waker) {
|
||||
return ((Task<?>)waker).runtime();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final HashSet<Task<?>> current = new HashSet<>();
|
||||
private final Queue<Task<?>> woke = new ArrayDeque<>();
|
||||
|
||||
public void blocking(Future<?> fut){
|
||||
spawn(fut).run();
|
||||
}
|
||||
|
||||
public synchronized Jokio spawn(Future<?> future){
|
||||
var task = new Task<>(future);
|
||||
current.add(task);
|
||||
woke.add(task);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void run(){
|
||||
while(!current.isEmpty()) {
|
||||
while(woke.isEmpty()) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
var task = woke.poll();
|
||||
var result = task.future.poll(task);
|
||||
if(result!=Future.Pending.INSTANCE) {
|
||||
current.remove(task);
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ public class GeneratorClassLoader extends ClassLoader {
|
|||
clm.findAttributes(Attributes.nestMembers()).forEach(i -> nestMem.addAll(i.nestMembers().stream().map(ClassEntry::asSymbol).toList()));
|
||||
clm.findAttributes(Attributes.innerClasses()).forEach(i -> innerCl.addAll(i.classes()));
|
||||
|
||||
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).build(clm.thisClass().asSymbol(), cb -> {
|
||||
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES, ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(clm.thisClass().asSymbol(), cb -> {
|
||||
for (var ce : clm) {
|
||||
if (ce instanceof MethodModel mem && !isGen && !isFuture) {
|
||||
StateMachineBuilder builder = null;
|
||||
|
|
@ -104,6 +104,10 @@ public class GeneratorClassLoader extends ClassLoader {
|
|||
var smb = new FutureSMBuilder(src_clm, src_mem, com);
|
||||
try{
|
||||
add(smb.CD_this.displayName(), smb.buildStateMachine());
|
||||
|
||||
cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> {
|
||||
mb.withCode(smb::buildSourceMethodShim);
|
||||
});
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> {
|
||||
|
|
@ -111,9 +115,6 @@ public class GeneratorClassLoader extends ClassLoader {
|
|||
});
|
||||
return smb;
|
||||
}
|
||||
cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> {
|
||||
mb.withCode(smb::buildSourceMethodShim);
|
||||
});
|
||||
return smb;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ public class LocalTracker {
|
|||
case ITEM_FLOAT -> CD_float;
|
||||
case ITEM_DOUBLE -> CD_double;
|
||||
case ITEM_OBJECT -> sym;
|
||||
case ITEM_NULL -> CD_Object;
|
||||
default -> throw new RuntimeException();
|
||||
};
|
||||
}
|
||||
|
|
@ -433,7 +434,7 @@ public class LocalTracker {
|
|||
|
||||
case TableSwitchInstruction ts -> popStack();
|
||||
case ThrowInstruction t -> popStack();
|
||||
case TypeCheckInstruction tc -> {}
|
||||
case TypeCheckInstruction tc -> decStack(1).pushStack(tc.type().asSymbol());
|
||||
case DiscontinuedInstruction d -> throw new IllegalStateException(d.toString());
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public abstract class StateMachineBuilder {
|
|||
if (!src_mem.flags().has(AccessFlag.STATIC)) {
|
||||
mts = mts.insertParameterTypes(0, src_clm.thisClass().asSymbol());
|
||||
}
|
||||
var name = src_clm.thisClass().name().stringValue() + "$" + src_mem.methodName().stringValue() + "$" + uniqueName();
|
||||
var name = src_clm.thisClass().asSymbol().displayName() + "$" + src_mem.methodName().stringValue() + "$" + uniqueName();
|
||||
|
||||
this.CD_this = ClassDesc.of(src_clm.thisClass().asSymbol().packageName(), name);
|
||||
this.params = mts.parameterArray();
|
||||
|
|
@ -84,7 +84,7 @@ public abstract class StateMachineBuilder {
|
|||
}
|
||||
|
||||
public byte[] buildStateMachine(){
|
||||
return ClassFile.of(ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED, ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).build(CD_this, clb -> {
|
||||
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).build(CD_this, clb -> {
|
||||
|
||||
if(shouldBeInnerClass()){
|
||||
src_clm.findAttributes(Attributes.sourceFile()).forEach(clb::with);
|
||||
|
|
@ -145,8 +145,8 @@ public abstract class StateMachineBuilder {
|
|||
handlers.add(handler.apply(this, cob));
|
||||
}
|
||||
}
|
||||
// if(handlers.isEmpty() && stateSwitchCases.isEmpty())
|
||||
// throw new RuntimeException("Not a state machine");
|
||||
if(handlers.isEmpty())
|
||||
throw new RuntimeException("Not a state machine");
|
||||
cob.aload(0).getfield(CD_this, STATE_NAME, TypeKind.INT.upperBound()).lookupswitch(invalidState, stateSwitchCases);
|
||||
var start = cob.startLabel();
|
||||
var end = cob.newLabel();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ public class FutureSMBuilder extends StateMachineBuilder {
|
|||
public final static MethodTypeDesc MTD_Object_Waker = MethodTypeDesc.of(ConstantDescs.CD_Object, CD_Waker);
|
||||
public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object);
|
||||
|
||||
public final static String AWAITING_FIELD_NAME = "awaiting";
|
||||
|
||||
static class AwaitHandler implements SpecialMethodHandler{
|
||||
final int yield_state;
|
||||
final Label yield_label;
|
||||
|
|
@ -36,18 +38,19 @@ public class FutureSMBuilder extends StateMachineBuilder {
|
|||
|
||||
@Override
|
||||
public void handle(StateMachineBuilder smb, CodeBuilder cob) {
|
||||
System.out.println("Await");
|
||||
cob.aload(0).loadConstant(yield_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound());
|
||||
var start = cob.newBoundLabel();
|
||||
cob.dup().dup()
|
||||
.aload(1)
|
||||
.invokeinterface(CD_Future, "poll", MTD_Object_Waker).dup()
|
||||
cob.dup()
|
||||
.aload(1).invokeinterface(CD_Future, "poll", MTD_Object_Waker).dup()
|
||||
.instanceOf(CD_Pending);
|
||||
cob.ifThenElse(bcb -> {
|
||||
bcb.swap().aload(0).swap().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
|
||||
smb.lt.savingLocals(smb.CD_this, bcb, () -> {
|
||||
bcb.swap().aload(0).swap().putfield(smb.CD_this, "meow", CD_Future);
|
||||
bcb.areturn().labelBinding(yield_label);
|
||||
bcb.aload(0).getfield(smb.CD_this, "meow", CD_Future);
|
||||
});
|
||||
bcb.aload(0).getfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
|
||||
bcb.aload(0).aconst_null().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
|
||||
bcb.goto_(start);
|
||||
}, bcb -> {
|
||||
bcb.swap().pop();
|
||||
|
|
@ -86,6 +89,7 @@ public class FutureSMBuilder extends StateMachineBuilder {
|
|||
|
||||
@Override
|
||||
public void handle(StateMachineBuilder smb, CodeBuilder cob) {
|
||||
System.out.println("Return");
|
||||
cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()).areturn();
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +106,14 @@ public class FutureSMBuilder extends StateMachineBuilder {
|
|||
cob.localVariable(1, "waker", CD_Waker, cob.startLabel(), cob.endLabel());
|
||||
buildStateMachineMethodCode(clb, cob, 2);
|
||||
}));
|
||||
clb.withField("meow", CD_Future, ClassFile.ACC_PRIVATE);
|
||||
clb.withMethod("cancel", MethodTypeDesc.of(ConstantDescs.CD_void), ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> {
|
||||
cob.aload(0).getfield(CD_this, AWAITING_FIELD_NAME, CD_Future).dup().ifThen(Opcode.IFNONNULL, boc -> {
|
||||
boc.invokeinterface(CD_Future, "cancel", MethodTypeDesc.of(ConstantDescs.CD_void))
|
||||
.aload(0).aconst_null().putfield(CD_this, AWAITING_FIELD_NAME, CD_Future).return_();
|
||||
});
|
||||
cob.pop().return_();
|
||||
}));
|
||||
clb.withField(AWAITING_FIELD_NAME, CD_Future, ClassFile.ACC_PRIVATE);
|
||||
}
|
||||
|
||||
public FutureSMBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue