Exemple #1
0
        internal override void DoWork(ref Worker wr)
        {
            var me = this.me;

            if (me < 0 && me == Interlocked.CompareExchange(ref this.me, 0, me))
            {
                return;
            }
            if (0 != Pick.PickAndSetNacks(pk, ref wr, me))
            {
                xJ.DoCancel(iar);
            }
            else
            {
                Cont.Do(xK, ref wr, xJ.DoEnd(iar));
            }
        }
Exemple #2
0
        internal static void PickReaders <T>(ref Cont <T> readersVar, T value, ref Worker wr)
        {
            var readers = readersVar;

            if (null == readers)
            {
                return;
            }
            readersVar = null;
            int  me     = 0;
            Work cursor = readers;

TryReader:
            var reader = cursor as Cont <T>;

            cursor = cursor.Next;
            var pk = reader.GetPick(ref me);

            if (null == pk)
            {
                goto GotReader;
            }

TryPick:
            var st = Pick.TryPick(pk);

            if (st > 0)
            {
                goto TryNextReader;
            }
            if (st < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, me, pk);
GotReader:
            reader.Value = value;
            Worker.Push(ref wr, reader);

TryNextReader:
            if (cursor != readers)
            {
                goto TryReader;
            }
        }
Exemple #3
0
        internal static int DoPickOpt(Pick pk)
        {
            var st = 0;

            if (null == pk)
            {
                goto Done;
            }
Retry:
            st = TryPick(pk);
            if (st < 0)
            {
                goto Retry;
            }
Done:
            return(st);
        }
Exemple #4
0
        internal static void AddGiver <T>(ref Send <T> queue, T x, int me, Pick pk, Cont <Unit> uK)
        {
            var       last = queue;
            Giver <T> elem;

            if (null != last)
            {
                goto MaybeReuse;
            }
            elem       = new Giver <T>();
            queue      = elem;
            elem.Next  = elem;
            elem.Value = x;
            elem.Me    = me;
            elem.Pick  = pk;
            elem.Cont  = uK;
            return;

MaybeReuse:
            elem = last as Giver <T>;
            if (null == elem)
            {
                goto New;
            }
            var pkGiver = elem.Pick;

            if (null != pkGiver && pkGiver.State > 0)
            {
                goto Init;
            }
New:
            elem      = new Giver <T>();
            queue     = elem;
            elem.Next = last.Next;
            last.Next = elem;

Init:
            elem.Value = x;
            elem.Me    = me;
            elem.Pick  = pk;
            elem.Cont  = uK;

            CleanGivers(elem);
        }
Exemple #5
0
        internal static void FailReaders <T>(Cont <T> readers, Exception e, ref Worker wr)
        {
            if (null == readers)
            {
                return;
            }
            Work cursor = readers;

TryReader:
            var reader = cursor as Cont <T>;

            cursor = cursor.Next;
            int me = 0;
            var pk = reader.GetPick(ref me);

            if (null == pk)
            {
                goto GotReader;
            }

TryPick:
            var st = Pick.TryPick(pk);

            if (st > 0)
            {
                goto TryNextReader;
            }
            if (st < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, me, pk);

GotReader:
            Worker.PushNew(ref wr, new FailWork(e, reader));

TryNextReader:
            if (cursor != readers)
            {
                goto TryReader;
            }
        }
Exemple #6
0
        internal override void TryAlt(ref Worker wr, int i, Cont <Unit> uK, Else uE)
        {
            var pkSelf = uE.pk;

Spin:
            var state = this.State;

            if (state > Initial)
            {
                goto TryPick;
            }
            if (state < Initial)
            {
                goto Spin;
            }
            if (Initial != Interlocked.CompareExchange(ref this.State, ~state, state))
            {
                goto Spin;
            }

            WaitQueue.AddTaker(ref this.Takers, i, pkSelf, uK);
            this.State = Initial;
            uE.TryElse(ref wr, i + 1);
            return;

TryPick:
            var st = Pick.TryPick(pkSelf);

            if (st > 0)
            {
                goto AlreadyPicked;
            }
            if (st < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, i, pkSelf);

            Work.Do(uK, ref wr);
AlreadyPicked:
            return;
        }
