#!/usr/bin/env perl6 module OS { my $debug = 0; sub yield(|c) is export { take c[0]; } role SystemCall { has $.data; has $.ret; multi method new(\data, \ret) { self.bless()!init-data(data)!init-ret(ret); } multi method new() { self.bless(); } method !init-data(\data) { $!data := data; self; } method !init-ret(\ret) { $!ret := ret; self; } method call($task, $scheduler) { ... } } multi sub systemcall(SystemCall:U $type, \d, \r) is export { yield $type.new(d, r); } multi sub systemcall(SystemCall:U $type, \d) is export { yield $type.new(d); } multi sub systemcall(SystemCall:U $type) is export { yield $type.new(); } class GetTid does SystemCall { multi method new(\ret) { self.bless()!init-ret(ret); } method call($task, $scheduler) { note "do system call\@{&?ROUTINE}" if $debug; $!ret = $task.id; $scheduler.scheduler($task); } } class NewTask does SystemCall { method call($task, $scheduler) { note "do system call\@{&?ROUTINE}" if $debug; $!ret = $scheduler.cue(&$!data); $scheduler.scheduler($task); } } class Task { my $taskid = 0; has $.id; has $.target; has $.send; method new(&target) { my $target = lazy gather &target(); self.bless(id => ++$taskid, target => $target.iterator, send => Nil); } method run() { return $!target.pull-one; } } class Scheduler { has @!ready; has %!task; method cue(&code) { my $task = Task.new(&code); %!task{$task.id} = $task; self.scheduler($task); return $task.id; } method scheduler(Task $task) { @!ready.push($task); } method exit(Task $task) { %!task{$task.id}:delete; } method main-loop() { while %!task { my $task = @!ready.shift; try { my $result := $task.run; note "get result from task {$task.id}: ", $result if $debug; if so try $result ~~ SystemCall { $result.call($task, self); next; } CATCH { when X::AdHoc { self.exit($task); } default { .say; } } } self.scheduler($task); } } } } import OS; sub foo() { systemcall(OS::GetTid, my $id); for 1..4 { say "I am foo, $id"; yield; } } sub bar() { systemcall(OS::NewTask, my $foo = &foo, my $id); say "CREATE FOO $id"; systemcall(OS::GetTid, my $tid); for 1..2 { say "I am bar, $tid"; yield; } } my $scheduler = OS::Scheduler.new; $scheduler.cue(&foo); $scheduler.cue(&bar); $scheduler.main-loop;