/// <summary> /// Process a config response (no longer supported or encouraged; for backwards-compatibility) /// </summary> /// <param name="response">Legacy config response</param> /// <returns>Asynchronous task</returns> public static async Task ProcessLegacyConfigResponse(byte[] response) { using JsonDocument jsonDocument = JsonDocument.Parse(response); using (await _monitor.EnterAsync(Program.CancellationToken)) { 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... _monitor.PulseAll(); // Check if the firmware is supposed to be updated if (Settings.UpdateOnly && !_updatingFirmware) { _updatingFirmware = true; _ = Task.Run(UpdateFirmware); } } }
/// <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 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 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 async Task <IPipelineStatus> AddJobs(IPipelineRunManager pipelineRunManager, IEnumerable <BuildJob> jobs, int buildNum, CancellationToken cancellationToken) { var dependentJobs = new HashSet <BuildJob>(); var jobMap = new Dictionary <BuildJob, IJobStatus>(); var runnableJobs = new List <RunnableJob>(); foreach (var job in jobs) { AddBuildJob(pipelineRunManager, job, runnableJobs, dependentJobs, jobMap); } var jobIds = new HashSet <string>(jobMap.Count); foreach (var buildJob in jobMap.Keys) { if (!jobIds.Add(buildJob.Id)) { throw new Exception("Duplicate job id."); } } runnableJobs.Reverse(); using (await monitor.EnterAsync(cancellationToken)) { foreach (var jobRun in runnableJobs) { await jobRun.Status.WriteBuildJobFile(); jobQueue.AddLast(jobRun); } monitor.PulseAll(); } return(new PipelineStatus( new ReadOnlyDictionary <string, IJobStatus>(jobMap.ToDictionary(kvp => kvp.Key.Id, kvp => kvp.Value)), buildNum, pipelineRunManager.PipelineDir )); }
/// <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); }
public void ProcessIncoming(Message msg, NetworkConnection conn, WeakReference <NetworkConnection> connWeak) { IDisposable monitor = null; try { monitor = m_monitor.Enter(); IDisposable monitorToUnlock; Message.MsgType type = msg.Type; SequenceNumber seqNum; Entry entry; uint id; switch (type) { case KeepAlive: break; // ignore case ClientHello: case ProtoUnsup: case ServerHelloDone: case ServerHello: case ClientHelloDone: // shouldn't get these, but ignore if we do break; case EntryAssign: { id = msg.Id; string name = msg.Str; bool mayNeedUpdate = false; if (m_server) { if (id == 0xffff) { if (m_entries.ContainsKey(name)) { return; } id = (uint)m_idMap.Count; entry = new Entry(name) { Value = msg.Val, Flags = (EntryFlags)msg.Flags, Id = id }; m_entries[name] = entry; m_idMap.Add(entry); if (entry.IsPersistent()) { m_persistentDirty = true; } m_notifier.NotifyEntry(name, entry.Value, NotifyFlags.NotifyNew); if (m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; var outMsg = Message.EntryAssign(name, id, entry.SeqNum.Value, msg.Val, (EntryFlags)msg.Flags); monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(outMsg, null, null); } return; } if (id >= m_idMap.Count || m_idMap[(int)id] == null) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("server: received assignment to unknown entry"); return; } entry = m_idMap[(int)id]; } else { if (id == 0xffff) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("client: received entry assignment request?"); return; } if (id >= m_idMap.Count) { ResizeIdMap(id + 1); } entry = m_idMap[(int)id]; if (entry == null) { Entry newEntry; if (!m_entries.ContainsKey(name)) { //Entry didn't exist at all. newEntry = new Entry(name) { Value = msg.Val, Flags = (EntryFlags)msg.Flags, Id = id }; m_idMap[(int)id] = newEntry; m_entries[name] = newEntry; m_notifier.NotifyEntry(name, newEntry.Value, NotifyFlags.NotifyNew); return; } else { newEntry = m_entries[name]; } mayNeedUpdate = true; entry = newEntry; entry.Id = id; m_idMap[(int)id] = entry; if ((EntryFlags)msg.Flags != entry.Flags) { var queueOutgoing = m_queueOutgoing; var outmsg = Message.FlagsUpdate(id, entry.Flags); monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(outmsg, null, null); Interlocked.Exchange(ref monitor, m_monitor.Enter()); } } } seqNum = new SequenceNumber(msg.SeqNumUid); if (seqNum < entry.SeqNum) { if (mayNeedUpdate) { var queueOutgoing = m_queueOutgoing; var outmsg = Message.EntryUpdate(entry.Id, entry.SeqNum.Value, entry.Value); monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(outmsg, null, null); } return; } //Sanity check. Name should match id if (msg.Str != entry.Name) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("entry assignment for same id with different name?"); return; } NotifyFlags notifyFlags = NotifyFlags.NotifyUpdate; if (!mayNeedUpdate && conn.ProtoRev >= 0x0300) { if ((entry.Flags & EntryFlags.Persistent) != ((EntryFlags)msg.Flags & EntryFlags.Persistent)) { m_persistentDirty = true; } if (entry.Flags != (EntryFlags)msg.Flags) { notifyFlags |= NotifyFlags.NotifyFlagsChanged; } entry.Flags = (EntryFlags)msg.Flags; } if (entry.IsPersistent() && entry.Value != msg.Val) { m_persistentDirty = true; } entry.Value = msg.Val; entry.SeqNum = seqNum; m_notifier.NotifyEntry(name, entry.Value, notifyFlags); if (m_server && m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; var outmsg = Message.EntryAssign(entry.Name, id, msg.SeqNumUid, msg.Val, entry.Flags); monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(outmsg, null, conn); } break; } case EntryUpdate: id = msg.Id; if (id >= m_idMap.Count || m_idMap[(int)id] == null) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("received update to unknown entyr"); return; } entry = m_idMap[(int)id]; seqNum = new SequenceNumber(msg.SeqNumUid); if (seqNum <= entry.SeqNum) { return; } entry.Value = msg.Val; entry.SeqNum = seqNum; if (entry.IsPersistent()) { m_persistentDirty = true; } m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyUpdate); if (m_server && m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(msg, null, conn); } break; case FlagsUpdate: { id = msg.Id; if (id >= m_idMap.Count || m_idMap[(int)id] == null) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("reeived flags update to unknown entry"); return; } entry = m_idMap[(int)id]; if (entry.Flags == (EntryFlags)msg.Flags) { return; } if ((entry.Flags & EntryFlags.Persistent) != ((EntryFlags)msg.Flags & EntryFlags.Persistent)) { m_persistentDirty = true; } entry.Flags = (EntryFlags)msg.Flags; m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyFlagsChanged); if (m_server && m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(msg, null, conn); } break; } case EntryDelete: { id = msg.Id; if (id >= m_idMap.Count || m_idMap[(int)id] == null) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("received delete to unknown entry"); return; } entry = m_idMap[(int)id]; if (entry.IsPersistent()) { m_persistentDirty = true; } m_idMap[(int)id] = null; if (m_entries.TryGetValue(entry.Name, out entry)) { m_entries.Remove(entry.Name); m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyDelete); } if (m_server && m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(msg, null, conn); } break; } case ClearEntries: { DeleteAllEntriesImpl(); if (m_server && m_queueOutgoing != null) { var queueOutgoing = m_queueOutgoing; monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); queueOutgoing(msg, null, conn); } break; } case ExecuteRpc: if (!m_server) { return; } id = msg.Id; if (id >= m_idMap.Count || m_idMap[(int)id] == null) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("received RPC call to unknown entry"); return; } entry = m_idMap[(int)id]; if (!entry.Value.IsRpc()) { monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); Debug("received RPC call to non-RPC entry"); return; } m_rpcServer.ProcessRpc(entry.Name, msg, entry.RpcCallback, conn.Uid, message => { NetworkConnection c; connWeak.TryGetTarget(out c); if (c != null && !c.Disposed) { c.QueueOutgoing(message); } }); break; case RpcResponse: if (m_server) { return; } if (!msg.Val.IsRpc()) { return; //Not an RPC message } m_rpcResults.Add(new ImmutablePair <uint, uint>(msg.Id, msg.SeqNumUid), msg.Val.GetRpc()); m_monitor.PulseAll(); break; } } finally { monitor?.Dispose(); } }