Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay initialization of Task related properties which are rarely used #45127

Merged
merged 4 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace System.Threading
public sealed class ExecutionContext : IDisposable, ISerializable
{
internal static readonly ExecutionContext Default = new ExecutionContext(isDefault: true);
internal static readonly ExecutionContext DefaultFlowSuppressed = new ExecutionContext(AsyncLocalValueMap.Empty, Array.Empty<IAsyncLocal>(), isFlowSuppressed: true);
private static volatile ExecutionContext? s_defaultFlowSuppressed;

private readonly IAsyncLocalValueMap? m_localValues;
private readonly IAsyncLocal[]? m_localChangeNotifications;
Expand Down Expand Up @@ -88,9 +88,11 @@ public void GetObjectData(SerializationInfo info, StreamingContext context)

if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
{
#pragma warning disable CA1825 // Avoid unnecessary zero-length array allocations
return isFlowSuppressed ?
DefaultFlowSuppressed :
(s_defaultFlowSuppressed ??= new ExecutionContext(AsyncLocalValueMap.Empty, new IAsyncLocal[0], isFlowSuppressed: true)) :
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
null; // implies the default context
#pragma warning restore
marek-safar marked this conversation as resolved.
Show resolved Hide resolved
}

return new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class Task<TResult> : Task
/// <summary>A cached task for default(TResult).</summary>
internal static readonly Task<TResult> s_defaultResultTask = TaskCache.CreateCacheableTask<TResult>(default);

private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>();
private static TaskFactory<TResult>? s_Factory;

// The value itself, if set.
internal TResult? m_result;
Expand Down Expand Up @@ -486,7 +486,10 @@ internal TResult GetResultCore(bool waitCompletionNotification)
/// of <see cref="System.Threading.Tasks.TaskFactory{TResult}"/>, as would result from using
/// the default constructor on the factory type.
/// </remarks>
public static new TaskFactory<TResult> Factory => s_Factory;
public static new TaskFactory<TResult> Factory =>
Volatile.Read(ref s_Factory) ??
Interlocked.CompareExchange(ref s_Factory, new TaskFactory<TResult>(), null) ??
s_Factory;

/// <summary>
/// Evaluates the value selector of the Task which is passed in as an object and stores the result.
Expand Down