/// <summary>
        /// Creates new threadpool with given settings and cancel token values
        /// </summary>
        /// <param name="settings">thread pool runtime settings</param>
        /// <param name="cancelToken">cancel token to indicate or send stop event to the pool</param>
        public CustomThreadPool3(ThreadPoolSettings settings, CancellationToken cancelToken)
            : base(settings, cancelToken)
        {
            _settings = settings;
            _linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
            this._poolStopToken = _linkedCts.Token;
            _tokenRegister = _poolStopToken.Register(OnPoolCancelRequested);

            //start minimum required threads immediately
            _mThreads = new Thread[_settings.MaxThreads];
            _mThreadLocalQueues = new ThreadLocalStealQueue<ThreadPoolWorkItem>[_settings.MaxThreads];

            for (int i = 0; i < _settings.MinThreads; i++)
            {
                StartNewThread(true);
            }

            EtwLogger.Log.PoolStarted(Name, _settings.MinThreads, _settings.MaxThreads);
        }
        private void WorkItemDispatchLoop(object threadData)
        {
            var startinfo = (WorkerThreadStartParams)threadData;
            // Register a new WSQ.
            var wsq = new ThreadLocalStealQueue<ThreadPoolWorkItem>();
            wsq.Name = startinfo.ThreadName;
            _mWsq = wsq; // Store in TLS.
            AddNewWorkQueue(wsq);

            DateTime lastItemProcesTime = DateTime.UtcNow;
            try
            {
                while (true)
                {
                    if (ShouldThreadExit(lastItemProcesTime, startinfo.IsPermenant))
                    {
                        return;
                    }

                    var wi = default(ThreadPoolWorkItem);

                    // Search order: (1) local queue, (2) global Queue, (3) steal from another thread.
                    if (!wsq.LocalPop(ref wi))
                    {

                        if (ShouldThreadExit(lastItemProcesTime, startinfo.IsPermenant))
                        {
                            return;
                        }
                        lock (_mQueue)
                        {
                            // If shutdown was requested, exit the thread.
                            if (_poolStopToken.IsCancellationRequested)
                                return;

                            // (2) try the global queue.
                            if (_mQueue.Count != 0)
                            {
                                // We found a work item! Grab it …
                                wi = _mQueue.Dequeue();
                            }
                        }

                        if (wi == null)
                        {
                            lock (_mThreadLocalQueues)
                            {

                                // (3) try to steal from neighbour thread.
                                ThreadLocalStealQueue<ThreadPoolWorkItem>[] wsQueues = _mThreadLocalQueues;
                                int i;
                                for (i = 0; i < wsQueues.Length; i++)
                                {
                                    if (wsQueues[i] != null)
                                    {
                                        if (wsQueues[i] != wsq && wsQueues[i].TrySteal(ref wi))
                                            break;
                                    }
                                }
                            }
                        }
                    }

                    try
                    {
                        //we got a work item, now try to invoke it.
                        if (wi != null)
                        {
                            wi.Execute();
                            lastItemProcesTime = DateTime.UtcNow;
                        }
                    }
                    catch (Exception ex)
                    {
                        EtwLogger.Log.WorkItemFailure(ex.ToString());
                        if (UserWorkItemException != null)
                        {
                            UserWorkItemException(this, new WorkItemEventArgs
                            {
                                Exception = ex,
                                UserData = wi.UserData,
                            });
                        }
                    }

                }
            }
            finally
            {
                OnWorkerThreadExit(startinfo.ThreadName);
            }
        }
 private void AddNewWorkQueue(ThreadLocalStealQueue<ThreadPoolWorkItem> wsq)
 {
     lock (_mThreadLocalQueues)
     {
         for (int i = 0; i < _mThreadLocalQueues.Length; i++)
         {
             if (_mThreadLocalQueues[i] == null)
             {
                 _mThreadLocalQueues[i] = wsq;
                 break;
             }
             else if (_mThreadLocalQueues[i].Name == wsq.Name)
             {
                 _mThreadLocalQueues[i] = wsq;
                 break;
             }
             else if (i == _mThreadLocalQueues.Length - 1)
             {
                 //expand the array now.
                 var queues = new ThreadLocalStealQueue<ThreadPoolWorkItem>[_mThreadLocalQueues.Length * 2];
                 Array.Copy(_mThreadLocalQueues, queues, i + 1);
                 queues[i + 1] = wsq;
                 _mThreadLocalQueues = queues;
             }
         }
     }
 }