You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -0,0 +1 @@
|
||||
a083e9d9bebedacd697da65dcdcec0bf21c9666d
|
||||
@@ -0,0 +1,414 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// DataflowBlockOptions.cs
|
||||
//
|
||||
//
|
||||
// DataflowBlockOptions types for configuring dataflow blocks
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides options used to configure the processing performed by dataflow blocks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="DataflowBlockOptions"/> is mutable and can be configured through its properties.
|
||||
/// When specific configuration options are not set, the following defaults are used:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Options</term>
|
||||
/// <description>Default</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>TaskScheduler</term>
|
||||
/// <description><see cref="System.Threading.Tasks.TaskScheduler.Default"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxMessagesPerTask</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>CancellationToken</term>
|
||||
/// <description><see cref="System.Threading.CancellationToken.None"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>BoundedCapacity</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>NameFormat</term>
|
||||
/// <description>"{0} Id={1}"</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Dataflow blocks capture the state of the options at their construction. Subsequent changes
|
||||
/// to the provided <see cref="DataflowBlockOptions"/> instance should not affect the behavior
|
||||
/// of a dataflow block.
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}")]
|
||||
public class DataflowBlockOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// A constant used to specify an unlimited quantity for <see cref="DataflowBlockOptions"/> members
|
||||
/// that provide an upper bound. This field is constant.
|
||||
/// </summary>
|
||||
public const Int32 Unbounded = -1;
|
||||
|
||||
/// <summary>The scheduler to use for scheduling tasks to process messages.</summary>
|
||||
private TaskScheduler _taskScheduler = TaskScheduler.Default;
|
||||
/// <summary>The cancellation token to monitor for cancellation requests.</summary>
|
||||
private CancellationToken _cancellationToken = CancellationToken.None;
|
||||
/// <summary>The maximum number of messages that may be processed per task.</summary>
|
||||
private Int32 _maxMessagesPerTask = Unbounded;
|
||||
/// <summary>The maximum number of messages that may be buffered by the block.</summary>
|
||||
private Int32 _boundedCapacity = Unbounded;
|
||||
/// <summary>The name format to use for creating a name for a block.</summary>
|
||||
private string _nameFormat = "{0} Id={1}"; // see NameFormat property for a description of format items
|
||||
|
||||
/// <summary>A default instance of <see cref="DataflowBlockOptions"/>.</summary>
|
||||
/// <remarks>
|
||||
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
|
||||
/// </remarks>
|
||||
internal static readonly DataflowBlockOptions Default = new DataflowBlockOptions();
|
||||
|
||||
/// <summary>Returns this <see cref="DataflowBlockOptions"/> instance if it's the default instance or else a cloned instance.</summary>
|
||||
/// <returns>An instance of the options that may be cached by the block.</returns>
|
||||
internal DataflowBlockOptions DefaultOrClone()
|
||||
{
|
||||
return (this == Default) ?
|
||||
this :
|
||||
new DataflowBlockOptions
|
||||
{
|
||||
TaskScheduler = this.TaskScheduler,
|
||||
CancellationToken = this.CancellationToken,
|
||||
MaxMessagesPerTask = this.MaxMessagesPerTask,
|
||||
BoundedCapacity = this.BoundedCapacity,
|
||||
NameFormat = this.NameFormat
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Initializes the <see cref="DataflowBlockOptions"/>.</summary>
|
||||
public DataflowBlockOptions() { }
|
||||
|
||||
/// <summary>Gets or sets the <see cref="System.Threading.Tasks.TaskScheduler"/> to use for scheduling tasks.</summary>
|
||||
public TaskScheduler TaskScheduler
|
||||
{
|
||||
get { return _taskScheduler; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value == null) throw new ArgumentNullException("value");
|
||||
_taskScheduler = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the <see cref="System.Threading.CancellationToken"/> to monitor for cancellation requests.</summary>
|
||||
public CancellationToken CancellationToken
|
||||
{
|
||||
get { return _cancellationToken; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
_cancellationToken = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the maximum number of messages that may be processed per task.</summary>
|
||||
public Int32 MaxMessagesPerTask
|
||||
{
|
||||
get { return _maxMessagesPerTask; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value < 1 && value != Unbounded) throw new ArgumentOutOfRangeException("value");
|
||||
_maxMessagesPerTask = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets a MaxMessagesPerTask value that may be used for comparison purposes.</summary>
|
||||
/// <returns>The maximum value, usable for comparison purposes.</returns>
|
||||
/// <remarks>Unlike MaxMessagesPerTask, this property will always return a positive value.</remarks>
|
||||
internal Int32 ActualMaxMessagesPerTask
|
||||
{
|
||||
get { return (_maxMessagesPerTask == Unbounded) ? Int32.MaxValue : _maxMessagesPerTask; }
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the maximum number of messages that may be buffered by the block.</summary>
|
||||
public Int32 BoundedCapacity
|
||||
{
|
||||
get { return _boundedCapacity; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value < 1 && value != Unbounded) throw new ArgumentOutOfRangeException("value");
|
||||
_boundedCapacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string to use when a block is queried for its name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The name format may contain up to two format items. {0} will be substituted
|
||||
/// with the block's name. {1} will be substituted with the block's Id, as is
|
||||
/// returned from the block's Completion.Id property.
|
||||
/// </remarks>
|
||||
public string NameFormat
|
||||
{
|
||||
get { return _nameFormat; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value == null) throw new ArgumentNullException("value");
|
||||
_nameFormat = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides options used to configure the processing performed by dataflow blocks that
|
||||
/// process each message through the invocation of a user-provided delegate, blocks such
|
||||
/// as <see cref="ActionBlock{T}"/> and <see cref="TransformBlock{TInput,TOutput}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="ExecutionDataflowBlockOptions"/> is mutable and can be configured through its properties.
|
||||
/// When specific configuration options are not set, the following defaults are used:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Options</term>
|
||||
/// <description>Default</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>TaskScheduler</term>
|
||||
/// <description><see cref="System.Threading.Tasks.TaskScheduler.Default"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>CancellationToken</term>
|
||||
/// <description><see cref="System.Threading.CancellationToken.None"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxMessagesPerTask</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>BoundedCapacity</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>NameFormat</term>
|
||||
/// <description>"{0} Id={1}"</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxDegreeOfParallelism</term>
|
||||
/// <description>1</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>SingleProducerConstrained</term>
|
||||
/// <description>false</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Dataflow block captures the state of the options at their construction. Subsequent changes
|
||||
/// to the provided <see cref="ExecutionDataflowBlockOptions"/> instance should not affect the behavior
|
||||
/// of a dataflow block.
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}, MaxDegreeOfParallelism = {MaxDegreeOfParallelism}")]
|
||||
public class ExecutionDataflowBlockOptions : DataflowBlockOptions
|
||||
{
|
||||
/// <summary>A default instance of <see cref="DataflowBlockOptions"/>.</summary>
|
||||
/// <remarks>
|
||||
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
|
||||
/// </remarks>
|
||||
internal new static readonly ExecutionDataflowBlockOptions Default = new ExecutionDataflowBlockOptions();
|
||||
|
||||
/// <summary>Returns this <see cref="ExecutionDataflowBlockOptions"/> instance if it's the default instance or else a cloned instance.</summary>
|
||||
/// <returns>An instance of the options that may be cached by the block.</returns>
|
||||
internal new ExecutionDataflowBlockOptions DefaultOrClone()
|
||||
{
|
||||
return (this == Default) ?
|
||||
this :
|
||||
new ExecutionDataflowBlockOptions
|
||||
{
|
||||
TaskScheduler = this.TaskScheduler,
|
||||
CancellationToken = this.CancellationToken,
|
||||
MaxMessagesPerTask = this.MaxMessagesPerTask,
|
||||
BoundedCapacity = this.BoundedCapacity,
|
||||
NameFormat = this.NameFormat,
|
||||
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
|
||||
SingleProducerConstrained = this.SingleProducerConstrained
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>The maximum number of tasks that may be used concurrently to process messages.</summary>
|
||||
private Int32 _maxDegreeOfParallelism = 1;
|
||||
/// <summary>Whether the code using this block will only ever have a single producer accessing the block at any given time.</summary>
|
||||
private Boolean _singleProducerConstrained = false;
|
||||
|
||||
/// <summary>Initializes the <see cref="ExecutionDataflowBlockOptions"/>.</summary>
|
||||
public ExecutionDataflowBlockOptions() { }
|
||||
|
||||
/// <summary>Gets the maximum number of messages that may be processed by the block concurrently.</summary>
|
||||
public Int32 MaxDegreeOfParallelism
|
||||
{
|
||||
get { return _maxDegreeOfParallelism; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value < 1 && value != Unbounded) throw new ArgumentOutOfRangeException("value");
|
||||
_maxDegreeOfParallelism = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether code using the dataflow block is constrained to one producer at a time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property defaults to false, such that the block may be used by multiple
|
||||
/// producers concurrently. This property should only be set to true if the code
|
||||
/// using the block can guarantee that it will only ever be used by one producer
|
||||
/// (e.g. a source linked to the block) at a time, meaning that methods like Post,
|
||||
/// Complete, Fault, and OfferMessage will never be called concurrently. Some blocks
|
||||
/// may choose to capitalize on the knowledge that there will only be one producer at a time
|
||||
/// in order to provide better performance.
|
||||
/// </remarks>
|
||||
public Boolean SingleProducerConstrained
|
||||
{
|
||||
get { return _singleProducerConstrained; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
_singleProducerConstrained = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets a MaxDegreeOfParallelism value that may be used for comparison purposes.</summary>
|
||||
/// <returns>The maximum value, usable for comparison purposes.</returns>
|
||||
/// <remarks>Unlike MaxDegreeOfParallelism, this property will always return a positive value.</remarks>
|
||||
internal Int32 ActualMaxDegreeOfParallelism
|
||||
{
|
||||
get { return (_maxDegreeOfParallelism == Unbounded) ? Int32.MaxValue : _maxDegreeOfParallelism; }
|
||||
}
|
||||
|
||||
/// <summary>Gets whether these dataflow block options allow for parallel execution.</summary>
|
||||
internal Boolean SupportsParallelExecution { get { return _maxDegreeOfParallelism == Unbounded || _maxDegreeOfParallelism > 1; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides options used to configure the processing performed by dataflow blocks that
|
||||
/// group together multiple messages, blocks such as <see cref="JoinBlock{T1,T2}"/> and
|
||||
/// <see cref="BatchBlock{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="GroupingDataflowBlockOptions"/> is mutable and can be configured through its properties.
|
||||
/// When specific configuration options are not set, the following defaults are used:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Options</term>
|
||||
/// <description>Default</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>TaskScheduler</term>
|
||||
/// <description><see cref="System.Threading.Tasks.TaskScheduler.Default"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>CancellationToken</term>
|
||||
/// <description><see cref="System.Threading.CancellationToken.None"/></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxMessagesPerTask</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>BoundedCapacity</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>NameFormat</term>
|
||||
/// <description>"{0} Id={1}"</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxNumberOfGroups</term>
|
||||
/// <description>GroupingDataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Greedy</term>
|
||||
/// <description>true</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Dataflow block capture the state of the options at their construction. Subsequent changes
|
||||
/// to the provided <see cref="GroupingDataflowBlockOptions"/> instance should not affect the behavior
|
||||
/// of a dataflow block.
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}, Greedy = {Greedy}, MaxNumberOfGroups = {MaxNumberOfGroups}")]
|
||||
public class GroupingDataflowBlockOptions : DataflowBlockOptions
|
||||
{
|
||||
/// <summary>A default instance of <see cref="DataflowBlockOptions"/>.</summary>
|
||||
/// <remarks>
|
||||
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
|
||||
/// </remarks>
|
||||
internal new static readonly GroupingDataflowBlockOptions Default = new GroupingDataflowBlockOptions();
|
||||
|
||||
/// <summary>Returns this <see cref="GroupingDataflowBlockOptions"/> instance if it's the default instance or else a cloned instance.</summary>
|
||||
/// <returns>An instance of the options that may be cached by the block.</returns>
|
||||
internal new GroupingDataflowBlockOptions DefaultOrClone()
|
||||
{
|
||||
return (this == Default) ?
|
||||
this :
|
||||
new GroupingDataflowBlockOptions
|
||||
{
|
||||
TaskScheduler = this.TaskScheduler,
|
||||
CancellationToken = this.CancellationToken,
|
||||
MaxMessagesPerTask = this.MaxMessagesPerTask,
|
||||
BoundedCapacity = this.BoundedCapacity,
|
||||
NameFormat = this.NameFormat,
|
||||
Greedy = this.Greedy,
|
||||
MaxNumberOfGroups = this.MaxNumberOfGroups
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Whether the block should greedily consume offered messages.</summary>
|
||||
private Boolean _greedy = true;
|
||||
/// <summary>The maximum number of groups that should be generated by the block.</summary>
|
||||
private Int64 _maxNumberOfGroups = Unbounded;
|
||||
|
||||
/// <summary>Initializes the <see cref="GroupingDataflowBlockOptions"/>.</summary>
|
||||
public GroupingDataflowBlockOptions() { }
|
||||
|
||||
/// <summary>Gets or sets the Boolean value to use to determine whether to greedily consume offered messages.</summary>
|
||||
public Boolean Greedy
|
||||
{
|
||||
get { return _greedy; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
_greedy = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the maximum number of groups that should be generated by the block.</summary>
|
||||
public Int64 MaxNumberOfGroups
|
||||
{
|
||||
get { return _maxNumberOfGroups; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
|
||||
if (value <= 0 && value != Unbounded) throw new ArgumentOutOfRangeException("value");
|
||||
_maxNumberOfGroups = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets a MaxNumberOfGroups value that may be used for comparison purposes.</summary>
|
||||
/// <returns>The maximum value, usable for comparison purposes.</returns>
|
||||
/// <remarks>Unlike MaxNumberOfGroups, this property will always return a positive value.</remarks>
|
||||
internal Int64 ActualMaxNumberOfGroups
|
||||
{
|
||||
get { return (_maxNumberOfGroups == Unbounded) ? Int64.MaxValue : _maxNumberOfGroups; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// DataflowLinkOptions.cs
|
||||
//
|
||||
//
|
||||
// DataflowLinkOptions type for configuring links between dataflow blocks
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides options used to configure a link between dataflow blocks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="DataflowLinkOptions"/> is mutable and can be configured through its properties.
|
||||
/// When specific configuration options are not set, the following defaults are used:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Options</term>
|
||||
/// <description>Default</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>PropagateCompletion</term>
|
||||
/// <description>False</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>MaxMessages</term>
|
||||
/// <description>DataflowBlockOptions.Unbounded (-1)</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Append</term>
|
||||
/// <description>True</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Dataflow blocks capture the state of the options at linking. Subsequent changes to the provided
|
||||
/// <see cref="DataflowLinkOptions"/> instance should not affect the behavior of a link.
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("PropagateCompletion = {PropagateCompletion}, MaxMessages = {MaxMessages}, Append = {Append}")]
|
||||
public class DataflowLinkOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// A constant used to specify an unlimited quantity for <see cref="DataflowLinkOptions"/> members
|
||||
/// that provide an upper bound. This field is a constant tied to <see cref="DataflowLinkOptions.Unbounded"/>.
|
||||
/// </summary>
|
||||
internal const Int32 Unbounded = DataflowBlockOptions.Unbounded;
|
||||
|
||||
/// <summary>Whether the linked target will have completion and faulting notification propagated to it automatically.</summary>
|
||||
private Boolean _propagateCompletion = false;
|
||||
/// <summary>The maximum number of messages that may be consumed across the link.</summary>
|
||||
private Int32 _maxNumberOfMessages = Unbounded;
|
||||
/// <summary>Whether the link should be appended to the source’s list of links, or whether it should be prepended.</summary>
|
||||
private Boolean _append = true;
|
||||
|
||||
/// <summary>A default instance of <see cref="DataflowLinkOptions"/>.</summary>
|
||||
/// <remarks>
|
||||
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
|
||||
/// </remarks>
|
||||
internal static readonly DataflowLinkOptions Default = new DataflowLinkOptions();
|
||||
|
||||
/// <summary>A cached instance of <see cref="DataflowLinkOptions"/>.</summary>
|
||||
/// <remarks>
|
||||
/// Do not change the values of this instance. It is shared by all of our blocks that need to unlink after one message has been consumed.
|
||||
/// </remarks>
|
||||
internal static readonly DataflowLinkOptions UnlinkAfterOneAndPropagateCompletion = new DataflowLinkOptions() { MaxMessages = 1, PropagateCompletion = true };
|
||||
|
||||
/// <summary>Initializes the <see cref="DataflowLinkOptions"/>.</summary>
|
||||
public DataflowLinkOptions()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets whether the linked target will have completion and faulting notification propagated to it automatically.</summary>
|
||||
public Boolean PropagateCompletion
|
||||
{
|
||||
get { return _propagateCompletion; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default && this != UnlinkAfterOneAndPropagateCompletion, "Default and UnlinkAfterOneAndPropagateCompletion instances are supposed to be immutable.");
|
||||
_propagateCompletion = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the maximum number of messages that may be consumed across the link.</summary>
|
||||
public Int32 MaxMessages
|
||||
{
|
||||
get { return _maxNumberOfMessages; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default && this != UnlinkAfterOneAndPropagateCompletion, "Default and UnlinkAfterOneAndPropagateCompletion instances are supposed to be immutable.");
|
||||
if (value < 1 && value != Unbounded) throw new ArgumentOutOfRangeException("value");
|
||||
_maxNumberOfMessages = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets whether the link should be appended to the source’s list of links, or whether it should be prepended.</summary>
|
||||
public Boolean Append
|
||||
{
|
||||
get { return _append; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(this != Default && this != UnlinkAfterOneAndPropagateCompletion, "Default and UnlinkAfterOneAndPropagateCompletion instances are supposed to be immutable.");
|
||||
_append = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// DataflowMessageHeader.cs
|
||||
//
|
||||
//
|
||||
// A container of data attributes passed between dataflow blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Threading.Tasks.Dataflow.Internal;
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Provides a container of data attributes for passing between dataflow blocks.</summary>
|
||||
[DebuggerDisplay("Id = {Id}")]
|
||||
public struct DataflowMessageHeader : IEquatable<DataflowMessageHeader>
|
||||
{
|
||||
/// <summary>The message ID. Needs to be unique within the source.</summary>
|
||||
private readonly long _id;
|
||||
|
||||
/// <summary>Initializes the <see cref="DataflowMessageHeader"/> with the specified attributes.</summary>
|
||||
/// <param name="id">The ID of the message. Must be unique within the originating source block. Need not be globally unique.</param>
|
||||
public DataflowMessageHeader(Int64 id)
|
||||
{
|
||||
if (id == default(long)) throw new ArgumentException(SR.Argument_InvalidMessageId, "id");
|
||||
Contract.EndContractBlock();
|
||||
|
||||
_id = id;
|
||||
}
|
||||
|
||||
/// <summary>Gets the validity of the message.</summary>
|
||||
/// <returns>True if the ID of the message is different from 0. False if the ID of the message is 0</returns>
|
||||
public Boolean IsValid { get { return _id != default(long); } }
|
||||
|
||||
/// <summary>Gets the ID of the message within the source.</summary>
|
||||
/// <returns>The ID contained in the <see cref="DataflowMessageHeader"/> instance.</returns>
|
||||
public Int64 Id { get { return _id; } }
|
||||
|
||||
// These overrides are required by the FX API Guidelines.
|
||||
// NOTE: When these overrides are present, the compiler doesn't complain about statements
|
||||
// like 'if (struct == null) ...' which will result in incorrect behavior at runtime.
|
||||
// The product code should not use them. Instead, it should compare the Id properties.
|
||||
// To verify that, every once in a while, comment out this region and build the product.
|
||||
#region Comparison Operators
|
||||
/// <summary>Checks two <see cref="DataflowMessageHeader"/> instances for equality by ID without boxing.</summary>
|
||||
/// <param name="other">Another <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <returns>True if the instances are equal. False otherwise.</returns>
|
||||
public bool Equals(DataflowMessageHeader other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
/// <summary>Checks boxed <see cref="DataflowMessageHeader"/> instances for equality by ID.</summary>
|
||||
/// <param name="obj">A boxed <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <returns>True if the instances are equal. False otherwise.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is DataflowMessageHeader && this == (DataflowMessageHeader)obj;
|
||||
}
|
||||
|
||||
/// <summary>Generates a hash code for the <see cref="DataflowMessageHeader"/> instance.</summary>
|
||||
/// <returns>Hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)Id;
|
||||
}
|
||||
|
||||
/// <summary>Checks two <see cref="DataflowMessageHeader"/> instances for equality by ID.</summary>
|
||||
/// <param name="left">A <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <param name="right">A <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <returns>True if the instances are equal. False otherwise.</returns>
|
||||
public static bool operator ==(DataflowMessageHeader left, DataflowMessageHeader right)
|
||||
{
|
||||
return left.Id == right.Id;
|
||||
}
|
||||
|
||||
/// <summary>Checks two <see cref="DataflowMessageHeader"/> instances for non-equality by ID.</summary>
|
||||
/// <param name="left">A <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <param name="right">A <see cref="DataflowMessageHeader"/> instance.</param>
|
||||
/// <returns>True if the instances are not equal. False otherwise.</returns>
|
||||
public static bool operator !=(DataflowMessageHeader left, DataflowMessageHeader right)
|
||||
{
|
||||
return left.Id != right.Id;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// DataflowMessageStatus.cs
|
||||
//
|
||||
//
|
||||
// Status about the propagation of a message.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents the status of a <see cref="DataflowMessageHeader"/> when passed between dataflow blocks.</summary>
|
||||
public enum DataflowMessageStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="ITargetBlock{TInput}"/> accepted the message. Once a target has accepted a message,
|
||||
/// it is wholly owned by the target.
|
||||
/// </summary>
|
||||
Accepted = 0x0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="ITargetBlock{TInput}"/> declined the message. The <see cref="ISourceBlock{TOutput}"/> still owns the message.
|
||||
/// </summary>
|
||||
Declined = 0x1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="ITargetBlock{TInput}"/> postponed the message for potential consumption at a later time.
|
||||
/// The <see cref="ISourceBlock{TOutput}"/> still owns the message.
|
||||
/// </summary>
|
||||
Postponed = 0x2,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="ITargetBlock{TInput}"/> tried to accept the message from the <see cref="ISourceBlock{TOutput}"/>, but the
|
||||
/// message was no longer available.
|
||||
/// </summary>
|
||||
NotAvailable = 0x3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="ITargetBlock{TInput}"/> declined the message. The <see cref="ISourceBlock{TOutput}"/> still owns the message.
|
||||
/// Additionally, the <see cref="ITargetBlock{TInput}"/> will decline all future messages sent by the source.
|
||||
/// </summary>
|
||||
DecliningPermanently = 0x4
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// IDataflowBlock.cs
|
||||
//
|
||||
//
|
||||
// The base interface for all dataflow blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents a dataflow block.</summary>
|
||||
public interface IDataflowBlock
|
||||
{
|
||||
// IMPLEMENT IMPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Blocks/Member[@name="Completion"]/*' />
|
||||
Task Completion { get; }
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Blocks/Member[@name="Complete"]/*' />
|
||||
void Complete();
|
||||
|
||||
// IMPLEMENT EXPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Blocks/Member[@name="Fault"]/*' />
|
||||
void Fault(Exception exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// IPropagatorBlock.cs
|
||||
//
|
||||
//
|
||||
// The base interface for all propagator blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents a dataflow block that is both a target for data and a source of data.</summary>
|
||||
/// <typeparam name="TInput">Specifies the type of data accepted by the <see cref="IPropagatorBlock{TInput,TOutput}"/>.</typeparam>
|
||||
/// <typeparam name="TOutput">Specifies the type of data supplied by the <see cref="IPropagatorBlock{TInput,TOutput}"/>.</typeparam>
|
||||
public interface IPropagatorBlock<in TInput, out TOutput> : ITargetBlock<TInput>, ISourceBlock<TOutput>
|
||||
{
|
||||
// No additional members beyond those inherited from ITargetBlock<TInput> and ISourceBlock<TOutput>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// IReceivableSourceBlock.cs
|
||||
//
|
||||
//
|
||||
// The base interface for all source blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents a dataflow block that supports receiving of messages without linking.</summary>
|
||||
/// <typeparam name="TOutput">Specifies the type of data supplied by the <see cref="IReceivableSourceBlock{TOutput}"/>.</typeparam>
|
||||
public interface IReceivableSourceBlock<TOutput> : ISourceBlock<TOutput>
|
||||
{
|
||||
// IMPLEMENT IMPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="TryReceive"]/*' />
|
||||
bool TryReceive(Predicate<TOutput> filter, out TOutput item);
|
||||
|
||||
// IMPLEMENT IMPLICITLY IF BLOCK SUPPORTS RECEIVING MORE THAN ONE ITEM, OTHERWISE EXPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="TryReceiveAll"]/*' />
|
||||
bool TryReceiveAll(out IList<TOutput> items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// ISourceBlock.cs
|
||||
//
|
||||
//
|
||||
// The base interface for all source blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents a dataflow block that is a source of data.</summary>
|
||||
/// <typeparam name="TOutput">Specifies the type of data supplied by the <see cref="ISourceBlock{TOutput}"/>.</typeparam>
|
||||
public interface ISourceBlock<out TOutput> : IDataflowBlock
|
||||
{
|
||||
// IMPLEMENT IMPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="LinkTo"]/*' />
|
||||
IDisposable LinkTo(ITargetBlock<TOutput> target, DataflowLinkOptions linkOptions);
|
||||
|
||||
// IMPLEMENT EXPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="ConsumeMessage"]/*' />
|
||||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#")]
|
||||
TOutput ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target, out Boolean messageConsumed);
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="ReserveMessage"]/*' />
|
||||
Boolean ReserveMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target);
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Sources/Member[@name="ReleaseReservation"]/*' />
|
||||
void ReleaseReservation(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
//
|
||||
// ITargetBlock.cs
|
||||
//
|
||||
//
|
||||
// The base interface for all target blocks.
|
||||
//
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
namespace System.Threading.Tasks.Dataflow
|
||||
{
|
||||
/// <summary>Represents a dataflow block that is a target for data.</summary>
|
||||
/// <typeparam name="TInput">Specifies the type of data accepted by the <see cref="ITargetBlock{TInput}"/>.</typeparam>
|
||||
public interface ITargetBlock<in TInput> : IDataflowBlock
|
||||
{
|
||||
// IMPLEMENT EXPLICITLY
|
||||
|
||||
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Targets/Member[@name="OfferMessage"]/*' />
|
||||
DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock<TInput> source, Boolean consumeToAccept);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user