Exemple #1
0
        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);
                }
            }
        }
Exemple #2
0
        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);
                }
            }
        }
Exemple #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();
            }
        }
Exemple #4
0
        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;
            }
        }
Exemple #5
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();
        }
Exemple #6
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();
            }
        }
Exemple #7
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);
            }
        }