Exemple #7
0
        internal static int PickAndSetNacks(Pick pk, ref Worker wr, int i)
        {
TryPick:
            var state = Pick.TryPick(pk);

            if (state > 0)
            {
                goto AlreadyPicked;
            }
            if (state < 0)
            {
                goto TryPick;
            }

            SetNacks(ref wr, i, pk);

AlreadyPicked:
            return(state);
        }
Exemple #8
0
        internal static void AddTaker <T>(ref Cont <T> queue, int me, Pick pk, Cont <T> xK)
        {
            var       last = queue;
            Taker <T> elem;

            if (null != last)
            {
                goto MaybeReuse;
            }
            elem      = new Taker <T>();
            queue     = elem;
            elem.Next = elem;
            elem.Me   = me;
            elem.Pick = pk;
            elem.Cont = xK;
            return;

MaybeReuse:
            elem = last as Taker <T>;
            if (null == elem)
            {
                goto New;
            }
            var pkTaker = elem.Pick;

            if (/*null != pkTaker &&*/ pkTaker.State > 0)
            {
                goto Init;
            }
New:
            elem      = new Taker <T>();
            queue     = elem;
            elem.Next = last.Next;
            last.Next = elem;

Init:
            elem.Me   = me;
            elem.Pick = pk;
            elem.Cont = xK;

            CleanTakers(elem);
        }
Exemple #9
0
        /// <summary>Internal implementation detail.</summary>
        internal override void TryAlt(ref Worker wr, int i, Pick pkSelf, Cont <Unit> uK)
        {
Spin:
            var state = this.State;

            if (state > Initial)
            {
                goto TryPick;
            }
            if (state < Initial)
            {
                goto Spin;
            }
            if (Initial != Interlocked.CompareExchange(ref this.State, Locked, Initial))
            {
                goto Spin;
            }

            WaitQueue.AddTaker(ref this.Takers, i, pkSelf, uK);
            this.State = Initial;
            uK.TryNext(ref wr, i + 1, pkSelf);
            return;

TryPick:
            var st = Pick.TryPick(pkSelf);

            if (st > 0)
            {
                goto AlreadyPicked;
            }
            if (st < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, i, pkSelf);

            uK.DoCont(ref wr, null);
AlreadyPicked:
            return;
        }
Exemple #10
0
        /// Internal implementation detail.
        internal override void TryAlt(ref Worker wr, int i, Pick pkSelf, Cont <T> aK)
        {
TryPick:
            var stSelf = Pick.TryPick(pkSelf);

            if (stSelf > 0)
            {
                goto AlreadyPicked;
            }
            if (stSelf < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, i, pkSelf);

            aK.DoCont(ref wr, this.value);

AlreadyPicked:
            return;
        }
Exemple #11
0
        internal override void TryAlt(ref Worker wr, int i, Cont <Unit> uK, Else uE)
        {
            var pkSelf = uE.pk;

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

            if (stSelf > 0)
            {
                goto AlreadyPicked;
            }
            if (stSelf < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, i, pkSelf);

            Work.Do(uK, ref wr);

AlreadyPicked:
            return;
        }
Exemple #12
0
        internal override void TryAlt(ref Worker wr, int i, Cont <T> xK, Else xE)
        {
            var pkSelf = xE.pk;

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

            if (stSelf > 0)
            {
                goto AlreadyPicked;
            }
            if (stSelf < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, i, pkSelf);

            Cont.Do(xK, ref wr, this.value);

AlreadyPicked:
            return;
        }
