コード例 #1
0
ファイル: ThreadPool.cs プロジェクト: Beefr/xenko-wd
        public void QueueWorkItem([NotNull][Pooled] Action workItem)
        {
            var lockTaken = false;

            try
            {
                spinLock.Enter(ref lockTaken);

                PooledDelegateHelper.AddReference(workItem);
                workItems.Enqueue(workItem);
                workAvailable.Set();

                var curWorkingCount = Interlocked.CompareExchange(ref workingCount, 0, 0);
                if (curWorkingCount + 1 >= aliveCount && aliveCount < maxThreadCount)
                {
                    aliveCount++;
                    Task.Factory.StartNew(ProcessWorkItems, TaskCreationOptions.LongRunning);
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinLock.Exit(true);
                }
            }
        }
コード例 #2
0
ファイル: ThreadPool.cs プロジェクト: whztt07/xenko-1
        public void QueueWorkItem([NotNull][Pooled] Action workItem)
        {
            var lockTaken = false;

            try
            {
                spinLock.Enter(ref lockTaken);

                PooledDelegateHelper.AddReference(workItem);
                workItems.Enqueue(workItem);

                if (activeThreadCount + 1 >= workers.Count && workers.Count < maxThreadCount)
                {
                    var worker = Task.Factory.StartNew(ProcessWorkItems, workers.Count, TaskCreationOptions.LongRunning);
                    workers.Add(worker);
                    //Console.WriteLine($"Thread {workers.Count} added");
                }

                workAvailable.Set();
            }
            finally
            {
                if (lockTaken)
                {
                    spinLock.Exit(true);
                }
            }
        }
コード例 #3
0
        public void QueueWorkItem([NotNull][Pooled] Action workItem)
        {
            PooledDelegateHelper.AddReference(workItem);
            bool lockTaken    = false;
            bool startNewTask = false;

            try
            {
                spinLock.Enter(ref lockTaken);

                workItems.Enqueue(workItem);
                workAvailable.Set();

                var curWorkingCount = Interlocked.CompareExchange(ref workingCount, 0, 0);
                if (curWorkingCount + 1 >= aliveCount && aliveCount < maxThreadCount)
                {
                    startNewTask = true;
                    aliveCount++;
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinLock.Exit(true);
                }
            }
            // No point in wasting spins on the lock while creating the task
            if (startNewTask)
            {
                new Task(cachedTaskLoop, null, TaskCreationOptions.LongRunning).Start();
            }
        }
コード例 #4
0
ファイル: ThreadPool.cs プロジェクト: Beefr/xenko-wd
        private void ProcessWorkItems(object state)
        {
            long     lastWork    = Stopwatch.GetTimestamp();
            TimeSpan maxIdleTime = TimeSpan.FromTicks(MaxIdleTimeInTicks);

            while (true)
            {
                Action workItem       = null;
                var    lockTaken      = false;
                bool   idleForTooLong = Utilities.ConvertRawToTimestamp(Stopwatch.GetTimestamp() - lastWork) < maxIdleTime;
                try
                {
                    spinLock.Enter(ref lockTaken);

                    if (workItems.Count > 0)
                    {
                        workItem = workItems.Dequeue();
                        if (workItems.Count == 0)
                        {
                            workAvailable.Reset();
                        }
                    }
                    else if (idleForTooLong)
                    {
                        aliveCount--;
                        return;
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        spinLock.Exit(true);
                    }
                }

                if (workItem != null)
                {
                    Interlocked.Increment(ref workingCount);
                    try
                    {
                        workItem.Invoke();
                    }
                    catch (Exception)
                    {
                        // Ignoring Exception
                    }
                    Interlocked.Decrement(ref workingCount);
                    PooledDelegateHelper.Release(workItem);
                    lastWork = Stopwatch.GetTimestamp();
                }

                // Wait for another work item to be (potentially) available
                workAvailable.WaitOne(maxIdleTime);
            }
        }
