internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var ch = this.Ch; TryNextTaker: ch.Lock.Enter(); var tail = ch.Takers; if (null == tail) { goto TryGiver; } 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); Work.Do(uK, ref wr); return; TryGiver: WaitQueue.AddGiver(ref ch.Givers, this.X, uK); ch.Lock.Exit(); return; }
internal override void TryAlt(ref Worker wr, int i, Cont <Unit> uK, Else uE) { var pkSelf = uE.pk; var ch = this.Ch; ch.Lock.Enter(); var tail = ch.Takers; if (null == tail) { goto TryGiver; } Cont <T> cache = null; var cursor = tail.Next; TryTaker: var taker = cursor as Cont <T>; cursor = cursor.Next; int me = 0; var pkOther = taker.GetPick(ref me); if (null == pkOther) { goto TryPickSelf; } if (pkOther == pkSelf) { goto OtherIsSelf; } TryPickOther: var stOther = Pick.TryClaim(pkOther); if (stOther > 0) { goto TryNextTaker; } if (stOther < 0) { goto TryPickOther; } TryPickSelf: var stSelf = Pick.TryPick(pkSelf); if (stSelf > 0) { goto SelfAlreadyPicked; } if (stSelf < 0) { goto BackOff; } WaitQueue.RemoveRange(ref ch.Takers, taker); ch.Lock.Exit(); if (null != pkOther) { Pick.PickClaimedAndSetNacks(ref wr, me, pkOther); } Pick.SetNacks(ref wr, i, pkSelf); taker.Value = this.X; Worker.Push(ref wr, taker); Work.Do(uK, ref wr); return; BackOff: if (null == pkOther) { goto TryPickSelf; } Pick.Unclaim(pkOther); goto TryPickOther; OtherIsSelf: WaitQueue.Enqueue(ref cache, taker); if (taker != tail) { goto TryTaker; } ch.Takers = cache; goto TryGiver; TryNextTaker: if (taker != tail) { goto TryTaker; } ch.Takers = cache; TryGiver: WaitQueue.AddGiver(ref ch.Givers, this.X, i, pkSelf, uK); ch.Lock.Exit(); uE.TryElse(ref wr, i + 1); return; SelfAlreadyPicked: if (null != pkOther) { Pick.Unclaim(pkOther); } WaitQueue.RemoveRangeInclusive(ch.Takers, taker); ch.Lock.Exit(); return; }