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; }); }
private void CompleteWriting() { using (_mutex.Lock()) { _completed = true; _notFullOrCompleted.NotifyAll(); _notEmptyOrCompleted.NotifyAll(); } }
/// <summary> /// Merge a received object model response /// </summary> /// <param name="json">JSON data</param> public static void ProcessResponse(ReadOnlySpan <byte> json) { using (_lock.Lock(Program.CancellationToken)) { json.CopyTo(_json); _jsonLength = json.Length; _dataAvailable.NotifyAll(); } }
//public ProcessingCollection(IProducerConsumerCollection<T> collection) //{ // _completed = new CancellationTokenSource(); // _mutex = new AsyncLock(); // _cancelled = new CancellationTokenSource(); // _cancelledOrCompleted = CancellationTokenSource.CreateLinkedTokenSource(_cancelled.Token, _completed.Token); // _completedOrIsEmpty = new AsyncConditionVariable(_mutex); // _completedOrNotEmpty = new AsyncConditionVariable(_mutex); // _collection = collection ?? new ConcurrentQueue<T>(); //} public void CompleteAdding() { using (_mutex.Lock()) { if (_completed.IsCancellationRequested) { return; } _completed.Cancel(); _completedOrIsEmpty.NotifyAll(); _completedOrNotEmpty.NotifyAll(); } }
/// <summary> /// Dispose of resources used by the <see cref="K8sMultiplexedReadStream"/>. /// </summary> /// <param name="disposing"> /// Explicit disposal? /// </param> protected override void Dispose(bool disposing) { if (disposing && !IsDisposed) { using (_mutex.Lock()) { IsDisposed = true; _completedOrDataAvailable.NotifyAll(); // Release any tasks that are waiting. // Ensure we don't leak memory. foreach (PendingRead pendingRead in _pendingReads) { pendingRead.Release(); } _pendingReads.Clear(); } } }
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; }
/// <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); }