コード例 #5
0
ファイル: ThreadPool.cs プロジェクト: visperc/xenko
        public void QueueWorkItem([NotNull, Pooled] Action workItem)
        {
            // Throw right here to help debugging
            if (workItem == null)
            {
                throw new NullReferenceException(nameof(workItem));
            }

            PooledDelegateHelper.AddReference(workItem);

            LinkedWork newSharedNode = null;

            while (true)
            {
                // Are all threads busy ?
                LinkedIdleThread node = idleThreads;
                if (node == null)
                {
                    if (newSharedNode == null)
                    {
                        newSharedNode = new LinkedWork(workItem);
                        if (idleThreads != null)
                        {
                            continue;
                        }
                    }

                    // Schedule it on the shared stack
                    newSharedNode.Previous        = Interlocked.Exchange(ref sharedWorkStack, newSharedNode);
                    newSharedNode.PreviousIsValid = true;
                    break;
                }
                // Schedule this work item on latest idle thread

                while (node.PreviousIsValid == false)
                {
                    // Spin while invalid, should be extremely short
                }

                // Try take this thread
                if (Interlocked.CompareExchange(ref idleThreads, node.Previous, node) != node)
                {
                    continue;                     // Latest idle threads changed, try again
                }
                // Wakeup thread and schedule work
                // The order those two lines are laid out in is essential !
                Interlocked.Exchange(ref node.Work, workItem);
                node.MRE.Set();
                break;
            }
        }
コード例 #6
0
        private void ProcessWorkItems()
        {
            while (true)
            {
                Action workItem  = null;
                var    lockTaken = false;
                try
                {
                    spinLock.Enter(ref lockTaken);
                    int workItemCount = workItems.Count;

                    if (workItemCount > 0)
                    {
                        workItem = workItems.Dequeue();
                        if (workItemCount == 1)
                        {
                            workAvailable.Reset();                     // we must have taken off our last item
                        }
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        spinLock.Exit(true);
                    }
                }

                if (workItem != null)
                {
                    Interlocked.Increment(ref workingCount);
                    try
                    {
                        workItem.Invoke();
                    }
                    catch (Exception)
                    {
                        // Ignoring Exception
                    }
                    Interlocked.Decrement(ref workingCount);
                    PooledDelegateHelper.Release(workItem);
                }

                // Wait for another work item to be (potentially) available
                if (workAvailable.WaitOne(maxIdleTime) == false)
                {
                    aliveCount--;
                    return;
                }
            }
        }
コード例 #7
0
        private void ProcessWorkItems()
        {
            while (true)
            {
                Action workItem  = null;
                var    lockTaken = false;
                int    workItemCount;
                try
                {
                    spinLock.Enter(ref lockTaken);
                    workItemCount = workItems.Count;

                    if (workItemCount > 0)
                    {
                        workItem = workItems.Dequeue();
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        spinLock.Exit(true);
                    }
                }

                // do we have a job to do?
                if (workItem != null)
                {
                    try
                    {
                        workItem.Invoke();
                    }
                    catch (Exception)
                    {
                        // Ignoring Exception
                    }
                    PooledDelegateHelper.Release(workItem);
                }

                // only reset and wait if we took our last job
                if (workItemCount <= 1)
                {
                    workAvailable.WaitOne();
                }
            }
        }
コード例 #8
0
        private void ProcessWorkItems()
        {
            while (true)
            {
                Action workItem  = null;
                var    lockTaken = false;
                try
                {
                    spinLock.Enter(ref lockTaken);

                    if (workItems.Count > 0)
                    {
                        workItem = workItems.Dequeue();
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        spinLock.Exit(true);
                    }
                }

                // do we have a job to do?
                if (workItem != null)
                {
                    try
                    {
                        workItem.Invoke();
                    }
                    catch (Exception)
                    {
                        // Ignoring Exception
                    }
                    PooledDelegateHelper.Release(workItem);
                }
                // couldn't find work, wait until some more is available
                else
                {
                    workAvailable.WaitOne();
                }
            }
        }
コード例 #9
0
        public void QueueWorkItem([NotNull][Pooled] Action workItem)
        {
            PooledDelegateHelper.AddReference(workItem);
            bool lockTaken = false;

            try
            {
                spinLock.Enter(ref lockTaken);
                workItems.Enqueue(workItem);
            }
            finally
            {
                if (lockTaken)
                {
                    spinLock.Exit(true);
                }
            }

            workAvailable.Set();
        }
