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();
     }
 }
Example #3
0
 /// <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();
     }
 }
Example #4
0
        //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;
        }
Example #7
0
        /// <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);
        }