internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var tI = this.tI; tI.Value = this.t; // This assumes correct usage of IVar. Spin: var state = tI.State; if (state < Delayed) { goto Spin; } if (state != Interlocked.CompareExchange(ref tI.State, HasValue, state)) { goto Spin; } if (state > Running) { uK.DoHandle(ref wr, new Exception("IVar full")); } else { WaitQueue.PickReaders(ref tI.Readers, tI.Value, ref wr); Work.Do(uK, ref wr); } }
internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var tI = this.tI; Spin: var state = tI.State; if (state < Delayed) { goto Spin; } if (state != Interlocked.CompareExchange(ref tI.State, ~state, state)) { goto Spin; } if (state > Running) { goto IVarFull; } tI.Value = this.t; tI.State = HasValue; WaitQueue.PickReaders(ref tI.Readers, tI.Value, ref wr); Work.Do(uK, ref wr); return; IVarFull: tI.State = state; uK.DoHandle(ref wr, new Exception("IVar full")); }
internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var tI = this.tI; Spin: var state = tI.State; if (state < Delayed) { goto Spin; } if (state != Interlocked.CompareExchange(ref tI.State, ~state, state)) { goto Spin; } if (state > Running) { goto IVarFull; } var readers = tI.Readers; var e = this.e; tI.Readers = new Fail <T>(e); tI.State = HasExn; WaitQueue.FailReaders(readers, e, ref wr); Work.Do(uK, ref wr); return; IVarFull: uK.DoHandle(ref wr, new Exception("IVar full")); }
internal override void DoJob(ref Worker wr, Cont <T> aK) { Spin: var state = this.State; Reconsider: if (state > Running) { goto Completed; } if (state < Delayed) { goto Spin; } var check = state; state = Interlocked.CompareExchange(ref this.State, state - MakeLocked, state); if (Delayed == state) { goto Delayed; } if (state != check) { goto Reconsider; } WaitQueue.AddTaker(ref this.Readers, aK); this.State = Running; return; Delayed: var readers = this.Readers; this.Readers = null; this.State = Running; var fulfill = readers as Fulfill; fulfill.tP = this; fulfill.reader = aK; var tJ = fulfill.tJ; fulfill.tJ = null; Job.Do(tJ, ref wr, fulfill); return; Completed: if (state == HasValue) { Cont.Do(aK, ref wr, this.Value); } else { aK.DoHandle(ref wr, (this.Readers as Fail <T>).exn); } }
/// Internal implementation detail. internal override void DoJob(ref Worker wr, Cont <T> aK) { Spin: var state = this.State; if (state < Running) { goto Completed; } if (state == Locked) { goto Spin; } if (state != Interlocked.CompareExchange(ref this.State, Locked, state)) { goto Spin; } if (state == Running) { goto Running; } var job = this.Readers as Cont; var taker = new Taker <T>(); taker.Cont = aK; taker.Next = taker; this.Readers = taker; this.State = Running; job.DoWork(ref wr); return; Running: WaitQueue.AddTaker(ref this.Readers, aK); this.State = Running; return; Completed: if (state == Completed) { aK.DoCont(ref wr, this.Value); } else { aK.DoHandle(ref wr, (this.Readers as Fail).exn); } }
internal override void TryAlt(ref Worker wr, int i, Cont <T> aK, Else aE) { Spin: var state = this.State; Reconsider: if (state > Running) { goto Completed; } if (state < Delayed) { goto Spin; } var check = state; state = Interlocked.CompareExchange(ref this.State, state - MakeLocked, state); if (Delayed == state) { goto Delayed; } if (state != check) { goto Reconsider; } WaitQueue.AddTaker(ref this.Readers, i, aE.pk, aK); this.State = Running; aE.TryElse(ref wr, i + 1); return; Delayed: var readers = this.Readers; this.Readers = null; this.State = Running; var fulfill = readers as Fulfill; fulfill.reader = aK; fulfill.me = i; fulfill.pk = aE.pk; Worker.PushNew(ref wr, fulfill); aE.TryElse(ref wr, i + i); return; Completed: var pkSelf = aE.pk; TryPick: var stSelf = Pick.TryPick(pkSelf); if (stSelf > 0) { goto AlreadyPicked; } if (stSelf < 0) { goto TryPick; } Pick.SetNacks(ref wr, i, pkSelf); if (state == HasValue) { Cont.Do(aK, ref wr, this.Value); } else { aK.DoHandle(ref wr, (this.Readers as Fail <T>).exn); } AlreadyPicked: return; }
internal override void TryAlt(ref Worker wr, int i, Cont <T> aK, Else aE) { var pkSelf = aE.pk; Spin: var state = this.State; if (state > Running) { goto Completed; } if (state < Delayed) { goto Spin; } if (state != Interlocked.CompareExchange(ref this.State, ~state, state)) { goto Spin; } if (Delayed == state) { goto Delayed; } WaitQueue.AddTaker(ref this.Readers, i, pkSelf, aK); this.State = Running; aE.TryElse(ref wr, i + 1); return; Delayed: var taker = new Taker <T>(); taker.Cont = aK; taker.Me = i; taker.Pick = pkSelf; taker.Next = taker; var readers = this.Readers; this.Readers = taker; this.State = Running; var fulfill = readers as Fulfill; var tJ = fulfill.tP; fulfill.tP = this; Worker.PushNew(ref wr, new JobWork <T>(tJ, fulfill)); aE.TryElse(ref wr, i + i); return; Completed: var stSelf = Pick.TryPick(pkSelf); if (stSelf > 0) { goto AlreadyPicked; } if (stSelf < 0) { goto Completed; } Pick.SetNacks(ref wr, i, pkSelf); if (state == HasValue) { Cont.Do(aK, ref wr, this.Value); } else { aK.DoHandle(ref wr, (this.Readers as Fail <T>).exn); } AlreadyPicked: return; }
/// Internal implementation detail. internal override void TryAlt(ref Worker wr, int i, Pick pkSelf, Cont <T> aK) { Spin: var state = this.State; if (state < Running) { goto Completed; } if (state == Locked) { goto Spin; } if (state != Interlocked.CompareExchange(ref this.State, Locked, state)) { goto Spin; } if (state == Running) { goto Running; } var job = this.Readers as Cont; var taker = new Taker <T>(); taker.Me = i; taker.Pick = pkSelf; taker.Cont = aK; taker.Next = taker; this.Readers = taker; this.State = Running; Worker.Push(ref wr, job); aK.TryNext(ref wr, i + 1, pkSelf); return; Running: WaitQueue.AddTaker(ref this.Readers, i, pkSelf, aK); this.State = Running; aK.TryNext(ref wr, i + 1, pkSelf); return; Completed: var stSelf = Pick.TryPick(pkSelf); if (stSelf > 0) { goto AlreadyPicked; } if (stSelf < 0) { goto Completed; } Pick.SetNacks(ref wr, i, pkSelf); if (state == Completed) { aK.DoCont(ref wr, this.Value); } else { aK.DoHandle(ref wr, (this.Readers as Fail).exn); } AlreadyPicked: return; }