Example #1
0
            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;
            }
Example #2
0
            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;
            }