Avoid delegate/work item allocations when setting async continuation (#22373)
authorStephen Toub <stoub@microsoft.com>
Sat, 2 Feb 2019 18:31:31 +0000 (13:31 -0500)
committerGitHub <noreply@github.com>
Sat, 2 Feb 2019 18:31:31 +0000 (13:31 -0500)
commita98189a1ac9fbfe462776eed4d99e0cfa883afe6
treee4fa4145d59240615d61d03b8b6d085c457d7bb8
parentc3c07ece61dc18454d0aad985dc7004b9ce63c26
Avoid delegate/work item allocations when setting async continuation (#22373)

When awaiting a task, there's a race between seeing whether the task has completed (in which case we just continue running synchronously), finding the task hasn't completed (in which case we hook up a continuation), and then by the time we try to hook up the continuation finding the task has already completed.  In that final case, we don't want to just execute the callback synchronously, as we risk a stack dive, so we queue it.  That queueing currently entails two allocations in the common case: one for the work item object, and one for the Action delegate we force into existence for the state machine box's MoveNext method (in the common case it's now never allocated because you only await Tasks and ValueTasks known to the runtime, which bypasses its creation).  We can instead just queue the box itself, and avoid both allocations.
src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs