예제 #1
0
            /// <summary>
            /// Thread method
            /// </summary>
            private void Start()
            {
                var curTid = OSApi.GetCurrentThreadId();

                var processThread = Process.GetCurrentProcess().Threads
                                    .OfType <ProcessThread>()
                                    .First(pt => pt.Id == curTid);

                processThread.IdealProcessor    = _processorId;
                processThread.ProcessorAffinity = (IntPtr)(1 << _processorId);

                var token      = _cancellationTokenSource.Token;
                var spinWait   = new SpinWait();
                var starvation = Stopwatch.StartNew();

                while (!token.IsCancellationRequested)
                {
                    if (TasksSource.TryDequeue(out var task))
                    {
                        task.Action(task.State);
                        starvation.Restart();
                        continue;
                    }

                    if (starvation.ElapsedMilliseconds > 300)
                    {
                        // If I have no work and exported to another context,
                        // return me back to home context. Next iteration will loop
                        // on home context's queue
                        if (Exported)
                        {
                            _exportRegistration.Dispose();
                            _exportRegistration = null;
                            continue;
                        }

                        // If I have no work, I can ask for work in another context
                        // If another context in my host have any work, let's take
                        // it's queue and join
                        if (_host.TryNotifyIdle(this, out var registration))
                        {
                            _exportRegistration = registration;
                        }
                        else
                        {
                            // else, go to blocking state
                            _hasJobEvent.Reset();
                            _hasJobEvent.WaitOne();
                            starvation.Restart();
                        }
                    }

                    spinWait.SpinOnce();
                }
            }
        /// <summary>
        /// SyncContext thread function
        /// </summary>
        private void Start(object obj)
        {
            SetSynchronizationContext(this);
            var tinfo  = (LocalThreadState)obj;
            var curTid = OSApi.GetCurrentThreadId();

            var processThread = Process.GetCurrentProcess().Threads.OfType <ProcessThread>().First(pt => pt.Id == curTid);

            processThread.IdealProcessor    = tinfo.ProcessorId;
            processThread.ProcessorAffinity = (IntPtr)(1 << tinfo.ProcessorId);
            tinfo.ProcessThread             = processThread;

            var token               = tinfo.CancellationTokenSource.Token;
            var spinWait            = new SpinWait();
            var starvation          = Stopwatch.StartNew();
            var invertingStarvation = Stopwatch.StartNew();

            while (!token.IsCancellationRequested)
            {
                if (_tasks.TryDequeue(out var task))
                {
                    task.Action(task.State);
                    starvation.Restart();
                }
                else
                {
                    if (starvation.ElapsedMilliseconds > 300)
                    {
                        Interlocked.Exchange(ref _hardLock, 1);
                        _event.WaitOne();
                        starvation.Restart();
                        continue;
                    }
                    spinWait.SpinOnce();
                }

                if (invertingStarvation.ElapsedMilliseconds > 5000)
                {
                    invertingStarvation.Restart();
                    Invert(tinfo);
                }
            }
        }