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); } } }
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); } } }
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(); } }
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; } }
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(); }
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(); } }
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); } }