public void PulseAll_ReleasesAllWaiters() { AsyncContext.Run(async() => { var monitor = new AsyncMonitor(); int completed = 0; var task1Ready = new TaskCompletionSource(); var task2Ready = new TaskCompletionSource(); Task <IDisposable> lockTask1 = null; Task waitTask1 = null; var task1 = Task.Run(async() => { lockTask1 = monitor.EnterAsync(); using (await lockTask1) { waitTask1 = monitor.WaitAsync(); task1Ready.SetResult(); await waitTask1; Interlocked.Increment(ref completed); } }); await task1Ready.Task; Task <IDisposable> lockTask2 = null; Task waitTask2 = null; var task2 = Task.Run(async() => { lockTask2 = monitor.EnterAsync(); using (await lockTask2) { waitTask2 = monitor.WaitAsync(); task2Ready.SetResult(); await waitTask2; Interlocked.Increment(ref completed); } }); await task2Ready.Task; var lockTask3 = monitor.EnterAsync(); using (await lockTask3) { monitor.PulseAll(); } await Task.WhenAll(task1, task2); var result = Interlocked.CompareExchange(ref completed, 0, 0); Assert.AreEqual(2, result); }); }
public async Task ProcessingRpcCompleted() { using (await netChMonitor.EnterAsync()) { await netChMonitor.WaitAsync(); } }
public async Task AddingTransactionsCompleted() { using (await submitChMonitor.EnterAsync()) { await submitChMonitor.WaitAsync(); } }
public async Task CommitBlocksCompleted() { using (await commitChMonitor.EnterAsync()) { await commitChMonitor.WaitAsync(); } }
/// <summary> /// Wait for the model to be fully updated from RepRapFirmware /// </summary> /// <param name="cancellationToken">Cancellation token</param> /// <returns>Asynchronous task</returns> public static async Task WaitForFullUpdate(CancellationToken cancellationToken) { using (await _monitor.EnterAsync(cancellationToken)) { await _monitor.WaitAsync(cancellationToken); Program.CancelSource.Token.ThrowIfCancellationRequested(); } }
/// <summary> /// Wait for the model to be fully updated from RepRapFirmware /// </summary> /// <returns>Asynchronous task</returns> public static async Task WaitForFullUpdate() { using (await _updateEvent.EnterAsync()) { await _updateEvent.WaitAsync(Program.CancelSource.Token); Program.CancelSource.Token.ThrowIfCancellationRequested(); } }
public async Task PulseAll_ReleasesAllWaiters() { AsyncMonitor monitor = new AsyncMonitor(); int[] completed = { 0 }; TaskCompletionSource <object> task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>(); TaskCompletionSource <object> task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>(); Task waitTask1 = null; Task task1 = Task.Run(async() => { using (await monitor.EnterAsync()) { waitTask1 = monitor.WaitAsync(); task1Ready.SetResult(null); await waitTask1; Interlocked.Increment(ref completed[0]); } }); await task1Ready.Task; Task waitTask2 = null; Task task2 = Task.Run(async() => { using (await monitor.EnterAsync()) { waitTask2 = monitor.WaitAsync(); task2Ready.SetResult(null); await waitTask2; Interlocked.Increment(ref completed[0]); } }); await task2Ready.Task; AwaitableDisposable <IDisposable> lockTask3 = monitor.EnterAsync(); using (await lockTask3) { monitor.PulseAll(); } await Task.WhenAll(task1, task2).ConfigureAwait(false); int result = Interlocked.CompareExchange(ref completed[0], 0, 0); Assert.Equal(2, result); }
public async Task PulseAll_ReleasesAllWaiters() { var monitor = new AsyncMonitor(); int completed = 0; var task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>(); var task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>(); Task waitTask1 = null; var task1 = Task.Run(async() => { using (await monitor.EnterAsync()) { waitTask1 = monitor.WaitAsync(); task1Ready.SetResult(null); await waitTask1; Interlocked.Increment(ref completed); } }); await task1Ready.Task; Task waitTask2 = null; var task2 = Task.Run(async() => { using (await monitor.EnterAsync()) { waitTask2 = monitor.WaitAsync(); task2Ready.SetResult(null); await waitTask2; Interlocked.Increment(ref completed); } }); await task2Ready.Task; var lockTask3 = monitor.EnterAsync(); using (await lockTask3) { monitor.PulseAll(); } await Task.WhenAll(task1, task2); var result = Interlocked.CompareExchange(ref completed, 0, 0); Assert.Equal(2, result); }
public void Pulse_ReleasesOneWaiter() { Test.Async(async() => { var monitor = new AsyncMonitor(); int completed = 0; var task1Ready = new TaskCompletionSource(); var task2Ready = new TaskCompletionSource(); var task1 = TaskShim.Run(async() => { using (await monitor.EnterAsync()) { var waitTask1 = monitor.WaitAsync(); task1Ready.SetResult(); await waitTask1; Interlocked.Increment(ref completed); } }); await task1Ready.Task; var task2 = TaskShim.Run(async() => { using (await monitor.EnterAsync()) { var waitTask2 = monitor.WaitAsync(); task2Ready.SetResult(); await waitTask2; Interlocked.Increment(ref completed); } }); await task2Ready.Task; using (await monitor.EnterAsync()) { monitor.Pulse(); } await TaskShim.WhenAny(task1, task2); var result = Interlocked.CompareExchange(ref completed, 0, 0); Assert.AreEqual(1, result); }); }
public override async Task <IQueueEntry <T> > DequeueAsync(CancellationToken cancellationToken) { _logger.Trace("Queue {type} dequeuing item...", typeof(T).Name); _logger.Trace("Queue count: {0}", _queue.Count); if (_queue.Count == 0 && !cancellationToken.IsCancellationRequested) { _logger.Trace("Waiting to dequeue item..."); var sw = Stopwatch.StartNew(); try { using (await _monitor.EnterAsync(cancellationToken)) await _monitor.WaitAsync(cancellationToken).AnyContext(); } catch (TaskCanceledException) {} sw.Stop(); _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString()); } if (_queue.Count == 0) { return(null); } _logger.Trace("Dequeue: Attempt"); QueueEntry <T> info; if (!_queue.TryDequeue(out info) || info == null) { return(null); } info.Attempts++; info.DequeuedTimeUtc = DateTime.UtcNow; if (!_dequeued.TryAdd(info.Id, info)) { throw new ApplicationException("Unable to add item to the dequeued list."); } Interlocked.Increment(ref _dequeuedCount); _logger.Trace("Dequeue: Got Item"); var entry = new QueueEntry <T>(info.Id, info.Value.Copy(), this, info.EnqueuedTimeUtc, info.Attempts); await OnDequeuedAsync(entry).AnyContext(); ScheduleNextMaintenance(DateTime.UtcNow.Add(_workItemTimeout)); return(entry); }
public async Task WillPulseMonitor() { var monitor = new AsyncMonitor(); var sw = Stopwatch.StartNew(); // Monitor will not be pulsed and should be cancelled after 100ms. using (await monitor.EnterAsync()) await Assert.ThrowsAsync <OperationCanceledException>(() => monitor.WaitAsync(TimeSpan.FromMilliseconds(100).ToCancellationToken())); sw.Stop(); Assert.InRange(sw.ElapsedMilliseconds, 75, 125); var t = Task.Run(async() => { await SystemClock.SleepAsync(25); using (await monitor.EnterAsync()) monitor.Pulse(); }); sw = Stopwatch.StartNew(); using (await monitor.EnterAsync()) await monitor.WaitAsync(TimeSpan.FromSeconds(1).ToCancellationToken()); sw.Stop(); Assert.InRange(sw.ElapsedMilliseconds, 25, 100); }
/// <summary> /// Process status updates in the background /// </summary> /// <returns>Asynchronous task</returns> public static async Task Run() { CancellationToken cancellationToken = Program.CancelSource.Token; do { // Wait for the next status response using (await _monitor.EnterAsync(cancellationToken)) { await _monitor.WaitAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); // Process it try { ReadOnlyMemory <byte> json = _json.AsMemory().Slice(0, _jsonLength); switch (_module) { case 2: await ProcessAdvancedResponse(json); break; case 3: await ProcessPrintResponse(json); break; case 5: await ProcessConfigResponse(json); break; } // Notify waiting clients about the model update if (_module == 2) { _updateEvent.PulseAll(); } } catch (JsonException e) { _logger.Error(e, "Failed to merge JSON (module {0})", _module); } } }while (true); }
public async Task JobLoop(CancellationToken cancellationToken) { try { using (await jobLock.EnterAsync(cancellationToken)) { while (!cancellationToken.IsCancellationRequested) { while (runningJobs < maxJobs) { _ = Task.Run(() => JobFiber(cancellationToken), cancellationToken); ++runningJobs; } await jobLock.WaitAsync(cancellationToken); } } } catch (OperationCanceledException) {} }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. /// </returns> /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception> public async ValueTask <bool> MoveNextAsync() { using (await monitor.EnterAsync()) { while (cached.Count == 0 && active) { await monitor.WaitAsync(); } if (active == false && cached.Count == 0) { return(false); } current = cached.Dequeue(); return(true); } }
/// <summary> /// MoveNext the enumerator /// </summary> /// <returns></returns> public async ValueTask <bool> MoveNextAsync() { using (await monitor.EnterAsync()) { if (Interlocked.Increment(ref callsToMoveNext) == numberOfConsumers) { callsToMoveNext = 0; moveNext = await innerEnumerator.MoveNextAsync(); current = innerEnumerator.Current; Debug("Pulsing all waiting threads"); monitor.PulseAll(); } else { await monitor.WaitAsync(); } } return(moveNext); }
/// <summary> /// Waits for commands to be received and enqueues them in a concurrent queue so that a <see cref="Code"/> /// can decide when to cancel/resume/resolve the execution. /// </summary> /// <returns>Task that represents the lifecycle of the connection</returns> public override async Task Process() { lock (_connections[_mode]) { _connections[_mode].Add(this); } Connection.Logger.Debug("Interception processor registered"); using (await _codeMonitor.EnterAsync(Program.CancellationToken)) { try { do { // Wait for the next code to be intercepted do { using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(Program.CancellationToken); cts.CancelAfter(Settings.SocketPollInterval); try { await _codeMonitor.WaitAsync(Program.CancellationToken); break; } catch (OperationCanceledException) { if (Program.CancellationToken.IsCancellationRequested) { throw; } Connection.Poll(); } }while (true); try { // Send it to the client await Connection.Send(_codeBeingIntercepted); // Keep processing incoming commands until a final action for the code has been received BaseCommand command; Type commandType; do { // Read another command from the IPC connection command = await Connection.ReceiveCommand(); commandType = command.GetType(); if (Command.SupportedCommands.Contains(commandType)) { // Make sure it is permitted Connection.CheckPermissions(commandType); // Execute regular commands here object result = await command.Invoke(); await Connection.SendResponse(result); } else if (SupportedCommands.Contains(commandType)) { // Make sure it is permitted Connection.CheckPermissions(commandType); // Send other commands to the task intercepting the code _interceptionResult = command; _codeMonitor.Pulse(); break; } else { // Take care of unsupported commands throw new ArgumentException($"Invalid command {command.Command} (wrong mode?)"); } }while (!Program.CancellationToken.IsCancellationRequested); // Stop if the connection has been terminated if (command == null) { break; } } catch (SocketException) { // Client has closed the connection while we're waiting for a result. Carry on... _interceptionResult = null; _codeMonitor.Pulse(); throw; } }while (!Program.CancellationToken.IsCancellationRequested); } finally { lock (_connections[_mode]) { _connections[_mode].Remove(this); } Connection.Logger.Debug("Interception processor unregistered"); } } }
protected override async Task <IQueueEntry <T> > DequeueImplAsync(CancellationToken cancellationToken) { _logger.Trace("Queue {_queueName} dequeuing item...", _queueName); var now = SystemClock.UtcNow.Ticks; await EnsureMaintenanceRunningAsync().AnyContext(); await EnsureTopicSubscriptionAsync().AnyContext(); var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token; RedisValue value = await DequeueIdAsync(linkedCancellationToken).AnyContext(); if (linkedCancellationToken.IsCancellationRequested && value.IsNullOrEmpty) { return(null); } _logger.Trace("Initial list value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())); while (value.IsNullOrEmpty && !linkedCancellationToken.IsCancellationRequested) { _logger.Trace("Waiting to dequeue item..."); var sw = Stopwatch.StartNew(); try { using (await _monitor.EnterAsync(cancellationToken).AnyContext()) await _monitor.WaitAsync(cancellationToken).AnyContext(); } catch (OperationCanceledException) { } sw.Stop(); _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString()); value = await DequeueIdAsync(linkedCancellationToken).AnyContext(); _logger.Trace("List value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())); } if (value.IsNullOrEmpty) { return(null); } await Run.WithRetriesAsync(() => _cache.SetAsync(GetDequeuedTimeKey(value), now, GetWorkItemTimeoutTimeTtl()), logger : _logger).AnyContext(); await Run.WithRetriesAsync(() => _cache.SetAsync(GetRenewedTimeKey(value), now, GetWorkItemTimeoutTimeTtl()), logger : _logger).AnyContext(); try { var entry = await GetQueueEntryAsync(value).AnyContext(); if (entry == null) { return(null); } Interlocked.Increment(ref _dequeuedCount); await OnDequeuedAsync(entry).AnyContext(); _logger.Debug("Dequeued item: {0}", value); return(entry); } catch (Exception ex) { _logger.Error(ex, "Error getting dequeued item payload: {0}", value); throw; } }
public override async Task <QueueEntry <T> > DequeueAsync(CancellationToken cancellationToken = default(CancellationToken)) { #if DEBUG Logger.Trace().Message($"Queue {_queueName} dequeuing item...").Write(); #endif await EnsureMaintenanceRunningAsync().AnyContext(); await EnsureTopicSubscriptionAsync().AnyContext(); var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token; RedisValue value = await GetRedisValueAsync(linkedCancellationToken).AnyContext(); if (linkedCancellationToken.IsCancellationRequested && value.IsNullOrEmpty) { return(null); } #if DEBUG Logger.Trace().Message("Initial list value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write(); #endif while (value.IsNullOrEmpty && !linkedCancellationToken.IsCancellationRequested) { #if DEBUG Logger.Trace().Message("Waiting to dequeue item...").Write(); var sw = Stopwatch.StartNew(); #endif try { using (await _monitor.EnterAsync(cancellationToken)) await _monitor.WaitAsync(cancellationToken).AnyContext(); } catch (TaskCanceledException) { } #if DEBUG sw.Stop(); Logger.Trace().Message("Waited for dequeue: {0}", sw.Elapsed.ToString()).Write(); #endif value = await GetRedisValueAsync(linkedCancellationToken).AnyContext(); #if DEBUG Logger.Trace().Message("List value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write(); #endif } if (value.IsNullOrEmpty) { return(null); } await _cache.SetAsync(GetDequeuedTimeKey(value), DateTime.UtcNow.Ticks, GetDequeuedTimeTtl()).AnyContext(); try { var payload = await _cache.GetAsync <T>(GetPayloadKey(value)).AnyContext(); if (payload.IsNull) { Logger.Error().Message("Error getting queue payload: {0}", value).Write(); await _db.ListRemoveAsync(WorkListName, value).AnyContext(); return(null); } var enqueuedTimeTicks = await _cache.GetAsync <long>(GetEnqueuedTimeKey(value), 0).AnyContext(); var attemptsValue = await _cache.GetAsync <int>(GetAttemptsKey(value), -1).AnyContext(); var entry = new QueueEntry <T>(value, payload.Value, this, new DateTime(enqueuedTimeTicks, DateTimeKind.Utc), attemptsValue); Interlocked.Increment(ref _dequeuedCount); await OnDequeuedAsync(entry).AnyContext(); #if DEBUG Logger.Debug().Message("Dequeued item: {0}", value).Write(); #endif return(entry); } catch (Exception ex) { Logger.Error().Exception(ex).Message("Error getting queue payload: {0}", value).Write(); throw; } }