コード例 #10
0
        public void QueueWorkItem([NotNull][Pooled] Action workItem)
        {
            bool lockTaken    = false;
            bool startNewTask = false;

            PooledDelegateHelper.AddReference(workItem);
            try
            {
                spinLock.Enter(ref lockTaken);
                workItems.Enqueue(workItem);
                workAvailable.Set();

                // We're only locking when potentially increasing aliveCount as we
                // don't want to go above our maximum amount of threads.
                int curBusyCount  = Interlocked.CompareExchange(ref busyCount, 0, 0);
                int curAliveCount = Interlocked.CompareExchange(ref aliveCount, 0, 0);
                if (curBusyCount + 1 >= curAliveCount && curAliveCount < maxThreadCount)
                {
                    // Start threads as busy otherwise only one thread will be created
                    // when calling this function multiple times in a row
                    Interlocked.Increment(ref busyCount);
                    Interlocked.Increment(ref aliveCount);
                    startNewTask = true;
                }
            }
            finally
            {
                if (lockTaken)
                {
                    spinLock.Exit(true);
                }
            }
            // No point in wasting spins on the lock while creating the task
            if (startNewTask)
            {
                new Task(cachedTaskLoop, null, TaskCreationOptions.LongRunning).Start();
            }
        }
コード例 #11
0
        public void QueueWorkItem([NotNull, Pooled] Action workItem, int amount = 1)
        {
            // Throw right here to help debugging
            if (workItem == null)
            {
                throw new NullReferenceException(nameof(workItem));
            }

            if (amount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(amount));
            }

            Interlocked.Add(ref itemCount, amount);

            for (int i = 0; i < amount; i++)
            {
                PooledDelegateHelper.AddReference(workItem);
                queue.Enqueue(workItem);
            }

            if (Volatile.Read(ref idleCount) == 0)
            {
                return;
            }

            lock (lockObj)
            {
                if (Volatile.Read(ref idleCount) == 0)
                {
                    return;
                }

                Monitor.Pulse(lockObj);
            }
        }
コード例 #12
0
        private void ProcessWorkItems()
        {
            Interlocked.Decrement(ref busyCount);
            try
            {
                long lastWorkTS = Stopwatch.GetTimestamp();
                while (true)
                {
                    Action workItem  = null;
                    bool   lockTaken = false;
                    try
                    {
                        spinLock.Enter(ref lockTaken);
                        if (workItems.Count > 0)
                        {
                            workItem = workItems.Dequeue();
                            if (workItems.Count == 0)
                            {
                                workAvailable.Reset();
                            }
                        }
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            spinLock.Exit(true);
                        }
                    }

                    if (workItem == null)
                    {
                        bool idleForTooLong = Stopwatch.GetTimestamp() - lastWorkTS > MaxIdleTimeTS;
                        // Wait for another work item to be (potentially) available
                        if (idleForTooLong || workAvailable.WaitOne(MaxIdleTimeInMS) == false)
                        {
                            // No work given in the last MaxIdleTimeTS, close this task
                            return;
                        }
                    }
                    else
                    {
                        Interlocked.Increment(ref busyCount);
                        try
                        {
                            workItem();
                        }
                        // Let exceptions fall into unhandled as we don't have any
                        // good mechanisms to pass it elegantly over to user-land yet
                        finally
                        {
                            Interlocked.Decrement(ref busyCount);
                        }
                        PooledDelegateHelper.Release(workItem);
                        lastWorkTS = Stopwatch.GetTimestamp();
                    }
                }
            }
            finally
            {
                Interlocked.Decrement(ref aliveCount);
            }
        }
コード例 #13
0
ファイル: ThreadPool.cs プロジェクト: whztt07/xenko-1
        private void ProcessWorkItems(object state)
        {
            //var spinWait = new SpinWait();

            while (true)
            {
                Action workItem = null;

                //while (!spinWait.NextSpinWillYield)
                {
                    var lockTaken = false;
                    try
                    {
                        spinLock.Enter(ref lockTaken);

                        if (workItems.Count > 0)
                        {
                            try
                            {
                                workItem = workItems.Dequeue();
                                //Interlocked.Increment(ref activeThreadCount);

                                if (workItems.Count == 0)
                                {
                                    workAvailable.Reset();
                                }
                            }
                            catch
                            {
                            }
                        }

                        //if (workItems.Count > 0)
                        //{
                        //    // If we didn't consume the last work item, kick off another worker
                        //    workAvailable.Set();
                        //}
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            spinLock.Exit(true);
                        }
                    }

                    if (workItem != null)
                    {
                        try
                        {
                            Interlocked.Increment(ref activeThreadCount);
                            workItem.Invoke();

                            //spinWait.Reset();
                        }
                        catch (Exception)
                        {
                            // Ignoring Exception
                        }
                        finally
                        {
                            PooledDelegateHelper.Release(workItem);
                            Interlocked.Decrement(ref activeThreadCount);
                        }
                    }
                    else
                    {
                        //spinWait.SpinOnce();
                    }
                }

                // Wait for another work item to be (potentially) available
                workAvailable.WaitOne();
            }
        }
