coroutine fixes, first example

coroutines
Ondřej Hruška 3 years ago
parent 8659240d01
commit c8d01b6151
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 16
      crsn/src/runtime/run_thread.rs
  2. 5
      crsn/src/runtime/run_thread/state.rs
  3. 38
      examples/coroutines1.csn

@ -91,6 +91,7 @@ impl RunThread {
loop_helper.loop_start();
}
trace!("Step {}; Status = {}", advance, self.state.cr.frame.status);
let orig_pc = self.state.cr.frame.pc;
self.state.cr.frame.pc.advance(advance);
if let Some(dl) = self.state.cr_deadline {
@ -100,14 +101,17 @@ impl RunThread {
match sched {
SchedSignal::Normal => {}
SchedSignal::Yield(None) => {
trace!("yield");
self.state.cr.cr_state = CoroutineState::Ready;
want_switch = true;
}
SchedSignal::Yield(Some(value)) => {
trace!("yield {}", value);
self.state.cr.cr_state = CoroutineState::YieldedValue(value);
want_switch = true;
}
SchedSignal::Sleep(time) => {
trace!("sleep {:?}", time);
self.state.cr.cr_state = CoroutineState::Sleep { due: Instant::now() + time };
want_switch = true;
}
@ -117,27 +121,33 @@ impl RunThread {
// TODO prioritize a thread that is waiting for this return value
}
SchedSignal::Join(handle) => {
trace!("Join cr {:#}", handle);
let mut found = false;
'find: for (n, th) in self.state.parked.iter_mut().enumerate() {
if th.handle == handle {
if let CoroutineState::Finished(_) = &th.cr_state {
let mut crs = mem::replace(&mut th.cr_state, CoroutineState::Ready);
self.state.parked.remove(n); // delete it
found = true;
if let CoroutineState::Finished(vals) = crs {
self.state.cr.frame.set_retvals(&vals);
found = true;
break 'find;
} else {
unreachable!();
}
} else {
self.state.cr.frame.pc = orig_pc; // Retry
self.state.cr.cr_state = CoroutineState::Ready;
want_switch = true;
found = true;
}
}
}
if !found {
self.state.set_flag(Flag::Invalid, true);
warn!("Join with invalid thread handle!");
warn!("Join with invalid thread handle {:#}!", handle);
self.state.cr.frame.set_retvals(&[]);
}
}
@ -214,7 +224,7 @@ impl RunThread {
let n_alive = self.state.parked.iter()
.filter(|p| p.cr_state.is_alive()).count();
if n_alive <= 1 {
if n_alive == 0 {
trace!("Stop task switching, no parked threads are alive");
self.state.cr_deadline = None;
}

@ -82,7 +82,10 @@ impl RunState {
/// Add a coroutine, marked as Ready, to run next
pub fn add_coroutine(&mut self, frame : StackFrame) -> Value {
let handle = self.thread_info.unique_handle();
self.parked.push_back(CoroutineContext {
trace!("Spawn cr {:#}", handle);
// front - so it runs ASAP
self.parked.push_front(CoroutineContext {
handle,
frame,
call_stack: vec![],

@ -0,0 +1,38 @@
(
(lds @cout "main\n")
(msleep 500)
(lds @cout "main\n")
(msleep 500)
(lds @cout "Spawnign bg\n")
(spawn r15 bg 10)
(msleep 500)
(lds @cout "FG\n")
(msleep 500)
(lds @cout "FG\n")
(msleep 500)
(lds @cout "FG\n")
(msleep 1000)
(lds @cout "Wait for BG\n")
(join @r15)
(lds @cout "Joined\n")
(msleep 500)
(lds @cout "main\n")
(msleep 500)
(lds @cout "main\n")
(msleep 500)
(proc bg times
(ld r0 times)
(:x)
(msleep 500)
(lds @cout "***BG\n")
(dec r0 (nz? (j :x)))
(lds @cout "***BG done.\n")
(ret)
)
)
Loading…
Cancel
Save