internal override void DoJob(ref Worker wr, Cont <bool> bK) { var ch = this.Ch; TryNextTaker: ch.Lock.Enter(); var tail = ch.Takers; if (null != tail) { goto TryTaker; } ch.Lock.Exit(); Cont.Do(bK, ref wr, false); return; TryTaker: var cursor = tail.Next; if (tail == cursor) { ch.Takers = null; ch.Lock.Exit(); } else { tail.Next = cursor.Next; ch.Lock.Exit(); tail = cursor as Cont <T>; } var taker = tail as Taker <T>; if (null == taker) { goto GotTaker; } var pkOther = taker.Pick; TryPickOther: var stOther = Pick.TryPick(pkOther); if (stOther > 0) { goto TryNextTaker; } if (stOther < 0) { goto TryPickOther; } Pick.SetNacks(ref wr, taker.Me, pkOther); tail = taker.Cont; GotTaker: tail.Value = this.X; Worker.Push(ref wr, tail); Cont.Do(bK, ref wr, true); return; }
internal override void DoJob(ref Worker wr, Cont <T> tK) { var tM = this.tM; Spin: var state = tM.State; if (state == MVar.Locked) { goto Spin; } if (state != Interlocked.CompareExchange(ref tM.State, MVar.Locked, state)) { goto Spin; } if (state <= MVar.Empty) { goto EmptyOrDemand; } var t = tM.Value; tM.State = MVar.Full; Cont.Do(tK, ref wr, t); return; EmptyOrDemand: WaitQueue.AddTaker(ref tM.Takers, new MVarReadCont <T>(tM, tK)); tM.State = MVar.Demand; }
internal override void DoJob(ref Worker wr, Cont <X> xK) { var work = wr.WorkStack; wr.WorkStack = null; Scheduler.PushAll(wr.Scheduler, work); Cont.Do(xK, ref wr, Do()); }
internal override void DoWork(ref Worker wr) { var value = this.tF.Invoke(null); var tK = this.tK; wr.Handler = tK; Lock.Exit(this.l, ref wr); Cont.Do(tK, ref wr, value); }
internal override void TryAlt(ref Worker wr, int i, Cont <T> tK, Else tE) { var tM = this.tM; var pkSelf = tE.pk; Spin: var state = tM.State; if (state == MVar.Locked) { goto Spin; } if (state != Interlocked.CompareExchange(ref tM.State, MVar.Locked, state)) { goto Spin; } if (state <= MVar.Empty) { goto EmptyOrDemand; } TryPick: var stSelf = Pick.TryPick(pkSelf); if (stSelf > 0) { goto AlreadyPicked; } if (stSelf < 0) { goto TryPick; } Pick.SetNacks(ref wr, i, pkSelf); var t = tM.Value; tM.State = MVar.Full; Cont.Do(tK, ref wr, t); return; AlreadyPicked: tM.State = MVar.Full; return; EmptyOrDemand: WaitQueue.AddTaker(ref tM.Takers, i, pkSelf, new MVarReadCont <T>(tM, tK)); tM.State = MVar.Demand; tE.TryElse(ref wr, i + 1); return; }
internal override void DoJob(ref Worker wr, Cont <T> tK) { var l = this.l; Spin: var state = l.State; if (state == Lock.Locked) { goto Spin; } if (state != Interlocked.CompareExchange(ref l.State, Lock.Locked, state)) { goto Spin; } if (state == Lock.Free) { goto GotIt; } var waiter = new GotIt(this.l, this.tF, tK); var tail = l.Waiters; if (tail == null) { waiter.Next = waiter; } else { waiter.Next = tail.Next; tail.Next = waiter; } l.Waiters = waiter; l.State = Lock.Held; return; GotIt: // We keep the lock in Locked stated for the duration of the function // call. This avoids doing a second interlocked operation. T value; try { value = this.tF.Invoke(null); } catch (Exception e) { tK = new FailCont <T>(tK, e); value = default(T); } l.State = Lock.Free; Cont.Do(tK, ref wr, value); }
/// internal override void DoJob(ref Worker wr, Cont <ulong> rK) { Cont.Do(rK, ref wr, Randomizer.Next(ref wr.RandomLo, ref wr.RandomHi)); }
internal override void DoJob(ref Worker wr, Cont <X> xK) { Cont.Do(xK, ref wr, Do(Randomizer.Next(ref wr.RandomLo, ref wr.RandomHi))); }
internal override void DoJob(ref Worker wr, Cont <X> xK) { Cont.Do(xK, ref wr, Do(xK.GetProc(ref wr))); }
internal override void DoJob(ref Worker wr, Cont <FSharpOption <T> > xK) { xK.Value = null; var ch = this.ch; TryNextGiver: ch.Lock.Enter(); var tail = ch.Givers; if (null != tail) { goto TryGiver; } ch.Lock.Exit(); Work.Do(xK, ref wr); return; TryGiver: var cursor = tail.Next; if (tail == cursor) { ch.Givers = null; } else { tail.Next = cursor.Next; } ch.Lock.Exit(); var giver = cursor as Giver <T>; if (null == giver) { goto GotSend; } var pkOther = giver.Pick; if (null == pkOther) { goto GotGiver; } TryPickOther: var stOther = Pick.TryPick(pkOther); if (stOther > 0) { goto TryNextGiver; } if (stOther < 0) { goto TryPickOther; } Pick.SetNacks(ref wr, giver.Me, pkOther); GotGiver: Worker.Push(ref wr, giver.Cont); GotSend: Cont.Do(xK, ref wr, FSharpOption <T> .Some(cursor.Value)); return; }
internal override void DoCont(ref Worker wr, T t) { tM.Fill(ref wr, t); Cont.Do(tK, ref wr, t); }