Ejemplo n.º 1
0
            /// 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;
            }
Ejemplo n.º 2
0
 internal override void DoWork(ref Worker wr)
 {
     yK.DoCont(ref wr, yJ.Do(this.Value));
 }
Ejemplo n.º 3
0
Archivo: Ch.cs Proyecto: 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;
            }
Ejemplo n.º 4
0
Archivo: Ch.cs Proyecto: silky/Hopac
            /// 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;
            }
Ejemplo n.º 5
0
Archivo: IVar.cs Proyecto: silky/Hopac
            /// 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"));
            }
Ejemplo n.º 6
0
Archivo: MVar.cs Proyecto: silky/Hopac
            /// 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"));
            }