コード例 #1
0
ファイル: Work.cs プロジェクト: SmartCloudAI/Hopac
    internal static void Do(Work work, ref Worker wr) {
#if TRAMPOLINE
      unsafe {
        if (Unsafe.GetStackPtr() < wr.StackLimit) {
          work.Next = wr.WorkStack;
          wr.WorkStack = work;
        } else {
          work.DoWork(ref wr);
        }
      }
#else
      work.DoWork(ref wr);
#endif
    }
コード例 #2
0
        internal static void RunOnThisThread(Work work)
        {
            var wr = new Worker();

            wr.Init();

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

            if (null != work)
            {
                do
                {
                    try {
                        do
                        {
                            wr.WorkStack = work.Next;
                            wr.Handler   = work;
                            work.DoWork(ref wr);
                            work = wr.WorkStack;
                        } while (null != work);
                    } catch (Exception e) {
                        work = new FailWork(wr.WorkStack, e, wr.Handler);
                    }
                } while (null != work);
            }
        }
コード例 #3
0
ファイル: WorkQueueLock.cs プロジェクト: sjkdev21/Hopac
        internal void Enter(ref Worker wr, Work work)
        {
            work.Next = null;

            var owner = Interlocked.Exchange(ref Tail, work);

            if (owner != null)
            {
                owner.Next = work;
            }
            else
            {
Release:
                work.DoWork(ref wr);
                var prev = work;
                work = Volatile.Read(ref prev.Next);
                if (null != work)
                {
                    goto Release;
                }

                if (prev == Interlocked.CompareExchange(ref Tail, null, prev))
                {
                    return;
                }

Spin:
                work = Volatile.Read(ref prev.Next);
                if (null != work)
                {
                    goto Release;
                }
                goto Spin;
            }
        }
コード例 #4
0
ファイル: WorkQueueLock.cs プロジェクト: SmartCloudAI/Hopac
    internal void Enter(ref Worker wr, Work work) {
      work.Next = null;

      var owner = Interlocked.Exchange(ref Tail, work);

      if (owner != null) {
        owner.Next = work;
      } else {
      Release:
        work.DoWork(ref wr);
        var prev = work;
        work = Volatile.Read(ref prev.Next);
        if (null != work)
          goto Release;

        if (prev == Interlocked.CompareExchange(ref Tail, null, prev))
          return;

      Spin:
        work = Volatile.Read(ref prev.Next);
        if (null != work)
          goto Release;
        goto Spin;
      }
    }
コード例 #5
0
        internal static void Do(Work work, ref Worker wr)
        {
#if TRAMPOLINE
            unsafe {
                if (Unsafe.GetStackPtr() < wr.StackLimit)
                {
                    work.Next    = wr.WorkStack;
                    wr.WorkStack = work;
                }
                else
                {
                    work.DoWork(ref wr);
                }
            }
#else
            work.DoWork(ref wr);
#endif
        }
コード例 #6
0
        internal static void RunOnThisThread(Scheduler sr, Work work)
        {
            var wr = new Worker();

            wr.Init(sr, 8000);

            Scheduler.Inc(sr);

            try {
                wr.Handler = work;
                work.DoWork(ref wr);
            } catch (Exception e) {
                wr.WorkStack = new FailWork(wr.WorkStack, e, wr.Handler);
            }

            Scheduler.PushAllAndDec(sr, wr.WorkStack);
        }
