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> /// Register a cancellation token source which will be signaled to external components /// if this dataflow runs into error. (Useful to terminate input stream to the dataflow /// together with PullFromAsync) /// </summary> public void RegisterCancellationTokenSource(CancellationTokenSource cts) { ImmutableUtils.AddOptimistically(ref m_ctsList, cts); if (m_children.Count != 0) { } }
/// <summary> /// Link the copied data stream to another block /// </summary> private void LinkCopyTo(IDataflow <T> other) { //first, create a new copy block Dataflow <T, T> copyBuffer = new BufferBlock <T>(m_dataflowOptions.ToGroupingBlockOption()).ToDataflow(m_dataflowOptions); RegisterChild(copyBuffer); copyBuffer.RegisterDependency(m_transformBlock); var afterAdd = ImmutableUtils.AddOptimistically(ref m_copyBuffers, copyBuffer); copyBuffer.Name = "Buffer" + afterAdd.Count; copyBuffer.LinkTo(other); }
/// <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 a post dataflow job, which will be executed and awaited after all children of the dataflow is done. /// The gived job effects the completion task of the dataflow /// </summary> /// <param name="postDataflowTask"></param> public void RegisterPostDataflowTask(Func <Task> postDataflowTask) { ImmutableUtils.AddOptimistically(ref m_postDataflowTasks, postDataflowTask); }