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 }
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); } }
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; } }
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; } }
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); }
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); } } }
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); } } }
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); } } }