コード例 #7
0
        internal static void Run(Scheduler sr, int me)
        {
            IsWorkerThread = true;

            var wr = new Worker();

            wr.Init(sr, 16000);
            wr.RandomHi = (ulong)DateTime.UtcNow.Ticks;

            var iK = new IdleCont();

            var wdm = (1L << 32) / sr.Events.Length;

            wr.Event = sr.Events[me];

            while (null != sr)
            {
                try {
Restart:
                    Work work = wr.WorkStack;
                    if (null == work)
                    {
                        goto EnterScheduler;
                    }

WorkerLoop:
                    wr.Handler = work;
                    {
                        var next = work.Next;
                        if (null != next && null == sr.WorkStack)
                        {
                            Scheduler.PushAll(sr, next);
                            next = null;
                        }
                        wr.WorkStack = next;
                    }
                    work.DoWork(ref wr);
                    work = wr.WorkStack;
                    if (null != work)
                    {
                        goto WorkerLoop;
                    }

                    wr.Handler = null;

EnterScheduler:
                    work = sr.WorkStack;
                    if (null == work)
                    {
                        goto TryIdle;
                    }

                    Scheduler.Enter(sr);
EnteredScheduler:
                    work = sr.WorkStack;
                    if (null == work)
                    {
                        goto ExitAndTryIdle;
                    }

                    SchedulerGotSome : {
                        var last         = work;
                        int numWorkStack = sr.NumWorkStack;
                        int n            = (int)((numWorkStack - 1L) * wdm >> 32) + 1;
                        sr.NumWorkStack = numWorkStack - n;
                        n -= 1;
                        while (n > 0)
                        {
                            last = last.Next;
                            n   -= 1;
                        }
                        var next = last.Next;
                        last.Next    = null;
                        sr.WorkStack = next;
                        if (null != next)
                        {
                            Scheduler.UnsafeSignal(sr);
                        }
                        Scheduler.Exit(sr);
                        goto WorkerLoop;
                    }

ExitAndTryIdle:
                    Scheduler.Exit(sr);

TryIdle:
                    iK.Value = Timeout.Infinite;

                    var iJ = sr.IdleHandler;
                    if (null != iJ)
                    {
                        wr.Handler = iK;
                        iJ.DoJob(ref wr, iK);
                    }

                    if (0 == iK.Value)
                    {
                        goto Restart;
                    }

                    Scheduler.Enter(sr);
                    work = sr.WorkStack;
                    if (null != work)
                    {
                        goto SchedulerGotSome;
                    }

                    Scheduler.UnsafeWait(sr, iK.Value, wr.Event);
                    goto EnteredScheduler;
                } catch (KillException) {
                    Scheduler.Kill(sr);
                    Scheduler.Dec(sr);
                    sr = null;
                } catch (Exception e) {
                    wr.WorkStack = new FailWork(wr.WorkStack, e, wr.Handler);
                }
            }
        }
コード例 #8
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);
                }
            }
        }
コード例 #9
0
        internal static void Run(Scheduler sr, int me)
        {
            IsWorkerThread = true;

            var wr = new Worker();

            wr.Init(sr, 4000);

            var iK = new IdleCont();

            wr.Event = sr.Events[me];

            while (null != sr)
            {
                try {
Restart:
                    Work work = wr.WorkStack;
                    if (null == work)
                    {
                        goto EnterScheduler;
                    }

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

                    wr.Handler = null;

EnterScheduler:
                    work = sr.WorkStack;
                    if (null == work)
                    {
                        goto TryIdle;
                    }

                    Scheduler.Enter(sr);

                    work = sr.WorkStack;
                    if (null == work)
                    {
                        goto ExitAndTryIdle;
                    }

                    SchedulerGotSome : {
                        var last         = work;
                        int numWorkStack = sr.NumWorkStack - 1;
                        int n            = sr.NumWorkStack >> 2;
                        numWorkStack -= n;
                        while (n > 0)
                        {
                            last = last.Next;
                            n   -= 1;
                        }
                        var next = last.Next;
                        last.Next    = null;
                        sr.WorkStack = next;
                        if (null != next)
                        {
                            Scheduler.UnsafeSignal(sr);
                        }
                        sr.NumWorkStack = numWorkStack;
                        Scheduler.Exit(sr);
                        goto WorkerLoop;
                    }

ExitAndTryIdle:
                    Scheduler.Exit(sr);

TryIdle:
                    iK.Value = Timeout.Infinite;

                    var iJ = sr.IdleHandler;
                    if (null != iJ)
                    {
                        wr.Handler = iK;
                        iJ.DoJob(ref wr, iK);
                    }

                    if (0 == iK.Value)
                    {
                        goto Restart;
                    }

                    Scheduler.Enter(sr);
                    work = sr.WorkStack;
                    if (null != work)
                    {
                        goto SchedulerGotSome;
                    }

                    Scheduler.UnsafeWait(sr, iK.Value, wr.Event);
                    goto EnterScheduler;
                } catch (KillException) {
                    Scheduler.Kill(sr);
                    Scheduler.Dec(sr);
                    sr = null;
                } catch (Exception e) {
                    wr.WorkStack = new FailWork(wr.WorkStack, e, wr.Handler);
                }
            }
        }