Exemplo n.º 1
0
            private bool TryDequeue(WorkQueueLocals locals, out IThreadPoolWorkItem callback, out bool missedSteal)
            {
                var localQueue = locals.Queue;

                missedSteal = false;

                if ((callback = localQueue.LocalPop()) == null && // first try the local queue
                    !_queue.TryDequeue(out callback))             // then try the global queue
                {
                    // finally try to steal from another thread's local queue
                    var queues = Volatile.Read(ref _localQueues);
                    int c      = queues.Length;

                    int maxIndex = c - 1;
                    int i        = locals.Random.Next(c);
                    while (c > 0)
                    {
                        i = i < maxIndex ? i + 1 : 0;
                        var otherQueue = queues[i];
                        if (otherQueue != localQueue && otherQueue.CanSteal)
                        {
                            callback = otherQueue.TrySteal(ref missedSteal);
                            if (callback != null)
                            {
                                break;
                            }
                        }
                        c--;
                    }
                }

                return(callback != null);
            }
Exemplo n.º 2
0
            public IEnumerable <IThreadPoolWorkItem> GetConsumingEnumerable()
            {
                using (var locals = new WorkQueueLocals(ref _localQueues))
                {
                    _localQueue = locals.Queue;

                    while (true)
                    {
                        IThreadPoolWorkItem work;
                        if (TryDequeue(locals, out work, out var missedSteal))
                        {
                            yield return(work);
                        }
                        else if (IsAddingCompleted)
                        {
                            while (TryDequeue(locals, out work, out missedSteal))
                            {
                                yield return(work);
                            }

                            break;
                        }
                        else
                        {
                            if (missedSteal)
                            {
                                EnsureThreadRequested();
                            }

                            _semaphore.Wait();
                            MarkThreadRequestSatisfied();
                        }
                    }
                }
            }
Exemplo n.º 3
0
        public void Dispatch(Action <TWorkItem, CancellationToken> action, CancellationToken cancellationToken)
        {
            using var locals = new WorkQueueLocals(this);
            try
            {
                CustomWorkQueueNonGenericStore.LocalQueue = locals.Queue;

                var waitAdded = false;
                var spinWait  = new SpinWait();

                while (!cancellationToken.IsCancellationRequested)
                {
                    if (TryDequeue(locals, out var work, out var missedSteal))
                    {
                        if (!waitAdded)
                        {
                            SignalOneThread();
                        }

                        do
                        {
                            action(work, cancellationToken);
                        } while (TryDequeue(locals, out work, out missedSteal));
                    }

                    if (!waitAdded)
                    {
                        AddWaitNode(locals.WaitNode, ref spinWait);
                        waitAdded = true;
                        continue;
                    }

                    if (missedSteal)
                    {
                        spinWait.SpinOnce();
                        continue;
                    }

                    locals.Semaphore.Wait(cancellationToken);
                    spinWait.Reset();
                    waitAdded = false;
                }

                cancellationToken.ThrowIfCancellationRequested();
            }
            finally
            {
                CustomWorkQueueNonGenericStore.LocalQueue = null;
            }
        }
Exemplo n.º 4
0
        public async Task DispatchAsync(Func<TWorkItem, CancellationToken, Task> action, CancellationToken cancellationToken)
        {
            using var locals = new WorkQueueLocals(this);
            try
            {
                LocalQueue.Value = locals.Queue;

                var waitAdded = false;
                var spinWait = new SpinWait();

                while (!cancellationToken.IsCancellationRequested)
                {
                    if (TryDequeue(locals, out var work, out var missedSteal))
                    {
                        if (!waitAdded) SignalOneThread();

                        do
                        {
                            await action(work, cancellationToken);
                        } while (TryDequeue(locals, out work, out missedSteal));
                    }

                    if (!waitAdded)
                    {
                        AddWaitNode(locals.WaitNode, ref spinWait);
                        waitAdded = true;
                        continue;
                    }

                    if (missedSteal)
                    {
                        spinWait.SpinOnce();
                        continue;
                    }

                    await locals.Semaphore.WaitAsync(cancellationToken);
                    spinWait.Reset();
                    waitAdded = false;
                }

                cancellationToken.ThrowIfCancellationRequested();
            }
            finally
            {
                LocalQueue.Value = null;
            }
        }