// 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
{
///
/// Provides options used to configure the processing performed by dataflow blocks.
///
///
/// is mutable and can be configured through its properties.
/// When specific configuration options are not set, the following defaults are used:
///
///
/// Options
/// Default
///
/// -
/// TaskScheduler
///
///
/// -
/// MaxMessagesPerTask
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// CancellationToken
///
///
/// -
/// BoundedCapacity
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// NameFormat
/// "{0} Id={1}"
///
///
/// Dataflow blocks capture the state of the options at their construction. Subsequent changes
/// to the provided instance should not affect the behavior
/// of a dataflow block.
///
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}")]
public class DataflowBlockOptions
{
///
/// A constant used to specify an unlimited quantity for members
/// that provide an upper bound. This field is constant.
///
public const Int32 Unbounded = -1;
/// The scheduler to use for scheduling tasks to process messages.
private TaskScheduler _taskScheduler = TaskScheduler.Default;
/// The cancellation token to monitor for cancellation requests.
private CancellationToken _cancellationToken = CancellationToken.None;
/// The maximum number of messages that may be processed per task.
private Int32 _maxMessagesPerTask = Unbounded;
/// The maximum number of messages that may be buffered by the block.
private Int32 _boundedCapacity = Unbounded;
/// The name format to use for creating a name for a block.
private string _nameFormat = "{0} Id={1}"; // see NameFormat property for a description of format items
/// A default instance of .
///
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
///
internal static readonly DataflowBlockOptions Default = new DataflowBlockOptions();
/// Returns this instance if it's the default instance or else a cloned instance.
/// An instance of the options that may be cached by the block.
internal DataflowBlockOptions DefaultOrClone()
{
return (this == Default) ?
this :
new DataflowBlockOptions
{
TaskScheduler = this.TaskScheduler,
CancellationToken = this.CancellationToken,
MaxMessagesPerTask = this.MaxMessagesPerTask,
BoundedCapacity = this.BoundedCapacity,
NameFormat = this.NameFormat
};
}
/// Initializes the .
public DataflowBlockOptions() { }
/// Gets or sets the to use for scheduling tasks.
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;
}
}
/// Gets or sets the to monitor for cancellation requests.
public CancellationToken CancellationToken
{
get { return _cancellationToken; }
set
{
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
_cancellationToken = value;
}
}
/// Gets or sets the maximum number of messages that may be processed per task.
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;
}
}
/// Gets a MaxMessagesPerTask value that may be used for comparison purposes.
/// The maximum value, usable for comparison purposes.
/// Unlike MaxMessagesPerTask, this property will always return a positive value.
internal Int32 ActualMaxMessagesPerTask
{
get { return (_maxMessagesPerTask == Unbounded) ? Int32.MaxValue : _maxMessagesPerTask; }
}
/// Gets or sets the maximum number of messages that may be buffered by the block.
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;
}
}
///
/// Gets or sets the format string to use when a block is queried for its name.
///
///
/// 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.
///
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;
}
}
}
///
/// 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 and .
///
///
/// is mutable and can be configured through its properties.
/// When specific configuration options are not set, the following defaults are used:
///
///
/// Options
/// Default
///
/// -
/// TaskScheduler
///
///
/// -
/// CancellationToken
///
///
/// -
/// MaxMessagesPerTask
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// BoundedCapacity
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// NameFormat
/// "{0} Id={1}"
///
/// -
/// MaxDegreeOfParallelism
/// 1
///
/// -
/// SingleProducerConstrained
/// false
///
///
/// Dataflow block captures the state of the options at their construction. Subsequent changes
/// to the provided instance should not affect the behavior
/// of a dataflow block.
///
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}, MaxDegreeOfParallelism = {MaxDegreeOfParallelism}")]
public class ExecutionDataflowBlockOptions : DataflowBlockOptions
{
/// A default instance of .
///
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
///
internal new static readonly ExecutionDataflowBlockOptions Default = new ExecutionDataflowBlockOptions();
/// Returns this instance if it's the default instance or else a cloned instance.
/// An instance of the options that may be cached by the block.
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
};
}
/// The maximum number of tasks that may be used concurrently to process messages.
private Int32 _maxDegreeOfParallelism = 1;
/// Whether the code using this block will only ever have a single producer accessing the block at any given time.
private Boolean _singleProducerConstrained = false;
/// Initializes the .
public ExecutionDataflowBlockOptions() { }
/// Gets the maximum number of messages that may be processed by the block concurrently.
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;
}
}
///
/// Gets whether code using the dataflow block is constrained to one producer at a time.
///
///
/// 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.
///
public Boolean SingleProducerConstrained
{
get { return _singleProducerConstrained; }
set
{
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
_singleProducerConstrained = value;
}
}
/// Gets a MaxDegreeOfParallelism value that may be used for comparison purposes.
/// The maximum value, usable for comparison purposes.
/// Unlike MaxDegreeOfParallelism, this property will always return a positive value.
internal Int32 ActualMaxDegreeOfParallelism
{
get { return (_maxDegreeOfParallelism == Unbounded) ? Int32.MaxValue : _maxDegreeOfParallelism; }
}
/// Gets whether these dataflow block options allow for parallel execution.
internal Boolean SupportsParallelExecution { get { return _maxDegreeOfParallelism == Unbounded || _maxDegreeOfParallelism > 1; } }
}
///
/// Provides options used to configure the processing performed by dataflow blocks that
/// group together multiple messages, blocks such as and
/// .
///
///
/// is mutable and can be configured through its properties.
/// When specific configuration options are not set, the following defaults are used:
///
///
/// Options
/// Default
///
/// -
/// TaskScheduler
///
///
/// -
/// CancellationToken
///
///
/// -
/// MaxMessagesPerTask
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// BoundedCapacity
/// DataflowBlockOptions.Unbounded (-1)
///
/// -
/// NameFormat
/// "{0} Id={1}"
///
/// -
/// MaxNumberOfGroups
/// GroupingDataflowBlockOptions.Unbounded (-1)
///
/// -
/// Greedy
/// true
///
///
/// Dataflow block capture the state of the options at their construction. Subsequent changes
/// to the provided instance should not affect the behavior
/// of a dataflow block.
///
[DebuggerDisplay("TaskScheduler = {TaskScheduler}, MaxMessagesPerTask = {MaxMessagesPerTask}, BoundedCapacity = {BoundedCapacity}, Greedy = {Greedy}, MaxNumberOfGroups = {MaxNumberOfGroups}")]
public class GroupingDataflowBlockOptions : DataflowBlockOptions
{
/// A default instance of .
///
/// Do not change the values of this instance. It is shared by all of our blocks when no options are provided by the user.
///
internal new static readonly GroupingDataflowBlockOptions Default = new GroupingDataflowBlockOptions();
/// Returns this instance if it's the default instance or else a cloned instance.
/// An instance of the options that may be cached by the block.
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
};
}
/// Whether the block should greedily consume offered messages.
private Boolean _greedy = true;
/// The maximum number of groups that should be generated by the block.
private Int64 _maxNumberOfGroups = Unbounded;
/// Initializes the .
public GroupingDataflowBlockOptions() { }
/// Gets or sets the Boolean value to use to determine whether to greedily consume offered messages.
public Boolean Greedy
{
get { return _greedy; }
set
{
Debug.Assert(this != Default, "Default instance is supposed to be immutable.");
_greedy = value;
}
}
/// Gets or sets the maximum number of groups that should be generated by the block.
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;
}
}
/// Gets a MaxNumberOfGroups value that may be used for comparison purposes.
/// The maximum value, usable for comparison purposes.
/// Unlike MaxNumberOfGroups, this property will always return a positive value.
internal Int64 ActualMaxNumberOfGroups
{
get { return (_maxNumberOfGroups == Unbounded) ? Int64.MaxValue : _maxNumberOfGroups; }
}
}
}