public void SetDeviceStatus([NotNull] DeviceStatus status) { Guard.NotNull(status, nameof(status)); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (deviceMap.ContainsKey(status.DeviceAddress)) { DeviceMapEntry existingEntry = deviceMap[status.DeviceAddress]; bool hasChanges = existingEntry.ApplyChanges(status); existingEntry.Extend(); if (hasChanges) { Log.Debug($"Device {status.DeviceAddress} changed."); DeviceChanged?.Invoke(this, new EventArgs<DeviceStatus>(status)); } } else { var newEntry = new DeviceMapEntry(status, RemoveTimerTick); deviceMap[status.DeviceAddress] = newEntry; newEntry.Extend(); Log.Debug($"Device {status.DeviceAddress} added."); DeviceAdded?.Invoke(this, new EventArgs<DeviceStatus>(status)); } } } }
public void Init() { Tracker = new LockTracker("xxx"); Now = DateTimeOffset.Now.AddHours(2); Later = Now.AddHours(4); SystemTime.Now = () => Now; }
public FileEntry([NotNull] string name, [NotNull] DirectoryEntry parent) : base(name, FileAttributes.Archive, parent.ChangeTracker, parent.LoggedOnAccount) { Guard.NotNull(parent, nameof(parent)); Parent = parent; PathFormatter = new FileEntryPathFormatter(this); lockTracker = new LockTracker(this); if (parent.IsEncrypted) { SetEncrypted(); } CreationTimeUtc = LastWriteTimeUtc = LastAccessTimeUtc = parent.SystemClock.UtcNow(); }
public void UpdateMediatorStatus(int mediatorStatus) { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (mediatorStatus != lastMediatorStatus) { Log.Debug($"Mediator status changed from {lastMediatorStatus} to {mediatorStatus}."); lastMediatorStatus = mediatorStatus; MediatorStatusChanged?.Invoke(this, new EventArgs<int>(mediatorStatus)); } } } }
public async Task LockAsync(string key, string subKey, Func <Task> insideLock) { //Modified version of : http://stackoverflow.com/questions/5578744/doing-locking-in-asp-net-correctly //And : https://blog.cdemi.io/async-waiting-inside-c-sharp-locks/ string lockKey = GetLockKey(key, subKey); LockTracker lockTracker = _Locks.GetOrAdd(lockKey + "0", k => new LockTracker()); Interlocked.Increment(ref lockTracker.WaitingThreads); try { await lockTracker.Lock.WaitAsync(); await insideLock(); } finally { _Locks.TryRemove(lockKey + Interlocked.Decrement(ref lockTracker.WaitingThreads), out LockTracker _); lockTracker.Lock.Release(); } }
public void Start() { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (hasBeenStarted || hasBeenDisposed) { Log.Debug("Already started or disposed."); return; } hasBeenStarted = true; } } Log.Debug("Creating task for reconnect loop."); Task.Factory.StartNew(ReconnectLoop, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).ContinueWith(task => reconnectLoopTerminatedWaitHandle.Set()); }
/// <summary> /// Pauses the consumer. Blocks until the current action has completed. /// </summary> public void Pause() { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (!disposeRequested && isConsumerRunning) { isConsumerRunning = false; Log.Debug("Signaling state change after pause."); Monitor.Pulse(stateLock); } else { Log.Debug("Already paused or disposed."); } } } }
public void Initialize([NotNull] CirceControllerSessionManager sessionManager) { Guard.NotNull(sessionManager, nameof(sessionManager)); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (circeSessionManager.Value != null) { throw new InvalidOperationException("Already initialized."); } sessionManager.DeviceTracker.DeviceAdded += DeviceTrackerOnDeviceAddedOrChanged; sessionManager.DeviceTracker.DeviceChanged += DeviceTrackerOnDeviceAddedOrChanged; circeSessionManager.Value = sessionManager; } } }
public void Suspend() { AssertInitialized(); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (raiseEventsCancellationTokenSource != null) { raiseEventsCancellationTokenSource.Cancel(); raiseEventsCancellationTokenSource = null; } syncCancellationSource.Value?.Cancel(); } } }
private void RemoveTimerTick([NotNull] object state) { try { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); var entry = (DeviceMapEntry) state; WirelessNetworkAddress address = entry.LastStatus.DeviceAddress; if (deviceMap.Remove(address)) { Log.Debug($"Device {address} removed."); DeviceRemoved?.Invoke(this, new EventArgs<WirelessNetworkAddress>(address)); } entry.Dispose(); } } } catch (Exception ex) { Log.Error("Unexpected error while processing removal of wireless device.", ex); } }
public void Dispose() { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); while (deviceMap.Count > 0) { KeyValuePair<WirelessNetworkAddress, DeviceMapEntry> firstPair = deviceMap.First(); deviceMap.Remove(firstPair.Key); firstPair.Value.Dispose(); } } } }
public void Init() { Tracker = new LockTracker("xxx"); }
private void HandleNetworkSynchronizationCompleted(ClockSynchronizationResult synchronizationResult) { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (synchronizationResult == ClockSynchronizationResult.Succeeded) { Resume(); } networkBeingSynced = null; } } try { SyncCompleted?.Invoke(this, new ClockSynchronizationCompletedEventArgs(synchronizationResult)); } catch (Exception ex) { Log.Error($"Failed to handle clock synchronization update for {synchronizationResult}.", ex); } }
public void Dispose() { using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (!disposeRequested) { disposeRequested = true; Log.Debug("Dispose: Signaling state change after dispose."); Monitor.Pulse(stateLock); workQueue.CompleteAdding(); } else { Log.Debug("Already disposed."); } } } }
public void Dispose() { // We protect against disposing multiple times sequentially, not concurrently. bool disposeAlreadyDone; bool mustWaitForReconnectLoopToComplete; using (var lockTracker = new LockTracker(Log, "Dispose (pre)")) { lock (stateLock) { lockTracker.Acquired(); disposeAlreadyDone = hasBeenDisposed; mustWaitForReconnectLoopToComplete = hasBeenStarted; } } if (!disposeAlreadyDone) { if (mustWaitForReconnectLoopToComplete) { Log.Debug("Signaling reconnect loop to terminate."); disposeRequestedWaitHandle.Set(); Log.Debug("Waiting until reconnect loop has terminated."); reconnectLoopTerminatedWaitHandle.Wait(); } Log.Debug("Cleaning up wait handles."); disposeRequestedWaitHandle.Dispose(); reconnectLoopTerminatedWaitHandle.Dispose(); using (var lockTracker = new LockTracker(Log, "Dispose (post)")) { lock (stateLock) { lockTracker.Acquired(); hasBeenDisposed = true; } } } else { Log.Debug("Already disposed."); } }
public void Accept(NotifyActionOperation operation) { using (var lockTracker = new LockTracker(InnerLog, MethodBase.GetCurrentMethod())) { lock (nonReentrantProcessIncomingOperationLock) { lockTracker.Acquired(); owner.HandleIncomingNotifyActionOperation(operation); } } }
private void DeviceTrackerOnDeviceAddedOrChanged([CanBeNull] object sender, [NotNull] EventArgs<DeviceStatus> eventArgs) { Guard.NotNull(eventArgs, nameof(eventArgs)); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (!deviceMap.ContainsKey(eventArgs.Argument.DeviceAddress)) { deviceMap[eventArgs.Argument.DeviceAddress] = new DeviceSyncStatus(); } deviceMap[eventArgs.Argument.DeviceAddress].Update(eventArgs.Argument.ClockSynchronization); if (deviceMap[eventArgs.Argument.DeviceAddress].IsSynchronized && IsSyncInProgress) { VerifySynchronizationComplete(); } } } }
public bool IsDeviceSynchronized([NotNull] WirelessNetworkAddress deviceAddress) { Guard.NotNull(deviceAddress, nameof(deviceAddress)); AssertInitialized(); bool result = false; using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (deviceMap.ContainsKey(deviceAddress)) { result = deviceMap[deviceAddress].IsSynchronized; } } } return result; }
public void NotifyDeviceIsAlive([NotNull] WirelessNetworkAddress deviceAddress) { Guard.NotNull(deviceAddress, nameof(deviceAddress)); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (deviceMap.ContainsKey(deviceAddress)) { DeviceMapEntry existingEntry = deviceMap[deviceAddress]; existingEntry.Extend(); } } } }
private void ConsumerLoop() { Log.Debug("Entering ConsumerLoop."); foreach (WorkItem workItem in workQueue.GetConsumingEnumerable()) { try { if (workItem.CancelToken.IsCancellationRequested) { // Action was canceled (and task was signaled) while waiting in the queue, so ignore it. Log.Debug("Skipping pre-canceled queue entry."); continue; } using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); if (!isConsumerRunning && !disposeRequested) { Log.Debug("Entering wait loop until running or disposing."); while (!isConsumerRunning && !disposeRequested) { // Consumer is paused, so block this thread until state changes. Monitor.Wait(stateLock); } Log.Debug("Exited wait loop."); } if (disposeRequested) { // Dispose has been called by producer, so cancel whatever is left in the queue. Log.Debug("Disposal has been requested, canceling queue entry."); workItem.TaskSource.TrySetCanceled(); continue; } int taskId = workItem.TaskSource.Task.Id; // Perform action inside lock, so that state transitions will block // until the current action has completed. try { workItem.CancelToken.ThrowIfCancellationRequested(); Log.Debug($"Executing action for task {taskId}."); workItem.Action(); workItem.TaskSource.TrySetResult(null); Log.Debug("Task completed."); } catch (OperationCanceledException) { Log.Debug($"Propagating cancellation request to task {taskId}."); workItem.TaskSource.TrySetCanceled(); } catch (Exception ex) { Log.Debug($"Setting task {taskId} to error state."); workItem.TaskSource.TrySetException(ex); } } } } catch (Exception ex) { Log.Error("Unexpected error in ConsumerLoop.", ex); } } workQueue.Dispose(); Log.Debug("Leaving ConsumerLoop."); }
public void StartNetworkSynchronization( [NotNull] [ItemNotNull] IEnumerable<WirelessNetworkAddress> devicesInNetwork) { Guard.NotNull(devicesInNetwork, nameof(devicesInNetwork)); CirceControllerSessionManager sessionManager = AssertInitialized(); using (var lockTracker = new LockTracker(Log, MethodBase.GetCurrentMethod())) { lock (stateLock) { lockTracker.Acquired(); AssertNotSyncInProgress(); Suspend(); networkBeingSynced = new HashSet<WirelessNetworkAddress>(devicesInNetwork); if (!NetworkContainsSynchronizableDevices()) { // Only devices without a clock. No need for sync or raise events for clock re-sync. Task.Factory.StartNew( () => HandleNetworkSynchronizationCompleted(ClockSynchronizationResult.Succeeded), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); return; } ResetDevices(); } } syncCancellationSource.Value = new CancellationTokenSource(); Task invokeOperationTask = sessionManager.SynchronizeClocksAsync(syncCancellationSource.Value.Token); invokeOperationTask.ContinueWith(opTask => { if (opTask.IsFaulted) { Log.Warn("Failed sending SynchronizeClocks operation.", opTask.Exception); HandleNetworkSynchronizationCompleted(ClockSynchronizationResult.Failed); } else if (opTask.IsCanceled) { Log.Warn("Timeout on sending SynchronizeClocks operation."); HandleNetworkSynchronizationCompleted(ClockSynchronizationResult.CanceledOrTimedOut); } else { Task<ClockSynchronizationResult> waitForRepliesTask = WaitForRepliesAsync(syncCancellationSource.Value.Token); waitForRepliesTask.ContinueWith(repliesTask => { if (repliesTask.IsFaulted) { Log.Warn("Failed waiting for Sync replies.", opTask.Exception); HandleNetworkSynchronizationCompleted(ClockSynchronizationResult.Failed); } else if (repliesTask.IsCanceled) { string succeeded = deviceMap.Any() ? string.Join(", ", deviceMap.Keys.Where(IsDeviceSynchronized)) : "(none)"; Log.Warn($"Timeout on waiting for Sync Succeeded replies. Devices succeeded: {succeeded}"); HandleNetworkSynchronizationCompleted(ClockSynchronizationResult.CanceledOrTimedOut); } else { HandleNetworkSynchronizationCompleted(repliesTask.Result); } }, TaskScheduler.Current); AutoCancelTaskAfterTimeout(waitForRepliesTask, syncCancellationSource.Value); } }, TaskScheduler.Current); AutoCancelTaskAfterTimeout(invokeOperationTask, syncCancellationSource.Value); }