From a945cd1e25f563f7826d057bc7e9098d8e129711 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 5 May 2019 18:45:38 +0100 Subject: [PATCH 1/3] Use same Task for Task.CompletedTask and ATMB.Completed --- .../Runtime/CompilerServices/AsyncMethodBuilder.cs | 13 ++++--------- .../shared/System/Threading/Tasks/Task.cs | 3 ++- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index fb6f2197c06a..54ab38e89b7a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -191,13 +191,6 @@ private void NotifySynchronizationContextOfCompletion() /// public struct AsyncTaskMethodBuilder { - /// A cached VoidTaskResult task used for builders that complete synchronously. -#if PROJECTN - private static readonly Task s_cachedCompleted = AsyncTaskCache.CreateCacheableTask(default(VoidTaskResult)); -#else - private static readonly Task s_cachedCompleted = AsyncTaskMethodBuilder.s_defaultResultTask; -#endif - /// The generic builder object to which this non-generic instance delegates. private AsyncTaskMethodBuilder m_builder; // mutable struct: must not be readonly. Debugger depends on the exact name of this field. @@ -270,7 +263,7 @@ public Task Task /// /// The builder is not initialized. /// The task has already completed. - public void SetResult() => m_builder.SetResult(s_cachedCompleted); // Using s_cachedCompleted is faster than using s_defaultResultTask. + public void SetResult() => m_builder.SetResult(Task.s_cachedCompleted); // Using s_cachedCompleted is faster than using s_defaultResultTask via generic. /// /// Completes the in the @@ -315,7 +308,9 @@ public struct AsyncTaskMethodBuilder { #if !PROJECTN /// A cached task for default(TResult). - internal readonly static Task s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC + internal readonly static Task s_defaultResultTask = (null != (object)default(TResult)! && typeof(TResult) == typeof(VoidTaskResult)) ? + (Task)(object)System.Threading.Tasks.Task.s_cachedCompleted : // Non-generic Task + AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC #endif /// The lazily-initialized built task. diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs index 2c35214248ff..507d9a9ba250 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @@ -1497,8 +1497,9 @@ bool IAsyncResult.CompletedSynchronously /// public static TaskFactory Factory { get; } = new TaskFactory(); + internal static readonly Task s_cachedCompleted = new Task(false, default, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default); /// Gets a task that's already been completed successfully. - public static Task CompletedTask { get; } = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default); + public static Task CompletedTask { get; } = s_cachedCompleted; /// /// Provides an event that can be used to wait for completion. From 0a62c8283accb84dc07acb3373b75c5e7d8790fb Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 6 May 2019 15:27:06 +0100 Subject: [PATCH 2/3] Feedback --- .../shared/System/Threading/Tasks/Task.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs index 507d9a9ba250..9d4fcffbbf0b 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @@ -1497,9 +1497,10 @@ bool IAsyncResult.CompletedSynchronously /// public static TaskFactory Factory { get; } = new TaskFactory(); + // Is a Task{VoidTaskResult} so it can be shared with AsyncTaskMethodBuilder internal static readonly Task s_cachedCompleted = new Task(false, default, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default); /// Gets a task that's already been completed successfully. - public static Task CompletedTask { get; } = s_cachedCompleted; + public static Task CompletedTask => s_cachedCompleted; /// /// Provides an event that can be used to wait for completion. From 12b0a79afddcb8a7092c03b577d13862fd834c7b Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 6 May 2019 16:35:59 +0100 Subject: [PATCH 3/3] Feedback 2 --- .../System/Runtime/CompilerServices/AsyncMethodBuilder.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index 54ab38e89b7a..8118cfd2b5e9 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -308,9 +308,7 @@ public struct AsyncTaskMethodBuilder { #if !PROJECTN /// A cached task for default(TResult). - internal readonly static Task s_defaultResultTask = (null != (object)default(TResult)! && typeof(TResult) == typeof(VoidTaskResult)) ? - (Task)(object)System.Threading.Tasks.Task.s_cachedCompleted : // Non-generic Task - AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC + internal readonly static Task s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC #endif /// The lazily-initialized built task.