internal void RegisterChild(IDataflowDependency childMeta, bool allowDuplicate) { var child = childMeta.Unwrap(); if (m_children.Any(cm => object.ReferenceEquals(cm.Unwrap(), child))) { if (allowDuplicate) { LogHelper.Logger.DebugFormat("Duplicate child registration ignored in {0}: {1}", this.FullName, childMeta.DisplayName); return; } else { throw new ArgumentException("Duplicate child to register in " + this.FullName); } } m_children = m_children.Add(childMeta); if (!m_completionTask.IsValueCreated) { //eagerly initialize completion task //would look better if Lazy<T> provides an EagerEvaluate() method var t = m_completionTask.Value; } }
internal void RegisterChild(IDataflowDependency childWrapper, bool allowDuplicate) { if (ImmutableUtils.TryAddOptimistically(ref m_children, childWrapper)) { var dataflowDependency = childWrapper as DataflowDependency; if (dataflowDependency != null) { //add myself as parents ImmutableUtils.AddOptimistically(ref dataflowDependency.Flow.m_parents, this); } } else { if (allowDuplicate) { LogHelper.Logger.DebugFormat( "Duplicate child registration ignored in {0}: {1}", this.FullName, childWrapper.DisplayName); return; } else { throw new ArgumentException("Duplicate child to register in " + this.FullName); } } if (!m_completionTask.IsValueCreated) { //eagerly initialize completion task //would look better if Lazy<T> provides an EagerEvaluate() method var t = m_completionTask.Value; } }
/// <summary> /// Starts the async loop which periodically check the status of the dataflow and its children /// </summary> private async void StartPerformanceMonitorAsync() { try { while (m_children.Count == 0 || !this.Completion.IsCompleted) { if (m_dataflowOptions.FlowMonitorEnabled) { var bufferStatus = this.BufferStatus; if (bufferStatus.Total() != 0 || m_dataflowOptions.PerformanceMonitorMode == DataflowOptions.PerformanceLogMode.Verbose) { LogHelper.PerfMon.Debug(h => h("{0} has {1} todo items (in:{2}, out:{3}) at this moment.", this.FullName, bufferStatus.Total(), bufferStatus.Item1, bufferStatus.Item2)); } } if (m_dataflowOptions.BlockMonitorEnabled) { bool verboseMode = m_dataflowOptions.PerformanceMonitorMode == DataflowOptions.PerformanceLogMode.Verbose; foreach (IDataflowDependency child in m_children) { IDataflowDependency c = child; Tuple <int, int> bufferStatus = c.BufferStatus; if (child.Completion.IsCompleted && verboseMode) { LogHelper.PerfMon.DebugFormat("{0} is completed"); } else if (bufferStatus.Total() != 0 || verboseMode) { LogHelper.PerfMon.Debug(h => h("{0} has {1} todo items (in:{2}, out:{3}) at this moment. ", c.DisplayName, bufferStatus.Total(), bufferStatus.Item1, bufferStatus.Item2)); } } } CustomPerfMonBehavior(); await Task.Delay(m_dataflowOptions.MonitorInterval).ConfigureAwait(false); } } catch (Exception e) { LogHelper.Logger.ErrorFormat("{0} Error occurred in my performance monitor loop. Monitoring stopped.", e, this.FullName); } }
/// <summary> /// Register an external block as dependency, whose completion will trigger completion of this dataflow /// if this dependencies finishes as the last amony all dependencies. /// i.e. Completion of this dataflow will only be triggered after ALL dependencies finish. /// </summary> internal void RegisterDependency(IDataflowDependency dependency) { bool isFirstDependency = m_dependencies.IsEmpty; if (!ImmutableUtils.TryAddOptimistically(ref m_dependencies, dependency)) { LogHelper.Logger.WarnFormat("A dependency registration is ignored by {0} as it is already a dependency: {1}", this.FullName, dependency.DisplayName); } if (isFirstDependency) { TaskEx.AwaitableWhenAll(() => m_dependencies, f => f.Completion).ContinueWith( upstreamTask => { if (!this.CompletionTask.IsCompleted) { if (upstreamTask.IsFaulted) { this.Fault(new LinkedDataflowFailedException()); } else if (upstreamTask.IsCanceled) { this.Fault(new LinkedDataflowCanceledException()); } else { if (m_dependencies.Count > 1) { LogHelper.Logger.InfoFormat("{0} All of my dependencies are done. Completing myself.", this.FullName); } this.Complete(); } } }); } else { LogHelper.Logger.InfoFormat("{0} now has {1} dependencies. (Added {2})", this.FullName, m_dependencies.Count, dependency.DisplayName); } }
/// <summary> /// Register an external block as dependency, whose completion will trigger completion of this dataflow /// if this dependencies finishes as the last amony all dependencies. /// i.e. Completion of this dataflow will only be triggered after ALL dependencies finish. /// </summary> internal void RegisterDependency(IDataflowDependency dependency) { bool isFirstDependency = m_dependencies.IsEmpty; m_dependencies = m_dependencies.Add(dependency); if (isFirstDependency) { TaskEx.AwaitableWhenAll(() => m_dependencies, f => f.Completion).ContinueWith( upstreamTask => { if (!this.Completion.IsCompleted) { if (upstreamTask.IsFaulted) { this.Fault(new LinkedDataflowFailedException()); } else if (upstreamTask.IsCanceled) { this.Fault(new LinkedDataflowCanceledException()); } else { if (m_dependencies.Count > 1) { LogHelper.Logger.InfoFormat("{0} All of my dependencies are done. Completing myself.", this.FullName); } this.Complete(); } } }); } else { LogHelper.Logger.InfoFormat("{0} now has {1} dependencies. (Added {2})", this.FullName, m_dependencies.Count, dependency.DisplayName); } }