コード例 #14
0
ファイル: ThreadPool.cs プロジェクト: visperc/xenko
        private void ProcessWorkItems(object nodeObj)
        {
            // nodeObj is non-null when a thread caught an exception and had to throw,
            // the thread created another one and passed its node obj to us.
            LinkedIdleThread node = nodeObj == null ? new LinkedIdleThread(new ManualResetEventSlim(true)) : (LinkedIdleThread)nodeObj;

            try
            {
                while (true)
                {
                    Action     action;
                    LinkedWork workNode = sharedWorkStack;
                    if (workNode != null)
                    {
                        if (TryTakeFromSharedNonBlocking(out var tempAction, workNode))
                        {
                            action = tempAction;
                        }
                        else
                        {
                            // We have shared work to do but failed to retrieve it, try again
                            continue;
                        }
                    }
                    else
                    {
                        // Should we notify system that this thread is ready to work?
                        // This has to also work for when a thread takes the place of another one when restoring
                        // from an exception for example.
                        // If the mre was set and we took the work, this node definitely is dequeued, re-queue it
                        if (node.MRE.IsSet && Volatile.Read(ref node.Work) == null)
                        {
                            // Notify that we're waiting for work
                            node.MRE.Reset();
                            node.PreviousIsValid = false;
                            node.Previous        = Interlocked.Exchange(ref idleThreads, node);
                            node.PreviousIsValid = true;
                        }

                        // Wait for work
                        SpinWait sw = new SpinWait();
                        while (true)
                        {
                            if (node.MRE.IsSet)
                            {
                                // Work has been scheduled for this thread specifically, take it
                                action = Interlocked.Exchange(ref node.Work, null);
                                break;
                            }
                            if (TryTakeFromSharedNonBlocking(out var tempAction, sharedWorkStack))
                            {
                                action = tempAction;
                                break;                                 // We successfully dequeued this node from the shared stack, quit loop and process action
                            }

                            // Wait for work
                            if (sw.NextSpinWillYield)
                            {
                                // Wait for work to be scheduled specifically to this thread
                                node.MRE.Wait();
                                action = Interlocked.Exchange(ref node.Work, null);
                                break;
                            }

                            sw.SpinOnce();
                        }
                    }

                    try
                    {
                        action();
                    }
                    finally
                    {
                        PooledDelegateHelper.Release(action);
                    }
                }
            }
            finally
            {
                // We must keep up the amount of threads that the system handles.
                // Spawn a new one as this one is about to abort because of an exception.
                NewThread(node);
            }
        }
コード例 #15
0
        private void ProcessWorkItems(object paramObj)
        {
            try
            {
                while (true)
                {
                    Action action;
                    var    sw = new SpinWait();
                    while (true)
                    {
                        if (queue.TryDequeue(out action))
                        {
                            break;
                        }

                        if (Volatile.Read(ref itemCount) == 0)
                        {
                            if (sw.NextSpinWillYield)
                            {
                                bool reset = false;
                                lock (lockObj)
                                {
                                    if (Volatile.Read(ref itemCount) == 0)
                                    {
                                        Interlocked.Increment(ref idleCount);
                                        Monitor.Wait(lockObj);
                                        // We've got work to deal with, pulse other threads
                                        Monitor.Pulse(lockObj);
                                        reset = true;
                                    }
                                }

                                if (reset)
                                {
                                    Interlocked.Decrement(ref idleCount);
                                    sw = new SpinWait();
                                }
                            }
                            else
                            {
                                // Spin for a while to catch more incoming work
                                sw.SpinOnce();
                            }
                        }
                    }

                    Interlocked.Decrement(ref itemCount);
                    try
                    {
                        action();
                    }
                    finally
                    {
                        PooledDelegateHelper.Release(action);
                    }
                }
            }
            finally
            {
                // We must keep up the amount of threads that the system handles.
                // Spawn a new one as this one is about to abort because of an exception.
                NewThread();
            }
        }