Esempio n. 1
0
        private void ExitWorkBlocker(WorkBlocker workBlocker)
        {
            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            Debug.Assert(workBlocker != null, "workBlocker != null");

            lock (_workBlockersSyncRoot)
            {
                // !!! Everything has changed, after we have captured the lock. !!!
                ////
                bool removed = workBlocker.WorkItem.Blockers.Remove(workBlocker);
                if (!removed)
                {
                    throw new InvalidOperationException(
                              $"Error exiting work blocker section. Work blocker already released. {CallerInfoToString(workBlocker.DebugInfo, workBlocker.CallerInfo)}");
                }

                removed = _workBlockers.Remove(workBlocker);
                Debug.Assert(removed, "Double remove error.");

                // Scheduling next work item after some grace period.
                if (!_workBlockers.Any() && !IsShutdownStarted)
                {
                    // Raising event for starting new work item.
                    _noMoreBlockersEvent.Set();
                }
            }
        }
Esempio n. 2
0
        private WorkBlocker EnterWorkBlocker(ActiveWorkItem workItem, string debugInfo, CallerInfo callerInfo)
        {
            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            Debug.Assert(workItem != null, "workItem != null");

            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            Debug.Assert(debugInfo != null, "debugInfo != null");

            lock (_workBlockersSyncRoot)
            {
                // Validating work item is active.
                if (!_activeWorkItems.Contains(workItem))
                {
                    throw new InvalidOperationException(
                              $"Error entering work blocker section. Work item already completed. {CallerInfoToString(debugInfo, callerInfo)}");
                }

                // !!! Everything has changed, after we have captured the lock. !!!
                ////
                // Canceling currently is being created work item.
                _workItemValidationId++;

                var workBlocker = new WorkBlocker(false, workItem, debugInfo, callerInfo);

                // Registering blocker.
                _workBlockers.Add(workBlocker);
                workBlocker.WorkItem.Blockers.Add(workBlocker);

                return(workBlocker);
            }
        }
Esempio n. 3
0
        private async Task ExecuteNewWorkItem(long workItemValidationId)
        {
            ActiveWorkItem workItem;
            WorkBlocker    workBlocker;

            lock (_workBlockersSyncRoot)
            {
                // !!! Everything has changed in the world, after we are captured the lock. !!!
                ////
                _shutdownCancellationToken.ThrowIfCancellationRequested();

                // Do nothing, if work item creation has been canceled.
                if (workItemValidationId != _workItemValidationId)
                {
                    return;
                }

                // Creating and registering a new work item.
                workItem = new ActiveWorkItem(this);

                // Creating initial work blocker for the new work item.
                workBlocker = new WorkBlocker(
                    true,
                    workItem,
                    string.Empty,
                    new CallerInfo("new work item", "initial_blocker", 0));

                // Registering blocker.
                _workBlockers.Add(workBlocker);
                workItem.Blockers.Add(workBlocker);

                _activeWorkItems.Add(workItem);
            }

            try
            {
                // Running new work item.
                await _workItemAction(workItem, new ActiveWorkerBlockerToken(workBlocker));
            }
            finally
            {
                lock (_workBlockersSyncRoot)
                {
                    bool removed = _activeWorkItems.Remove(workItem);
                    Debug.Assert(removed, "Double remove is wrong");

                    // When no more work items left and termination requested - setting termination finish cts event.
                    if (IsShutdownStarted && !_activeWorkItems.Any())
                    {
                        _shutdownCompletedCts.Cancel();
                    }

                    // It's allowed to not dispose initial blocker.
                    if ((workItem.Blockers.Count == 1) && workItem.Blockers.First().IsInitialBlocker)
                    {
                        var blocker = workItem.Blockers.First();

                        // Disposing last initial blocker.
                        workItem.Blockers.Remove(blocker);
                        _workBlockers.Remove(blocker);

                        // Scheduling next work item after some grace period.
                        if (!_workBlockers.Any() && !IsShutdownStarted)
                        {
                            // Raising event for starting new work item.
                            _noMoreBlockersEvent.Set();
                        }
                    }
                    else
                    {
                        // Raising critical errors if some locks was not released when task exited.
                        foreach (WorkBlocker unreleasedBlockers in workItem.Blockers)
                        {
                            Critical.Assert(
                                false,
                                $"Unreleased work blocker section at {CallerInfoToString(unreleasedBlockers.DebugInfo, unreleasedBlockers.CallerInfo)}");
                        }
                    }
                }
            }
        }