コード例 #1
0
        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;
            });
        }
コード例 #2
0
        /// <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();
            }
        }
コード例 #3
0
    public async Task DoSomethingAsync()
    {
        using (await _mutex.LockAsync())
        {
            DoSomeWork();
            await _cv.WaitAsync();

            DoMoreWork();
        }
    }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
        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);
            });
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        //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);
            }
        }
コード例 #11
0
        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;
        }
コード例 #12
0
        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();
            }
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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;
        }
コード例 #15
0
        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);
        }
コード例 #16
0
        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);
            }
        }
コード例 #17
0
        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;
        }
コード例 #18
0
        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);
            }
        }
コード例 #19
0
        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();
                }
            }
        }
コード例 #20
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);
        }