/// Internal implementation detail. internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var mb = this.Mb; TryNextTaker: mb.Lock.Enter(); var tail = mb.Takers; if (null == tail) { goto NoTakers; } var cursor = tail.Next; if (tail == cursor) { mb.Takers = null; mb.Lock.Exit(); } else { tail.Next = cursor.Next; mb.Lock.Exit(); tail = cursor as Cont <T>; } var taker = cursor as Taker <T>; if (null == taker) { goto GotTaker; } var pk = taker.Pick; TryPick: var st = Pick.TryPick(pk); if (st > 0) { goto TryNextTaker; } if (st < 0) { goto TryPick; } Pick.SetNacks(ref wr, taker.Me, pk); GotTaker: tail.Value = this.X; tail.Next = null; Worker.Push(ref wr, tail); uK.DoCont(ref wr, null); return; NoTakers: mb.Values.Enqueue(this.X); mb.Lock.Exit(); uK.DoCont(ref wr, null); return; }
internal override void DoWork(ref Worker wr) { yK.DoCont(ref wr, yJ.Do(this.Value)); }
/// Internal implementation detail. internal override void TryAlt(ref Worker wr, int i, Pick pkSelf, Cont <Unit> uK) { 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; } //GotTaker: WaitQueue.ReplaceRange(ref ch.Takers, taker, cache); ch.Lock.Exit(); if (null != pkOther) { Pick.PickClaimed(pkOther); Pick.SetNacks(ref wr, me, pkOther); //taker = (taker as Taker<T>).Cont; } Pick.SetNacks(ref wr, i, pkSelf); taker.Value = this.X; taker.Next = null; Worker.Push(ref wr, taker); uK.DoCont(ref wr, null); 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(); uK.TryNext(ref wr, i + 1, pkSelf); return; SelfAlreadyPicked: if (null != pkOther) { Pick.Unclaim(pkOther); } WaitQueue.ReplaceRangeInclusive(ch.Takers, taker, cache); ch.Lock.Exit(); return; }
/// Internal implementation detail. 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; tail.Next = null; Worker.Push(ref wr, tail); uK.DoCont(ref wr, null); return; TryGiver: WaitQueue.AddGiver(ref ch.Givers, this.X, uK); ch.Lock.Exit(); return; }
/// Internal implementation detail. internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var iv = this.IV; iv.Value = this.X; // This assumes correct usage of IVar. Spin: var state = iv.State; if (state < IVar <T> .Empty) { goto Spin; } if (state != Interlocked.CompareExchange(ref iv.State, IVar <T> .HasValue, state)) { goto Spin; } if (state > IVar <T> .Empty) { goto IVarFull; } var takers = iv.Takers; if (null == takers) { goto Empty; } iv.Takers = null; int me = 0; Work cursor = takers; TryTaker: var taker = cursor as Cont <T>; cursor = cursor.Next; var pk = taker.GetPick(ref me); if (null == pk) { goto GotTaker; } TryPick: var st = Pick.TryPick(pk); if (st > 0) { goto TryNextTaker; } if (st < 0) { goto TryPick; } Pick.SetNacks(ref wr, me, pk); GotTaker: taker.Value = iv.Value; taker.Next = null; Worker.Push(ref wr, taker); TryNextTaker: if (cursor != takers) { goto TryTaker; } Empty: uK.DoCont(ref wr, null); return; IVarFull: uK.DoHandle(ref wr, new Exception("IVar full")); }
/// Internal implementation detail. internal override void DoJob(ref Worker wr, Cont <Unit> uK) { var mv = this.MV; TryNextTaker: var state = mv.State; if (state == MVar <T> .Locked) { goto TryNextTaker; } if (state != Interlocked.CompareExchange(ref mv.State, MVar <T> .Locked, state)) { goto TryNextTaker; } if (state == MVar <T> .Empty) { goto WasEmpty; } var tail = mv.Takers; if (null == tail) { goto MVarFull; } var cursor = tail.Next; if (tail == cursor) { mv.Takers = null; mv.State = MVar <T> .Empty; } else { tail.Next = cursor.Next; mv.State = MVar <T> .Demand; tail = cursor as Cont <T>; } var taker = tail as Taker <T>; if (null == taker) { goto GotTaker; } var pk = taker.Pick; TryPick: int st = Pick.TryPick(pk); if (st > 0) { goto TryNextTaker; } if (st < 0) { goto TryPick; } Pick.SetNacks(ref wr, taker.Me, pk); tail = taker.Cont; GotTaker: tail.Value = this.X; tail.Next = null; Worker.Push(ref wr, tail); uK.DoCont(ref wr, null); return; WasEmpty: mv.Value = this.X; mv.State = MVar <T> .Full; uK.DoCont(ref wr, null); return; MVarFull: uK.DoHandle(ref wr, new Exception("MVar full")); }