コード例 #1
0
ファイル: Ch.cs プロジェクト: silky/Hopac
        /// Internal implementation detail.
        internal override void TryAlt(ref Worker wr, int i, Pick pkSelf, Cont <T> xK)
        {
            this.Lock.Enter();
            var tail = this.Givers;

            if (null == tail)
            {
                goto TryTaker;
            }
            Giver <T> cache  = null;
            var       cursor = tail.Next;

TryGiver:
            var giver = cursor;

            cursor = cursor.Next;
            var pkOther = giver.Pick;

            if (null == pkOther)
            {
                goto TryPickSelf;
            }
            if (pkOther == pkSelf)
            {
                goto OtherIsSelf;
            }

TryPickOther:
            var stOther = Pick.TryClaim(pkOther);

            if (stOther > 0)
            {
                goto TryNextGiver;
            }
            if (stOther < 0)
            {
                goto TryPickOther;
            }

TryPickSelf:
            var stSelf = Pick.TryPick(pkSelf);

            if (stSelf > 0)
            {
                goto SelfAlreadyPicked;
            }
            if (stSelf < 0)
            {
                goto BackOff;
            }

            //GotGiver:
            WaitQueue.ReplaceRange(ref this.Givers, giver, cache);
            this.Lock.Exit();
            if (null != pkOther)
            {
                Pick.PickClaimed(pkOther);
                Pick.SetNacks(ref wr, giver.Me, pkOther);
            }
            Pick.SetNacks(ref wr, i, pkSelf);
            var uK = giver.Cont;

            uK.Next = null;
            Worker.Push(ref wr, uK);
            xK.DoCont(ref wr, giver.Value);
            return;

BackOff:
            if (null == pkOther)
            {
                goto TryPickSelf;
            }
            Pick.Unclaim(pkOther);
            goto TryPickOther;

OtherIsSelf:
            WaitQueue.Enqueue(ref cache, giver);
            if (giver != tail)
            {
                goto TryGiver;
            }

            this.Givers = cache;
            goto TryTaker;

TryNextGiver:
            if (giver != tail)
            {
                goto TryGiver;
            }

            this.Givers = cache;
TryTaker:
            WaitQueue.AddTaker(ref this.Takers, i, pkSelf, xK);
            this.Lock.Exit();
            xK.TryNext(ref wr, i + 1, pkSelf);
            return;

SelfAlreadyPicked:
            if (null != pkOther)
            {
                Pick.Unclaim(pkOther);
            }

            WaitQueue.ReplaceRangeInclusive(this.Givers, giver, cache);
            this.Lock.Exit();
            return;
        }
コード例 #2
0
ファイル: Ch.cs プロジェクト: silky/Hopac
            /// 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;
            }