Пример #1
0
 private static void ReallyInit()
 {
     SpinlockTTAS.Enter(ref Scheduler.Lock);
     if (Volatile.Read(ref Events) == null)
     {
         var numWorkers = Environment.ProcessorCount;
         Waiters = -1;
         Events  = new WorkerEvent[numWorkers];
         var threads = new Thread[numWorkers];
         for (int i = 0; i < numWorkers; ++i)
         {
             Events[i] = new WorkerEvent(i);
             var index  = i;
             var thread = new Thread(() => Worker.Run(index));
             threads[i]          = thread;
             thread.IsBackground = true;
         }
         for (int i = 0; i < numWorkers; ++i)
         {
             threads[i].Start();
         }
         SpinlockTTAS.Exit(ref Scheduler.Lock);
     }
 }
Пример #2
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);
                }
            }
        }