| /* | |
| Copyright 2020 Google Inc | |
| Licensed under the Apache License, Version 2.0 (the "License"); | |
| you may not use this file except in compliance with the License. | |
| You may obtain a copy of the License at | |
| https://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| namespace Google.Apis.Util | |
| { | |
| // Note: this is duplicated between Google.Apis.Auth and Google.Apis.Core so it can stay internal. Please | |
| // change both at the same time. | |
| internal static class TaskExtensions | |
| { | |
| /// <summary> | |
| /// Returns a task which can be cancelled by the given cancellation token, but otherwise observes the original | |
| /// task's state. This does *not* cancel any work that the original task was doing, and should be used carefully. | |
| /// </summary> | |
| internal static Task<T> WithCancellationToken<T>(this Task<T> task, CancellationToken cancellationToken) | |
| { | |
| if (!cancellationToken.CanBeCanceled) | |
| { | |
| return task; | |
| } | |
| return ImplAsync(); | |
| // Separate async method to allow the above optimization to avoid creating any new state machines etc. | |
| async Task<T> ImplAsync() | |
| { | |
| var cts = new TaskCompletionSource<T>(); | |
| using (cancellationToken.Register(() => cts.TrySetCanceled())) | |
| { | |
| var completedTask = await Task.WhenAny(task, cts.Task).ConfigureAwait(false); | |
| return await completedTask.ConfigureAwait(false); | |
| } | |
| } | |
| } | |
| } | |
| } | |