Exemple #13
0
        public static Nack AddNack(Pick pk, int i0)
        {
TryClaim:
            var st = TryClaim(pk);

            if (st > 0)
            {
                goto AlreadyPicked;
            }
            if (st < 0)
            {
                goto TryClaim;
            }

            var nk = new Nack(pk.Nacks, i0);

            pk.Nacks = nk;

            Unclaim(pk);
            return(nk);

AlreadyPicked:
            return(null);
        }
Exemple #14
0
 internal static void Unclaim(Pick pk)
 {
     pk.State = Available;
 }
Exemple #15
0
        internal static void Signal(ref Worker wr, Nack nk)
        {
Spin:
            var state = nk.State;

            if (state > Initial)
            {
                goto JustExit;            // XXX Can this happen?
            }
            if (state < Initial)
            {
                goto Spin;
            }
            if (Initial != Interlocked.CompareExchange(ref nk.State, state + 1, state))
            {
                goto Spin;
            }

            var takers = nk.Takers;

            if (null == takers)
            {
                goto JustExit;
            }
            nk.Takers = null;
            var  me     = 0;
            Work cursor = takers;

TryTaker:
            var taker = cursor as Cont <Unit>;

            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:
            Worker.Push(ref wr, taker);
TryNextTaker:
            if (cursor != takers)
            {
                goto TryTaker;
            }
JustExit:
            return;
        }
Exemple #16
0
 internal static int TryPick(Pick pk)
 {
     return(Interlocked.CompareExchange(ref pk.State, Picked, Available));
 }
Exemple #17
0
        internal static void Run(int me)
        {
            var wr = new Worker();

            wr.Init();

            //Func<Worker> box = () => wr;

            var  mine = Scheduler.Events[me];
            Work work = null;

            while (true)
            {
                try {
                    goto Begin;

WorkerLoop:
                    wr.WorkStack = work.Next;
Do:
                    wr.Handler = work;
                    work.DoWork(ref wr);
                    work = wr.WorkStack;
Begin:
                    if (null != work)
                    {
                        goto WorkerLoop;
                    }

EnterScheduler:
                    SpinlockTTAS.Enter(ref Scheduler.Lock);
TryScheduler:
                    work = Scheduler.WorkStack;
                    if (null == work)
                    {
                        goto TryTimed;
                    }

                    {
                        var next = work.Next;
                        Scheduler.WorkStack = next;
                        if (null == next)
                        {
                            goto NoWake;
                        }
                        var waiter = Scheduler.Waiters;
                        if (0 <= waiter)
                        {
                            Scheduler.Events[waiter].Set();
                        }
                    }
NoWake:
                    SpinlockTTAS.Exit(ref Scheduler.Lock);
                    goto Do;

TryTimed:
                    var waitTicks = Timeout.Infinite;
                    {
                        var tt = Scheduler.TopTimed;
                        if (null == tt)
                        {
                            goto JustWait;
                        }

                        waitTicks = tt.Ticks - Environment.TickCount;
                        if (waitTicks > 0)
                        {
                            goto JustWait;
                        }

                        Scheduler.DropTimed();
                        SpinlockTTAS.Exit(ref Scheduler.Lock);

                        var pk = tt.Pick;
                        if (null == pk)
                        {
                            goto GotIt;
                        }
TryPick:
                        var st = Pick.TryPick(pk);
                        if (st > 0)
                        {
                            goto EnterScheduler;
                        }
                        if (st < 0)
                        {
                            goto TryPick;
                        }

                        Pick.SetNacks(ref wr, tt.Me, pk);

GotIt:
                        work = tt;
                        goto Do;
                    }
JustWait:
                    var n = Scheduler.Waiters;
                    if (n < 0)
                    {
                        mine.Next         = -1;
                        Scheduler.Waiters = me;
                    }
                    else
                    {
                        WorkerEvent other = Scheduler.Events[n];
                        mine.Next  = other.Next;
                        other.Next = me;
                    }

                    mine.Reset();
                    SpinlockTTAS.Exit(ref Scheduler.Lock);
                    mine.Wait(waitTicks);
                    SpinlockTTAS.Enter(ref Scheduler.Lock);

                    if (Scheduler.Waiters == me)
                    {
                        Scheduler.Waiters = mine.Next;
                    }
                    else
                    {
                        WorkerEvent ev = Scheduler.Events[Scheduler.Waiters];
                        if (ev.Next != me)
                        {
                            do
                            {
                                ev = Scheduler.Events[ev.Next];
                            } while (ev.Next != me);
                        }
                        ev.Next = mine.Next;
                    }

                    goto TryScheduler;
                } catch (Exception e) {
                    work = new FailWork(wr.WorkStack, e, wr.Handler);
                }
            }
        }
