Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Created July 21, 2019 05:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewrk/06f8f0cfd87570a6bcb7206aa95a71fd to your computer and use it in GitHub Desktop.
Save andrewrk/06f8f0cfd87570a6bcb7206aa95a71fd to your computer and use it in GitHub Desktop.
coroutine brainstorming
fn simpleAsyncFn() void {
x += 1;
suspend;
x += 1;
}
// implementation with switch
const Frame = struct {
index: u2,
};
fn simpleAsyncFn(locals: *Frame) void {
switch (locals.index) {
0 => {
locals.index += 1;
x += 1;
},
1 => {
locals.index += 1;
x += 1;
},
else => @panic("illegal coroutine resume"),
}
}
// implementation with function pointers
const Frame = struct {
next: fn (*Frame) void,
};
fn simpleAsyncFn_0(locals: *Frame) void {
locals.next = simpleAsyncFn_1;
x += 1;
}
fn simpleAsyncFn_1(locals: *Frame) void {
locals.next = simpleAsyncFn_2;
x += 1;
}
fn simpleAsyncFn_2(locals: *Frame) void {
@panic("illegal coroutine resume");
}
// implementation with switch
const Frame = struct {
index: u2,
b: bool,
};
fn jumper(locals: *Frame) void {
while (true) {
switch (locals.index) {
0 => {
locals.index += 1;
foo();
if (locals.b) {
return;
}
},
1 => {
locals.index += 1;
bar();
return;
},
else => @panic("illegal coroutine resume"),
}
}
}
// implementation with function pointers
const Frame = struct {
next: fn (*Frame) void,
b: bool,
};
fn jumper_0(locals: *Frame) void {
locals.next = jumper_1;
foo();
if (locals.b) {
return;
}
@tailCall(jumper_1, locals);
}
fn jumper_1(locals: *Frame) void {
locals.next = jumper_2;
bar();
}
fn jumper_2(locals: *Frame) void {
@panic("illegal coroutine resume");
}
fn looper(arr: []Foo) void {
for (arr) |foo| {
foo.bar();
suspend;
foo.baz();
}
}
// implementation with switch
const Frame = struct {
resume_index: u2,
arr: []Foo,
i: usize,
foo: *Foo,
};
fn looper(locals: *Frame) void {
switch (locals.resume_index) {
0 => {
if (locals.i < locals.arr.len) {
locals.foo = &locals.arr[i];
locals.foo.bar();
locals.resume_index = 1;
return;
} else {
locals.resume_index = 2;
return;
}
},
1 => {
locals.foo.baz();
locals.i += 1;
goto 0;
},
else => @panic("illegal coroutine resume"),
}
}
// implementation with function pointers
const Frame = struct {
next: fn (*Frame) void,
arr: []Foo,
i: usize,
foo: *Foo,
};
fn looper_0(locals: *Frame) void {
if (locals.i < locals.arr.len) {
locals.foo = &locals.arr[i];
locals.foo.bar();
locals.next = looper_1;
return;
} else {
locals.next = looper_2;
return;
}
}
fn looper_1(locals: *Frame) void {
locals.foo.baz();
locals.i += 1;
@tailCall(looper_0, locals);
}
fn looper_2(locals: *Frame) void {
@panic("illegal coroutine resume");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment