forked from MightyPork/crsn
coroutine fixes, first example
This commit is contained in:
@@ -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)
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user