Exemple #18
0
 internal Else Init(Pick pk, S1 s1)
 {
     this.pk = pk; this.State1 = s1; return(this);
 }
Exemple #19
0
 internal Else Init(Pick pk)
 {
     this.pk = pk; return(this);
 }
Exemple #20
0
 internal AltCallback(Scheduler sr, FromBeginEnd <X> xJ, Cont <X> xK, Pick pk, int me) : base(sr, xJ, xK)
 {
     this.pk = pk;
     this.me = me;
 }
Exemple #21
0
 internal Else_State(Pick pk, S s) : base(pk)
 {
     State = s;
 }
Exemple #22
0
 internal WorkTimed(int ticks, int me, Pick pk)
 {
     this.Ticks = ticks;
     this.Me    = me;
     this.Pick  = pk;
 }
Exemple #23
0
 internal static void PickClaimed(Pick pk)
 {
     pk.State = 1;
 }
Exemple #24
0
 internal static void Unclaim(Pick pk)
 {
     pk.State = 0;
 }
Exemple #25
0
 internal static int TryPick(Pick pk)
 {
     return(Interlocked.CompareExchange(ref pk.State, 1, 0));
 }
Exemple #26
0
        internal override void DoJob(ref Worker wr, Cont <int> iK)
        {
TryNextTimed:
            var waitTicks = Timeout.Infinite;
            var tt = this.TopTimed;

            if (null == tt)
            {
                goto Return;
            }

            var tickCount = Environment.TickCount;

            waitTicks = tt.Ticks - tickCount;
            if (waitTicks > 0)
            {
                goto Return;
            }

            this.Lock.Enter();
            tt = this.TopTimed;
            if (null == tt)
            {
                goto ExitAndReturnWithInfinite;
            }

            waitTicks = tt.Ticks - tickCount;
            if (waitTicks > 0)
            {
                goto ExitAndReturn;
            }

            DropTimed();
            this.Lock.Exit();

            var pk = tt.Pick;

            if (null == pk)
            {
                goto GotIt;
            }

TryPick:
            var st = Pick.TryPick(pk);

            if (st > 0)
            {
                goto TryNextTimed;
            }
            if (st < 0)
            {
                goto TryPick;
            }

            Pick.SetNacks(ref wr, tt.Me, pk);

GotIt:
            Worker.Push(ref wr, tt);
            iK.DoCont(ref wr, 0);
            return;

ExitAndReturnWithInfinite:
            waitTicks = Timeout.Infinite;
ExitAndReturn:
            this.Lock.Exit();
Return:
            iK.DoCont(ref wr, waitTicks);
        }
Exemple #27
0
 internal static void PickClaimedAndSetNacks(ref Worker wr, int i, Pick pk)
 {
     pk.State = 1;
     SetNacks(ref wr, i, pk);
 }
Exemple #28
0
 internal Else(Pick pk)
 {
     this.pk = pk;
 }
Exemple #29
0
 internal WorkTimed(int ticks, int me, Pick pk)
 {
     this.Ticks = ((long)ticks) << 32;
     this.Me    = me;
     this.Pick  = pk;
 }