public CompetitionClassModel ReplaceModel([NotNull] CompetitionClassModel replacementVersion, [NotNull] CompetitionClassModel originalVersion) { Guard.NotNull(replacementVersion, nameof(replacementVersion)); Guard.NotNull(originalVersion, nameof(originalVersion)); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (originalVersion != activeModel.Value) { // Should never get here. throw new OptimisticConcurrencyException("Unexpected model update from multiple threads."); } try { serializer.Save(replacementVersion); } catch (Exception ex) { Log.Error("Failed to save in-memory model to disk.", ex); } activeModel.Value = replacementVersion; return replacementVersion; } } }
private void ExecuteExclusiveIfStateIn([NotNull] ICollection<CompetitionClassState> statesAllowed, [NotNull] Action action) { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (statesAllowed.Contains(classState)) { action(); } else { string statesList = string.Join(", ", statesAllowed.Select(s => s.ToString())); Log.Debug( $"Discarding operation, because current state {classState} is not in allowed set ({statesList})."); } } } }
public void Reset() { // Note: Intentionally not raising any events here, because caller wants to // combine multiple changes in single network packet (performance optimization). StopMonitorCourseTime(); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); maximumCourseTimeElapsed = false; isManuallyEliminated = false; refusalCount = 0; } } }
private void RaiseEventsOnChangeWithLock([NotNull] Action action) { EliminationEventArgs argsForEliminationChanged; EventArgs<int> argsForRefusalCountChanged; using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); bool beforeIsEliminated = UnsafeIsEliminated; int beforeRefusalCount = refusalCount; action(); argsForEliminationChanged = UnsafeIsEliminated != beforeIsEliminated ? new EliminationEventArgs(UnsafeIsEliminated) : null; argsForRefusalCountChanged = refusalCount != beforeRefusalCount ? new EventArgs<int>(refusalCount) : null; } } if (argsForEliminationChanged != null) { EliminationChanged?.Invoke(this, argsForEliminationChanged); } if (argsForRefusalCountChanged != null) { RefusalCountChanged?.Invoke(this, argsForRefusalCountChanged); } }
private void ExclusiveUpdateWithRaiseEvent(bool forceChanged, [NotNull] Func<NetworkHealthReport, NetworkHealthReport> updateCallback) { EventArgs<NetworkHealthReport> eventArgs; // Must lock despite of FreshReference, to prevent concurrent calls overwriting each others changes. using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (StateLock) { lockTracker.Acquired(); NetworkHealthReport newReport = updateCallback(previousReport.Value); bool hasChanged = forceChanged || newReport != previousReport.Value; previousReport.Value = newReport; eventArgs = hasChanged ? new EventArgs<NetworkHealthReport>(newReport) : null; } } if (eventArgs != null) { Log.Info($"Network health has changed - {eventArgs.Argument}"); HealthChanged?.Invoke(this, eventArgs); } }