/// <summary> /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle. /// </summary> private void SignalUserWaitHandle() { _callbackLock.VerifyIsLocked(); SafeWaitHandle handle = UserUnregisterWaitHandle; IntPtr handleValue = UserUnregisterWaitHandleValue; try { if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1)) { Debug.Assert(handleValue == handle.DangerousGetHandle()); #if PLATFORM_WINDOWS Interop.Kernel32.SetEvent(handle); #else WaitSubsystem.SetEvent(handleValue); #endif } } finally { handle?.DangerousRelease(); _callbacksComplete?.Set(); _unregistered = true; } }
// // This method must only be called if ShouldAdjustMaxWorkersActive has returned true, *and* // _hillClimbingThreadAdjustmentLock is held. // private void AdjustMaxWorkersActive() { _hillClimbingThreadAdjustmentLock.VerifyIsLocked(); int currentTicks = Environment.TickCount; int totalNumCompletions = (int)_completionCounter.Count; int numCompletions = totalNumCompletions - _separated.priorCompletionCount; long startTime = _currentSampleStartTime; long endTime = Stopwatch.GetTimestamp(); long freq = Stopwatch.Frequency; double elapsedSeconds = (double)(endTime - startTime) / freq; if (elapsedSeconds * 1000 >= _threadAdjustmentIntervalMs / 2) { ThreadCounts currentCounts = ThreadCounts.VolatileReadCounts(ref _separated.counts); int newMax; (newMax, _threadAdjustmentIntervalMs) = HillClimbing.ThreadPoolHillClimber.Update(currentCounts.numThreadsGoal, elapsedSeconds, numCompletions); while (newMax != currentCounts.numThreadsGoal) { ThreadCounts newCounts = currentCounts; newCounts.numThreadsGoal = (short)newMax; ThreadCounts oldCounts = ThreadCounts.CompareExchangeCounts(ref _separated.counts, newCounts, currentCounts); if (oldCounts == currentCounts) { // // If we're increasing the max, inject a thread. If that thread finds work, it will inject // another thread, etc., until nobody finds work or we reach the new maximum. // // If we're reducing the max, whichever threads notice this first will sleep and timeout themselves. // if (newMax > oldCounts.numThreadsGoal) { WorkerThread.MaybeAddWorkingWorker(); } break; } else { if (oldCounts.numThreadsGoal > currentCounts.numThreadsGoal && oldCounts.numThreadsGoal >= newMax) { // someone (probably the gate thread) increased the thread count more than // we are about to do. Don't interfere. break; } currentCounts = oldCounts; } } _separated.priorCompletionCount = totalNumCompletions; _separated.nextCompletedWorkRequestsTime = currentTicks + _threadAdjustmentIntervalMs; Volatile.Write(ref _separated.priorCompletedWorkRequestsTime, currentTicks); _currentSampleStartTime = endTime; } }
/// <summary> /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle. /// </summary> private void SignalUserWaitHandle() { _callbackLock.VerifyIsLocked(); SafeWaitHandle handle = UserUnregisterWaitHandle; IntPtr handleValue = UserUnregisterWaitHandleValue; try { if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1)) { EventWaitHandle.Set(handleValue); } } finally { handle?.DangerousRelease(); _callbacksComplete?.Set(); _unregistered = true; } }
/// <summary> /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle. /// </summary> private void SignalUserWaitHandle() { s_callbackLock.VerifyIsLocked(); SafeWaitHandle?handle = UserUnregisterWaitHandle; IntPtr handleValue = UserUnregisterWaitHandleValue; try { if (handleValue != IntPtr.Zero && handleValue != InvalidHandleValue) { Debug.Assert(handleValue == handle !.DangerousGetHandle()); EventWaitHandle.Set(handle); } } finally { handle?.DangerousRelease(); _callbacksComplete?.Set(); _unregistered = true; } }