File: src\runtime\src\libraries\Common\src\System\Threading\Tasks\TaskCompletionSourceWithCancellation.cs
Web Access
Project: src\runtime\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Threading.Tasks
{
    /// <summary>
    /// A <see cref="TaskCompletionSource{TResult}"/> that supports cancellation registration so that any
    /// <seealso cref="OperationCanceledException"/>s contain the relevant <see cref="CancellationToken"/>,
    /// while also avoiding unnecessary allocations for closure captures.
    /// </summary>
    internal class TaskCompletionSourceWithCancellation<T> : TaskCompletionSource<T>
    {
        public TaskCompletionSourceWithCancellation() : base(TaskCreationOptions.RunContinuationsAsynchronously)
        {
        }

        public async ValueTask<T> WaitWithCancellationAsync(CancellationToken cancellationToken)
        {
            using (cancellationToken.UnsafeRegister(static (s, cancellationToken) => ((TaskCompletionSourceWithCancellation<T>)s!).TrySetCanceled(cancellationToken), this))
            {
                return await Task.ConfigureAwait(false);
            }
        }

        public T WaitWithCancellation(CancellationToken cancellationToken)
        {
            using (cancellationToken.UnsafeRegister(static (s, cancellationToken) => ((TaskCompletionSourceWithCancellation<T>)s!).TrySetCanceled(cancellationToken), this))
            {
                return Task.GetAwaiter().GetResult();
            }
        }

        public ValueTask<T> WaitWithCancellationAsync(bool async, CancellationToken cancellationToken)
        {
            return async ?
                WaitWithCancellationAsync(cancellationToken) :
                new ValueTask<T>(WaitWithCancellation(cancellationToken));
        }
    }
}