void release(Object p) { coroutine self = find_self(this.coroutines); coroutine blocked = this.coroutines.Find(c => c.port == p); if (blocked == null) { if (self != null) { Debug.WriteLine("[" + self.id + "] skip block"); } this.skip_block.Add(p); return; } Debug.WriteLine("[" + blocked.id + "] unblock"); Debug.WriteLine("[" + self.id + "] released"); self.released = true; this.switch_context = () => { blocked.port = null; Debug.WriteLine("[" + self.id + "] switch from"); Debug.WriteLine("[" + blocked.id + "] to"); self.yield_to(blocked); }; }
public static void finish(list <coroutine> coroutines) { coroutine self = find_self(coroutines); self.finished = true; Debug.WriteLine("[" + self.id + "] finish coroutine"); }
public void block(Object p) { int skip = this.skip_block.FindIndex(o => o == p); if (skip != -1) { this.skip_block.RemoveAt(skip); return; } coroutine self = find_self(this.coroutines); self.port = p; Debug.WriteLine("[" + self.id + "] block"); create_context(); self.yield_to(this.coroutines.Last()); Debug.WriteLine("[" + self.id + "] re-entered context"); Debug.Write("routines: "); foreach (coroutine c in this.coroutines) { Debug.Write(c.id + " "); } Debug.WriteLine(""); this.coroutines.RemoveAll((c) => { if (!c.finished) { return(false); } Debug.WriteLine("[" + c.id + "] removing"); c.Dispose(); return(true); }); }
public void collateral_block() { coroutine self = find_self(this.coroutines); Debug.WriteLine("[" + self.id + "] collateral_block"); this.collateral_blocked.Add(self); this.coroutines.Remove(self); create_context(); self.yield_to(this.coroutines.Last()); Debug.WriteLine("[" + self.id + "] collateral_unblock"); }
public void collateral_release(coroutine self) { if (this.collateral_blocked.Count != 0) { finish(coroutines); } while (this.collateral_blocked.Count != 0) { this.coroutines.Add(this.collateral_blocked[0]); this.collateral_blocked.RemoveAt(0); self.yield_to(this.coroutines.Last()); } }
public void create_context() { this.coroutines.Add(new coroutine(() => { try { coroutine self = find_self(this.coroutines); Debug.WriteLine("[" + self.id + "] create context"); while ((this.running || this.queue.Count != 0) && !self.released) { worker(); if (!self.released) { collateral_release(self); } } if (self.released) { finish(this.coroutines); } if (this.switch_context != null) { Action switch_context = this.switch_context; this.switch_context = null; switch_context(); } if (!self.released) { collateral_release(self); } this.exit(); } catch (forced_unwind) { Debug.WriteLine("ignoring forced_unwind"); } catch (Exception e) { Console.Error.WriteLine("oops: " + e); System.Environment.Exit(1); } })); }
public void call(coroutine c) { this.context.call(c.context); }
public void yield_to(coroutine c) { this.yield(c.context); }
public void run() { try { this.worker = () => { context.lck(this, () => { if (this.queue.Count == 0) { Monitor.Pulse(this); } if (this.timers.Count == 0) { while (this.queue.Count == 0 && running) { Monitor.Wait(this); } } else { IEnumerator <KeyValuePair <Deadline, Action> > t = timers.OrderBy(k => k.Key).GetEnumerator(); t.MoveNext(); bool timedout = false; TimeSpan wait = t.Current.Key.t - DateTime.Now; while (!timedout && this.queue.Count == 0 && running && wait.Ticks > 0) { timedout = !Monitor.Wait(this, wait); } } Action service_timers = () => { IEnumerator <KeyValuePair <Deadline, Action> > t = timers.OrderBy(k => k.Key.t).GetEnumerator(); while (timers.Count != 0 && t.MoveNext() && t.Current.Key.expired()) { if (Monitor.IsEntered(this)) { Monitor.Exit(this); } t.Current.Value(); Monitor.Enter(this); this.timers.Remove(t.Current.Key); } }; service_timers(); if (this.queue.Count != 0) { Action f = this.queue.Dequeue(); Monitor.Exit(this); f(); service_timers(); } }); }; coroutine zero = new coroutine(); this.exit = () => { Debug.WriteLine("exit"); zero.release(); }; create_context(); context.lck(this, () => { while (this.running || this.queue.Count != 0 || this.collateral_blocked.Count != 0) { Monitor.Exit(this); Debug.Assert(this.coroutines.Count != 0); this.coroutines.Last().call(zero); Monitor.Enter(this); this.coroutines.RemoveAll((c) => { if (!c.finished) { return(false); } Debug.WriteLine("[" + c.id + "] removing"); c.Dispose(); return(true); }); } Debug.WriteLine("finish pump"); Debug.Assert(this.queue.Count == 0); }); } catch (Exception e) { Console.Error.WriteLine("oops: " + e); System.Environment.Exit(1); } }