<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.TransitionTime.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Tuple.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\TupleSlim.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TupleExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Type.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Type.Enum.cs" />
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
private long m_allKeywordMask; // Match all keyword
- private List<SessionInfo>? m_liveSessions; // current live sessions (Tuple<sessionIdBit, etwSessionId>)
+ private List<SessionInfo>? m_liveSessions; // current live sessions (KeyValuePair<sessionIdBit, etwSessionId>)
private bool m_enabled; // Enabled flag from Trace callback
private string? m_providerName; // Control name
private Guid m_providerId; // Control Guid
m_anyKeywordMask = anyKeyword;
m_allKeywordMask = allKeyword;
- List<Tuple<SessionInfo, bool>> sessionsChanged = GetSessions();
+ List<KeyValuePair<SessionInfo, bool>> sessionsChanged = GetSessions();
// The GetSessions() logic was here to support the idea that different ETW sessions
// could have different user-defined filters. (I believe it is currently broken but that is another matter.)
// All this session based logic should be reviewed and likely removed, but that is a larger
// change that needs more careful staging.
if (sessionsChanged.Count == 0)
- sessionsChanged.Add(new Tuple<SessionInfo, bool>(new SessionInfo(0, 0), true));
+ sessionsChanged.Add(new KeyValuePair<SessionInfo, bool>(new SessionInfo(0, 0), true));
- foreach (Tuple<SessionInfo, bool> session in sessionsChanged)
+ foreach (KeyValuePair<SessionInfo, bool> session in sessionsChanged)
{
- int sessionChanged = session.Item1.sessionIdBit;
- int etwSessionId = session.Item1.etwSessionId;
- bool bEnabling = session.Item2;
+ int sessionChanged = session.Key.sessionIdBit;
+ int etwSessionId = session.Key.etwSessionId;
+ bool bEnabling = session.Value;
skipFinalOnControllerCommand = true;
args = null; // reinitialize args for every session...
/// ETW session that was added or remove, and the bool specifies whether the
/// session was added or whether it was removed from the set.
/// </summary>
- private List<Tuple<SessionInfo, bool>> GetSessions()
+ private List<KeyValuePair<SessionInfo, bool>> GetSessions()
{
List<SessionInfo>? liveSessionList = null;
GetSessionInfoCallback(etwSessionId, matchAllKeywords, ref sessionList),
ref liveSessionList);
- List<Tuple<SessionInfo, bool>> changedSessionList = new List<Tuple<SessionInfo, bool>>();
+ List<KeyValuePair<SessionInfo, bool>> changedSessionList = new List<KeyValuePair<SessionInfo, bool>>();
// first look for sessions that have gone away (or have changed)
// (present in the m_liveSessions but not in the new liveSessionList)
int idx;
if ((idx = IndexOfSessionInList(liveSessionList, s.etwSessionId)) < 0 ||
(liveSessionList![idx].sessionIdBit != s.sessionIdBit))
- changedSessionList.Add(Tuple.Create(s, false));
+ changedSessionList.Add(new KeyValuePair<SessionInfo, bool>(s, false));
}
}
// next look for sessions that were created since the last callback (or have changed)
int idx;
if ((idx = IndexOfSessionInList(m_liveSessions, s.etwSessionId)) < 0 ||
(m_liveSessions![idx].sessionIdBit != s.sessionIdBit))
- changedSessionList.Add(Tuple.Create(s, true));
+ changedSessionList.Add(new KeyValuePair<SessionInfo, bool>(s, true));
}
}
ReadAsync(array.Array!, array.Offset, array.Count) :
Task<int>.Factory.StartNew(static state =>
{
- var t = (Tuple<TextReader, Memory<char>>)state!;
+ var t = (TupleSlim<TextReader, Memory<char>>)state!;
return t.Item1.Read(t.Item2.Span);
- }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
+ }, new TupleSlim<TextReader, Memory<char>>(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
- internal virtual ValueTask<int> ReadAsyncInternal(Memory<char> buffer, CancellationToken cancellationToken)
- {
- var tuple = new Tuple<TextReader, Memory<char>>(this, buffer);
- return new ValueTask<int>(Task<int>.Factory.StartNew(static state =>
+ internal virtual ValueTask<int> ReadAsyncInternal(Memory<char> buffer, CancellationToken cancellationToken) =>
+ new ValueTask<int>(Task<int>.Factory.StartNew(static state =>
{
- var t = (Tuple<TextReader, Memory<char>>)state!;
+ var t = (TupleSlim<TextReader, Memory<char>>)state!;
return t.Item1.Read(t.Item2.Span);
- },
- tuple, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
- }
+ }, new TupleSlim<TextReader, Memory<char>>(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
public virtual Task<int> ReadBlockAsync(char[] buffer, int index, int count)
{
ReadBlockAsync(array.Array!, array.Offset, array.Count) :
Task<int>.Factory.StartNew(static state =>
{
- var t = (Tuple<TextReader, Memory<char>>)state!;
+ var t = (TupleSlim<TextReader, Memory<char>>)state!;
return t.Item1.ReadBlock(t.Item2.Span);
- }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
+ }, new TupleSlim<TextReader, Memory<char>>(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
internal async ValueTask<int> ReadBlockAsyncInternal(Memory<char> buffer, CancellationToken cancellationToken)
{
}
#region Task based Async APIs
- public virtual Task WriteAsync(char value)
- {
- var tuple = new Tuple<TextWriter, char>(this, value);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteAsync(char value) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, char>)state!;
+ var t = (TupleSlim<TextWriter, char>)state!;
t.Item1.Write(t.Item2);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, char>(this, value), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- public virtual Task WriteAsync(string? value)
- {
- var tuple = new Tuple<TextWriter, string?>(this, value);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteAsync(string? value) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, string?>)state!;
+ var t = (TupleSlim<TextWriter, string?>)state!;
t.Item1.Write(t.Item2);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, string?>(this, value), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
/// <summary>
/// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
return WriteAsync(buffer, 0, buffer.Length);
}
- public virtual Task WriteAsync(char[] buffer, int index, int count)
- {
- var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteAsync(char[] buffer, int index, int count) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, char[], int, int>)state!;
+ var t = (TupleSlim<TextWriter, char[], int, int>)state!;
t.Item1.Write(t.Item2, t.Item3, t.Item4);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, char[], int, int>(this, buffer, index, count), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
WriteAsync(array.Array!, array.Offset, array.Count) :
Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!;
+ var t = (TupleSlim<TextWriter, ReadOnlyMemory<char>>)state!;
t.Item1.Write(t.Item2.Span);
- }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }, new TupleSlim<TextWriter, ReadOnlyMemory<char>>(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- public virtual Task WriteLineAsync(char value)
- {
- var tuple = new Tuple<TextWriter, char>(this, value);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteLineAsync(char value) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, char>)state!;
+ var t = (TupleSlim<TextWriter, char>)state!;
t.Item1.WriteLine(t.Item2);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, char>(this, value), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- public virtual Task WriteLineAsync(string? value)
- {
- var tuple = new Tuple<TextWriter, string?>(this, value);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteLineAsync(string? value) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, string?>)state!;
+ var t = (TupleSlim<TextWriter, string?>)state!;
t.Item1.WriteLine(t.Item2);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, string?>(this, value), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
/// <summary>
/// Equivalent to WriteLineAsync(stringBuilder.ToString()) however it uses the
return WriteLineAsync(buffer, 0, buffer.Length);
}
- public virtual Task WriteLineAsync(char[] buffer, int index, int count)
- {
- var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
- return Task.Factory.StartNew(static state =>
+ public virtual Task WriteLineAsync(char[] buffer, int index, int count) =>
+ Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, char[], int, int>)state!;
+ var t = (TupleSlim<TextWriter, char[], int, int>)state!;
t.Item1.WriteLine(t.Item2, t.Item3, t.Item4);
- },
- tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ }, new TupleSlim<TextWriter, char[], int, int>(this, buffer, index, count), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
WriteLineAsync(array.Array!, array.Offset, array.Count) :
Task.Factory.StartNew(static state =>
{
- var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!;
+ var t = (TupleSlim<TextWriter, ReadOnlyMemory<char>>)state!;
t.Item1.WriteLine(t.Item2.Span);
- }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }, new TupleSlim<TextWriter, ReadOnlyMemory<char>>(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
public virtual Task WriteLineAsync()
{
// this work with a callback mechanism will add additional cost to other more common cases.
return new ValueTask(Task.Factory.StartNew(static s =>
{
- Debug.Assert(s is Tuple<CancellationTokenSource, long>);
- var state = (Tuple<CancellationTokenSource, long>)s;
+ var state = (TupleSlim<CancellationTokenSource, long>)s!;
state.Item1.WaitForCallbackToComplete(state.Item2);
- }, Tuple.Create(this, id), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
+ }, new TupleSlim<CancellationTokenSource, long>(this, id), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
}
private sealed class Linked1CancellationTokenSource : CancellationTokenSource
/// A scheduler shim used to queue tasks to the pair and execute those tasks on request of the pair.
/// </summary>
[DebuggerDisplay("Count={CountForDebugger}, MaxConcurrencyLevel={m_maxConcurrencyLevel}, Id={Id}")]
- [DebuggerTypeProxy(typeof(ConcurrentExclusiveTaskScheduler.DebugView))]
+ [DebuggerTypeProxy(typeof(DebugView))]
private sealed class ConcurrentExclusiveTaskScheduler : TaskScheduler
{
- /// <summary>Cached delegate for invoking TryExecuteTaskShim.</summary>
- private static readonly Func<object?, bool> s_tryExecuteTaskShim = new Func<object?, bool>(TryExecuteTaskShim);
/// <summary>The parent pair.</summary>
private readonly ConcurrentExclusiveSchedulerPair m_pair;
/// <summary>The maximum concurrency level for the scheduler.</summary>
// is able to invoke the task, which might account for an additional but unavoidable delay.
// Once it's done, we can return whether the task executed by returning the
// shim task's Result, which is in turn the result of TryExecuteTask.
- var t = new Task<bool>(s_tryExecuteTaskShim, Tuple.Create(this, task));
+ var t = new Task<bool>(s =>
+ {
+ var tuple = (TupleSlim<ConcurrentExclusiveTaskScheduler, Task>)s!;
+ return tuple.Item1.TryExecuteTask(tuple.Item2);
+ }, new TupleSlim<ConcurrentExclusiveTaskScheduler, Task>(this, task));
try
{
t.RunSynchronously(m_pair.m_underlyingTaskScheduler);
finally { t.Dispose(); }
}
- /// <summary>Shim used to invoke this.TryExecuteTask(task).</summary>
- /// <param name="state">A tuple of the ConcurrentExclusiveTaskScheduler and the task to execute.</param>
- /// <returns>true if the task was successfully inlined; otherwise, false.</returns>
- /// <remarks>
- /// This method is separated out not because of performance reasons but so that
- /// the SecuritySafeCritical attribute may be employed.
- /// </remarks>
- private static bool TryExecuteTaskShim(object? state)
- {
- Debug.Assert(state is Tuple<ConcurrentExclusiveTaskScheduler, Task>);
- var tuple = (Tuple<ConcurrentExclusiveTaskScheduler, Task>)state;
- return tuple.Item1.TryExecuteTask(tuple.Item2);
- }
-
/// <summary>Gets for debugging purposes the tasks scheduled to this scheduler.</summary>
/// <returns>An enumerable of the tasks queued.</returns>
protected override IEnumerable<Task> GetScheduledTasks() { return m_tasks; }
case SynchronizationContext sc:
sc.Post(static s =>
{
- var tuple = (Tuple<Action<object?>, object?>)s!;
+ var tuple = (TupleSlim<Action<object?>, object?>)s!;
tuple.Item1(tuple.Item2);
- }, Tuple.Create(continuation, state));
+ }, new TupleSlim<Action<object?>, object?>(continuation, state));
break;
case TaskScheduler ts:
case SynchronizationContext sc:
sc.Post(static s =>
{
- var state = (Tuple<Action<object?>, object?>)s!;
+ var state = (TupleSlim<Action<object?>, object?>)s!;
state.Item1(state.Item2);
- }, Tuple.Create(_continuation, _continuationState));
+ }, new TupleSlim<Action<object?>, object?>(_continuation, _continuationState));
break;
case TaskScheduler ts:
// antecedent.RemoveCancellation(continuation) can be invoked.
ctr = cancellationToken.UnsafeRegister(static t =>
{
- var tuple = (Tuple<Task, Task, TaskContinuation>)t!;
+ var tuple = (TupleSlim<Task, Task, TaskContinuation>)t!;
Task targetTask = tuple.Item1;
Task antecedentTask = tuple.Item2;
antecedentTask.RemoveContinuation(tuple.Item3);
targetTask.InternalCancel();
- },
- new Tuple<Task, Task, TaskContinuation>(this, antecedent, continuation));
+ }, new TupleSlim<Task, Task, TaskContinuation>(this, antecedent, continuation));
}
props.m_cancellationRegistration = new StrongBox<CancellationTokenRegistration>(ctr);
ThreadPool.UnsafeQueueUserWorkItem(static state =>
{
// InvokeCore(completingTask);
- var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!;
+ var tuple = (TupleSlim<UnwrapPromise<TResult>, Task>)state!;
tuple.Item1.InvokeCore(tuple.Item2);
- }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
+ }, new TupleSlim<UnwrapPromise<TResult>, Task>(this, completingTask));
}
/// <summary>Processes the outer task once it's completed.</summary>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System
+{
+ /// <summary>Simple alternative to <see cref="Tuple{T1, T2}"/> for use in corelib.</summary>
+ /// <remarks>Exists to avoid the unnecessary size increase that may come from Tuple's additional surface area.</remarks>
+ internal sealed class TupleSlim<T1, T2>
+ {
+ public readonly T1 Item1;
+ public readonly T2 Item2;
+
+ public TupleSlim(T1 item1, T2 item2)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ }
+ }
+
+ /// <summary>Simple alternative to <see cref="Tuple{T1, T2, T3}"/> for use in corelib.</summary>
+ /// <remarks>Exists to avoid the unnecessary size increase that may come from Tuple's additional surface area.</remarks>
+ internal sealed class TupleSlim<T1, T2, T3>
+ {
+ public readonly T1 Item1;
+ public readonly T2 Item2;
+ public readonly T3 Item3;
+
+ public TupleSlim(T1 item1, T2 item2, T3 item3)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ }
+ }
+
+ /// <summary>Simple alternative to <see cref="Tuple{T1, T2, T3, T4}"/> for use in corelib.</summary>
+ /// <remarks>Exists to avoid the unnecessary size increase that may come from Tuple's additional surface area.</remarks>
+ internal sealed class TupleSlim<T1, T2, T3, T4>
+ {
+ public readonly T1 Item1;
+ public readonly T2 Item2;
+ public readonly T3 Item3;
+ public readonly T4 Item4;
+
+ public TupleSlim(T1 item1, T2 item2, T3 item3, T4 item4)
+ {
+ Item1 = item1;
+ Item2 = item2;
+ Item3 = item3;
+ Item4 = item4;
+ }
+ }
+}