mirror of
https://github.com/ParkerTenBroeck/coroutines.git
synced 2026-06-07 05:08:51 -04:00
added first iteration of cancellations in futures
This commit is contained in:
parent
6329257702
commit
baf0e86f39
4 changed files with 99 additions and 40 deletions
|
|
@ -4,6 +4,7 @@ import async_runtime.Util;
|
||||||
import generators.RT;
|
import generators.RT;
|
||||||
import future.Future;
|
import future.Future;
|
||||||
import gen.Gen;
|
import gen.Gen;
|
||||||
|
import generators.loadtime.future.Cancellation;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|
@ -12,10 +13,38 @@ public class Main implements Runnable {
|
||||||
RT.runWithGeneratorSupport(Main.class);
|
RT.runWithGeneratorSupport(Main.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Meow implements AutoCloseable{
|
||||||
|
{
|
||||||
|
System.out.println("CREATED");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
System.out.println("CLOSED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Void, RuntimeException> nya(){
|
||||||
|
try(@Cancellation("close") var nya = new Meow()){
|
||||||
|
Future.yield();
|
||||||
|
Future.yield();
|
||||||
|
int beep = 1;
|
||||||
|
Future.yield();
|
||||||
|
Future.yield();
|
||||||
|
return Future.ret(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new Jokio().blocking(AsyncExamples.meow());
|
// new Jokio().blocking();
|
||||||
new Jokio().blocking(new AsyncExamples().meow2());
|
var future = nya();
|
||||||
|
future.poll(null);
|
||||||
|
future.poll(null);
|
||||||
|
future.cancel();
|
||||||
|
// new Jokio().blocking(AsyncExamples.meow());
|
||||||
|
// new Jokio().blocking(new AsyncExamples().meow2());
|
||||||
// async_lambda(() -> {
|
// async_lambda(() -> {
|
||||||
// System.out.println("START");
|
// System.out.println("START");
|
||||||
// Delay.delay(100).await();
|
// Delay.delay(100).await();
|
||||||
|
|
@ -31,8 +60,8 @@ public class Main implements Runnable {
|
||||||
// start = end;
|
// start = end;
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
lexer();
|
// lexer();
|
||||||
await();
|
// await();
|
||||||
}
|
}
|
||||||
|
|
||||||
void async_lambda(Supplier<Future<?, ?>> lambda){
|
void async_lambda(Supplier<Future<?, ?>> lambda){
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack, int b
|
||||||
public void save_locals(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
|
public void save_locals(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
for (var entry : locals) {
|
for (var entry : locals) {
|
||||||
slot++;
|
slot++;// <-----
|
||||||
if (slot <= smb.paramSlotOff) continue;
|
if (slot <= smb.paramSlotOff) continue;
|
||||||
|
|
||||||
if(entry.tag() == FrameTracker.Type.TOP_TYPE.tag())continue;
|
if(entry.tag() == FrameTracker.Type.TOP_TYPE.tag())continue;
|
||||||
if (entry.isCategory2_2nd()) continue;
|
if (entry.isCategory2_2nd()) continue;
|
||||||
|
|
||||||
sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1);
|
sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1); //minus one cause increment before here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void save_stack(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int stack_off) {
|
public void save_stack(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int stack_off) {
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ import java.lang.classfile.CodeBuilder;
|
||||||
import java.lang.classfile.TypeKind;
|
import java.lang.classfile.TypeKind;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SavedStateTracker {
|
public class SavedStateTracker {
|
||||||
private final ArrayList<SavedState> saved = new ArrayList<>();
|
private final ArrayList<SavedState> saved = new ArrayList<>();
|
||||||
|
|
||||||
public sealed interface SavedState{
|
public sealed interface SavedState{
|
||||||
String name();
|
String name();
|
||||||
}
|
}
|
||||||
|
|
@ -52,6 +54,16 @@ public class SavedStateTracker {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LocalState load_param(int slot) {
|
||||||
|
for(var saved : saved){
|
||||||
|
if (saved instanceof LocalState(var name, var desc, int s) && s == slot) {
|
||||||
|
return (LocalState) saved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
public SavedStateTracker restore(StateMachineBuilder<?> smb, CodeBuilder cob, SavedState s){
|
public SavedStateTracker restore(StateMachineBuilder<?> smb, CodeBuilder cob, SavedState s){
|
||||||
if(!saved.remove(s))throw new IllegalStateException();
|
if(!saved.remove(s))throw new IllegalStateException();
|
||||||
switch(s){
|
switch(s){
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@ import future.Waker;
|
||||||
import generators.loadtime.*;
|
import generators.loadtime.*;
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
|
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;
|
||||||
import java.lang.classfile.constantpool.MethodRefEntry;
|
import java.lang.classfile.constantpool.MethodRefEntry;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.classfile.instruction.SwitchCase;
|
||||||
import java.lang.constant.ConstantDescs;
|
import java.lang.constant.*;
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
@ -37,7 +38,6 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
awaiting = sb.create(cob);
|
awaiting = sb.create(cob);
|
||||||
save_label = cob.newLabel();
|
save_label = cob.newLabel();
|
||||||
resume_inline = cob.newLabel();
|
resume_inline = cob.newLabel();
|
||||||
smb.yielding_state(awaiting, frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
|
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
|
||||||
|
|
@ -51,6 +51,8 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
frame.save_stack(smb, cob, sst,1);
|
frame.save_stack(smb, cob, sst,1);
|
||||||
cob.loadLocal(TypeKind.REFERENCE, 2);
|
cob.loadLocal(TypeKind.REFERENCE, 2);
|
||||||
|
|
||||||
|
|
||||||
|
smb.yielding_state(awaiting, frame, sst);
|
||||||
smb.resumable_return(cob, awaiting, TypeKind.REFERENCE);
|
smb.resumable_return(cob, awaiting, TypeKind.REFERENCE);
|
||||||
|
|
||||||
sst.restore_all(smb, cob);
|
sst.restore_all(smb, cob);
|
||||||
|
|
@ -89,8 +91,6 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
resume = sb.create(cob);
|
resume = sb.create(cob);
|
||||||
save_ret = cob.newLabel();
|
save_ret = cob.newLabel();
|
||||||
end = cob.newLabel();
|
end = cob.newLabel();
|
||||||
|
|
||||||
smb.yielding_state(resume, frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
|
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
|
||||||
|
|
@ -98,14 +98,15 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
@Override
|
@Override
|
||||||
public void build_prelude(FutureSMBuilder smb, CodeBuilder cob, Frame frame) {
|
public void build_prelude(FutureSMBuilder smb, CodeBuilder cob, Frame frame) {
|
||||||
cob.labelBinding(save_ret);
|
cob.labelBinding(save_ret);
|
||||||
var saved = frame.save(smb, cob, 2, 0);
|
var sst = frame.save(smb, cob, 2, 0);
|
||||||
|
|
||||||
resume.setState(smb, cob);
|
resume.setState(smb, cob);
|
||||||
cob.getstatic(CD_Pending, "INSTANCE", CD_Pending);
|
cob.getstatic(CD_Pending, "INSTANCE", CD_Pending);
|
||||||
|
|
||||||
|
smb.yielding_state(resume, frame, sst);
|
||||||
smb.resumable_return(cob, resume, TypeKind.REFERENCE);
|
smb.resumable_return(cob, resume, TypeKind.REFERENCE);
|
||||||
|
|
||||||
saved.restore_all(smb, cob);
|
sst.restore_all(smb, cob);
|
||||||
cob.goto_(end);
|
cob.goto_(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,31 +203,42 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void yielding_state(StateBuilder.State state, Frame frame){
|
private void yielding_state(StateBuilder.State state, Frame frame, SavedStateTracker sst){
|
||||||
if(frame.local_annotations().length==0)return;
|
if(frame.local_annotations().length==0)return;
|
||||||
cancellation_behavior.put(state.id(), cob -> {
|
|
||||||
for(var ann : frame.local_annotations()){
|
ArrayList<Consumer<CodeBuilder>> stuff = new ArrayList<>();
|
||||||
if(ann.annotation().classSymbol().descriptorString().equals(Cancellation.class.descriptorString())){
|
for(var ann : frame.local_annotations()){
|
||||||
ClassDesc owner = frame.locals()[ann.slot()].sym();
|
if(ann.annotation().classSymbol().descriptorString().equals(Cancellation.class.descriptorString())){
|
||||||
ClassDesc param = frame.locals()[ann.slot()].sym();
|
var param = sst.load_param(ann.slot()-paramSlotOff+2);
|
||||||
String name = "cancel";
|
ClassDesc owner = frame.locals()[ann.slot()].sym();
|
||||||
for(var el : ann.annotation().elements()){
|
String name = "cancel";
|
||||||
switch(el.name().stringValue()){
|
for(var el : ann.annotation().elements()){
|
||||||
case "value" -> name = fromAnnValue(el.value());
|
switch(el.name().stringValue()){
|
||||||
case "owner" -> {}
|
case "value" -> name = fromAnnValue(el.value());
|
||||||
case "param" -> {}
|
case "owner" -> {}
|
||||||
case "ret" -> {}
|
case "ret" -> {}
|
||||||
}
|
|
||||||
el.name().equalsString("value");
|
|
||||||
}
|
}
|
||||||
var mre = cob.constantPool().methodRefEntry(owner, name, MethodTypeDesc.of(ConstantDescs.CD_void));
|
el.name().equalsString("value");
|
||||||
cob.trying(tcob -> {
|
|
||||||
tcob.aconst_null()
|
|
||||||
// .aload(ann.slot())
|
|
||||||
.invokevirtual(mre);
|
|
||||||
}, cb -> cb.catchingAll(ccob -> ccob.pop()));
|
|
||||||
}
|
}
|
||||||
|
String final_name = name;
|
||||||
|
stuff.add(cob -> {
|
||||||
|
cob.trying(tcob -> {
|
||||||
|
tcob.aload(0).getfield(CD_this, param.name(), param.desc());
|
||||||
|
try{
|
||||||
|
if(FutureSMBuilder.class.getClassLoader().loadClass(owner.displayName()).isInterface()){
|
||||||
|
tcob.invokeinterface(owner, final_name, MethodTypeDesc.of(ConstantDescs.CD_void));
|
||||||
|
}else{
|
||||||
|
tcob.invokevirtual(owner, final_name, MethodTypeDesc.of(ConstantDescs.CD_void));
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}, cb -> cb.catchingAll(ccob -> ccob.pop()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
cancellation_behavior.put(state.id(), cob -> {
|
||||||
|
for(var thing : stuff) thing.accept(cob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,15 +262,21 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
.aload(0).aconst_null().putfield(CD_this, AWAITING_FIELD_NAME, CD_Future);
|
.aload(0).aconst_null().putfield(CD_this, AWAITING_FIELD_NAME, CD_Future);
|
||||||
});
|
});
|
||||||
|
|
||||||
for(var cb : cancellation_behavior.entrySet()){
|
if(!cancellation_behavior.isEmpty()){
|
||||||
var end = tcob.newLabel();
|
var states = cancellation_behavior.entrySet().stream().toList();
|
||||||
|
var cases = states.stream().map(v -> SwitchCase.of(v.getKey(), tcob.newLabel())).toList();
|
||||||
tcob.iload(1);
|
tcob.iload(1);
|
||||||
tcob.loadConstant(cb.getKey());
|
var end = tcob.newLabel();
|
||||||
tcob.if_icmpne(end);
|
tcob.tableswitch(end, cases);
|
||||||
cb.getValue().accept(tcob);
|
for(int i = 0; i < states.size(); i ++){
|
||||||
|
tcob.labelBinding(cases.get(i).target());
|
||||||
|
states.get(i).getValue().accept(tcob);
|
||||||
|
tcob.goto_(end);
|
||||||
|
}
|
||||||
tcob.labelBinding(end);
|
tcob.labelBinding(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.synchronized_exit(tcob);
|
this.synchronized_exit(tcob);
|
||||||
tcob.return_();
|
tcob.return_();
|
||||||
}, cb -> {
|
}, cb -> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue