public void MultipleWaits_NotifyAll_AllAreCompleted() { AsyncContext.Run(async() => { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); var key1 = await mutex.LockAsync(); var task1 = cv.WaitAsync(); var __ = task1.ContinueWith(_ => key1.Dispose()); var key2 = await mutex.LockAsync(); var task2 = cv.WaitAsync(); var ___ = task2.ContinueWith(_ => key2.Dispose()); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.NotifyAll(); } }); await task1; await task2; }); }
/// <summary> /// Wait for an update to occur /// </summary> /// <param name="cancellationToken">Cancellation token</param> /// <returns>Asynchronous task</returns> public static async Task WaitForUpdate(CancellationToken cancellationToken) { using (await _updateLock.LockAsync(cancellationToken)) { await _updateEvent.WaitAsync(cancellationToken); Program.CancelSource.Token.ThrowIfCancellationRequested(); } }
public async Task DoSomethingAsync() { using (await _mutex.LockAsync()) { DoSomeWork(); await _cv.WaitAsync(); DoMoreWork(); } }
public async Task WaitAsync_WithoutNotify_IsNotCompleted() { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); await mutex.LockAsync(); var task = cv.WaitAsync(); await AsyncAssert.NeverCompletesAsync(task); }
public async Task WaitAsync_WithoutNotify_IsNotCompleted() { AsyncLock mutex = new AsyncLock(); AsyncConditionVariable cv = new AsyncConditionVariable(mutex); await mutex.LockAsync(); Task task = cv.WaitAsync(); await AsyncAssert.NeverCompletesAsync(task).ConfigureAwait(false); }
public async Task <bool> OutputAvailableAsync(CancellationToken cancellationToken) { using (await _mutex.LockAsync().ConfigureAwait(false)) { while (!_completed.IsCancellationRequested && Empty) { await _completedOrNotEmpty.WaitAsync(cancellationToken).ConfigureAwait(false); } return(!Empty); } }
public void WaitAsync_WithoutNotify_IsNotCompleted() { AsyncContext.Run(async() => { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); await mutex.LockAsync(); var task = cv.WaitAsync(); await AssertEx.NeverCompletesAsync(task); }); }
public async Task MultipleWaits_Notify_OneIsCompleted() { AsyncLock mutex = new AsyncLock(); AsyncConditionVariable cv = new AsyncConditionVariable(mutex); IDisposable key = await mutex.LockAsync(); Task task1 = cv.WaitAsync(); Task __ = task1.ContinueWith(_ => key.Dispose()); await mutex.LockAsync(); Task task2 = cv.WaitAsync(); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }).ConfigureAwait(false); await task1; await AsyncAssert.NeverCompletesAsync(task2).ConfigureAwait(false); }
public async Task MultipleWaits_Notify_OneIsCompleted() { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); var key = await mutex.LockAsync(); var task1 = cv.WaitAsync(); var __ = task1.ContinueWith(_ => key.Dispose()); await mutex.LockAsync(); var task2 = cv.WaitAsync(); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }); await task1; await AsyncAssert.NeverCompletesAsync(task2); }
//private static async Task AwaitCompletionAsync(IProcessingContext context) //{ // do // { // await Task.WhenAll( // context.InteractionCollection.IsEmptyAsync(), // context.EvaluatorCollection.IsEmptyAsync()); // } while ( // (!context.InteractionCollection.IsEmpty() || // !context.EvaluatorCollection.IsEmpty()) && // !context.IsCancellationRequested); // if (context.IsCancellationRequested) return; // context.EvaluatorCollection.CompleteAdding(); // context.InteractionCollection.CompleteAdding(); //} public async Task <bool> IsEmptyAsync(CancellationToken cancellationToken) { // Lock our mutex using (await _mutex.LockAsync().ConfigureAwait(false)) { // while we are not complete and the collection is not empty wait to be notified that it is. while (!_completed.IsCancellationRequested && !Empty) { await _completedOrIsEmpty.WaitAsync(cancellationToken).ConfigureAwait(false); } return(Empty); } }
public async Task MultipleWaits_NotifyAll_AllAreCompleted() { AsyncLock mutex = new AsyncLock(); AsyncConditionVariable cv = new AsyncConditionVariable(mutex); IDisposable key1 = await mutex.LockAsync(); Task task1 = cv.WaitAsync(); Task __ = task1.ContinueWith(_ => key1.Dispose()); IDisposable key2 = await mutex.LockAsync(); Task task2 = cv.WaitAsync(); Task ___ = task2.ContinueWith(_ => key2.Dispose()); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.NotifyAll(); } }).ConfigureAwait(false); await task1; await task2; }
public async Task AddAsync(T item) { using (await mutex.LockAsync()) { while (Full) { await notFull.WaitAsync(); } if (!collection.TryAdd(item)) { throw new InvalidOperationException("The underlying collection refused the item."); } notEmpty.Notify(); } }
public async Task WaitAsync_AfterNotify_IsNotCompleted() { AsyncLock mutex = new AsyncLock(); AsyncConditionVariable cv = new AsyncConditionVariable(mutex); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }).ConfigureAwait(false); await mutex.LockAsync(); Task task = cv.WaitAsync(); await AsyncAssert.NeverCompletesAsync(task).ConfigureAwait(false); }
public async Task WaitAsync_Notified_IsCompleted() { AsyncLock mutex = new AsyncLock(); AsyncConditionVariable cv = new AsyncConditionVariable(mutex); await mutex.LockAsync(); Task task = cv.WaitAsync(); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }).ConfigureAwait(false); await task; }
public async Task WaitAsync_AfterNotify_IsNotCompleted() { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }); await mutex.LockAsync(); var task = cv.WaitAsync(); await AsyncAssert.NeverCompletesAsync(task); }
public async Task <T> TakeAsync() { using (await mutex.LockAsync()) { while (Empty) { await notEmpty.WaitAsync(); } T ret; if (!collection.TryTake(out ret)) { throw new InvalidOperationException("The underlying collection refused to provide an item."); } notFull.Notify(); return(ret); } }
public async Task WaitAsync_Notified_IsCompleted() { var mutex = new AsyncLock(); var cv = new AsyncConditionVariable(mutex); await mutex.LockAsync(); var task = cv.WaitAsync(); await Task.Run(async() => { using (await mutex.LockAsync()) { cv.Notify(); } }); await task; }
private async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool sync) { using (sync ? _mutex.Lock(cancellationToken) : await _mutex.LockAsync(cancellationToken).ConfigureAwait(false)) { while (Empty && !_completed) { if (sync) { _notEmptyOrCompleted.Wait(cancellationToken); } else { await _notEmptyOrCompleted.WaitAsync(cancellationToken).ConfigureAwait(false); } } cancellationToken.ThrowIfCancellationRequested(); if (AvailableToRead == 0) { return(0); } // Copy the data from the stream var bytesToCopy = Math.Min(count, AvailableToRead); Array.Copy(_data.First.Value, _headDataBytesRead, buffer, offset, bytesToCopy); // Remove those bytes from the stream if (bytesToCopy == AvailableToRead) { _data.RemoveFirst(); _headDataBytesRead = 0; } else { _headDataBytesRead += bytesToCopy; } _currentBytes -= bytesToCopy; ReaderPosition += bytesToCopy; _notFullOrCompleted.Notify(); return(bytesToCopy); } }
private async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool sync) { using (sync ? _mutex.Lock(cancellationToken) : await _mutex.LockAsync(cancellationToken).ConfigureAwait(false)) { while (count != 0) { while (Full && !_completed) { if (sync) { _notFullOrCompleted.Wait(cancellationToken); } else { await _notFullOrCompleted.WaitAsync(cancellationToken).ConfigureAwait(false); } } if (_completed) { throw new OperationCanceledException("Stream has been closed for writing."); } cancellationToken.ThrowIfCancellationRequested(); // Copy the data var bytesToCopy = Math.Min(count, AvailableToWrite); var data = new byte[bytesToCopy]; Array.Copy(buffer, offset, data, 0, bytesToCopy); // Add it to the stream _data.AddLast(data); _currentBytes += bytesToCopy; WriterPosition += bytesToCopy; // Adjust status of current operation offset += bytesToCopy; count -= bytesToCopy; _notEmptyOrCompleted.Notify(); } } }
/// <summary> /// Process status updates in the background /// </summary> /// <returns>Asynchronous task</returns> public static async Task Run() { do { using (await _lock.LockAsync(Program.CancellationToken)) { // Wait for the next object model update await _dataAvailable.WaitAsync(Program.CancellationToken); Program.CancellationToken.ThrowIfCancellationRequested(); // Process it try { ReadOnlyMemory <byte> json = new ReadOnlyMemory <byte>(_json, 0, _jsonLength); using JsonDocument jsonDocument = JsonDocument.Parse(json); if (SPI.DataTransfer.ProtocolVersion == 1) { // This must be a legacy config response used to get the board names if (jsonDocument.RootElement.TryGetProperty("boardName", out JsonElement boardName)) { using (await Provider.AccessReadWriteAsync()) { Provider.Get.Boards.Add(new Board { IapFileNameSBC = $"Duet3_SBCiap_{boardName.GetString()}.bin", FirmwareFileName = $"Duet3Firmware_{boardName.GetString()}.bin" }); } _logger.Warn("Deprecated firmware detected, please update it in order to use DSF"); } else { // boardName field is not present - this must be a really old firmware version using (await Provider.AccessReadWriteAsync()) { Provider.Get.Boards.Add(new Board { IapFileNameSBC = $"Duet3_SDiap_MB6HC.bin", FirmwareFileName = "Duet3Firmware_MB6HC.bin" }); } _logger.Warn("Deprecated firmware detected, assuming legacy firmware files. You may have to use bossa to update it"); } // Cannot perform any further updates... _fullyUpdated.NotifyAll(); // Check if the firmware is supposed to be updated if (Settings.UpdateOnly && !_updatingFirmware) { _updatingFirmware = true; _ = Task.Run(UpdateFirmware); } } else if (jsonDocument.RootElement.TryGetProperty("key", out JsonElement key) && jsonDocument.RootElement.TryGetProperty("result", out JsonElement result)) { // This is a new object model result if (string.IsNullOrWhiteSpace(key.GetString())) { // Standard request to update frequently changing fields using (await Provider.AccessReadWriteAsync()) { Provider.Get.UpdateFromFirmwareModel(string.Empty, result); } // Request limits if no sequence numbers have been set yet if (_lastSeqs.Count == 0) { SPI.Interface.RequestObjectModel("limits", "d99vn"); } // Request object model updates wherever needed bool objectModelSynchronized = true; foreach (JsonProperty seqProperty in result.GetProperty("seqs").EnumerateObject()) { if (seqProperty.Name != "reply" && (!Settings.UpdateOnly || seqProperty.Name == "boards")) { int newSeq = seqProperty.Value.GetInt32(); if (!_lastSeqs.TryGetValue(seqProperty.Name, out int lastSeq) || lastSeq != newSeq) { _logger.Debug("Requesting update of key {0}, seq {1} -> {2}", seqProperty.Name, lastSeq, newSeq); _lastSeqs[seqProperty.Name] = newSeq; SPI.Interface.RequestObjectModel(seqProperty.Name, "d99vn"); objectModelSynchronized = false; } } } // Update the layers UpdateLayers(); if (objectModelSynchronized) { // Notify clients waiting for the machine model to be synchronized _fullyUpdated.NotifyAll(); // Check if the firmware is supposed to be updated if (Settings.UpdateOnly && !_updatingFirmware) { _updatingFirmware = true; _ = Task.Run(UpdateFirmware); } } } else { // Specific request - still updating the OM using (await Provider.AccessReadWriteAsync()) { string keyName = key.GetString(); if (Provider.Get.UpdateFromFirmwareModel(key.GetString(), result)) { _logger.Debug("Updated key {0}", keyName); if (_logger.IsTraceEnabled) { _logger.Trace("Key JSON: {0}", Encoding.UTF8.GetString(_json, 0, _jsonLength)); } } else { _logger.Warn($"Invalid key {key.GetString()} in the object model"); } } } } else { _logger.Warn("Received invalid object model response without key and/or result field(s)"); } } catch (InvalidOperationException e) { _logger.Error(e, "Failed to merge JSON due to internal error: {0}", Encoding.UTF8.GetString(_json, 0, _jsonLength)); } catch (JsonException e) { _logger.Error(e, "Failed to merge JSON: {0}", Encoding.UTF8.GetString(_json, 0, _jsonLength)); } } }while (true); }