// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable enable using System; using System.Threading; using System.Threading.Tasks; namespace osu.Game.Utils { /// /// A chain of s that run sequentially. /// public class TaskChain { private readonly object currentTaskLock = new object(); private Task? currentTask; /// /// Adds a new task to the end of this . /// /// The action to be executed. /// The for this task. Does not affect further tasks in the chain. /// The awaitable . public Task Add(Action action, CancellationToken cancellationToken = default) { lock (currentTaskLock) { // Note: Attaching the cancellation token to the continuation could lead to re-ordering of tasks in the chain. // Therefore, the cancellation token is not used to cancel the continuation but only the run of each task. if (currentTask == null) { currentTask = Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); action(); }, CancellationToken.None); } else { currentTask = currentTask.ContinueWith(_ => { cancellationToken.ThrowIfCancellationRequested(); action(); }, CancellationToken.None); } return currentTask; } } } }