Beispiel #1
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;
            }
        }
Beispiel #2
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;
            }
        }
Beispiel #3
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;
        }
Beispiel #4
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;
        }
Beispiel #5
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;
        }
Beispiel #6
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;
        }
Beispiel #7
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;
        }
Beispiel #8
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);
        }
Beispiel #9
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;
        }
Beispiel #10
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);
                }
            }
        }