#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member using Cysharp.Threading.Tasks.Internal; using System; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Threading; namespace Cysharp.Threading.Tasks { public partial struct UniTask { static readonly UniTask CanceledUniTask = new Func(() => { return new UniTask(new CanceledResultSource(CancellationToken.None), 0); })(); static class CanceledUniTaskCache { public static readonly UniTask Task; static CanceledUniTaskCache() { Task = new UniTask(new CanceledResultSource(CancellationToken.None), 0); } } public static readonly UniTask CompletedTask = new UniTask(); public static UniTask FromException(Exception ex) { if (ex is OperationCanceledException oce) { return FromCanceled(oce.CancellationToken); } return new UniTask(new ExceptionResultSource(ex), 0); } public static UniTask FromException(Exception ex) { if (ex is OperationCanceledException oce) { return FromCanceled(oce.CancellationToken); } return new UniTask(new ExceptionResultSource(ex), 0); } public static UniTask FromResult(T value) { return new UniTask(value); } public static UniTask FromCanceled(CancellationToken cancellationToken = default) { if (cancellationToken == CancellationToken.None) { return CanceledUniTask; } else { return new UniTask(new CanceledResultSource(cancellationToken), 0); } } public static UniTask FromCanceled(CancellationToken cancellationToken = default) { if (cancellationToken == CancellationToken.None) { return CanceledUniTaskCache.Task; } else { return new UniTask(new CanceledResultSource(cancellationToken), 0); } } public static UniTask Create(Func factory) { return factory(); } public static UniTask Create(Func> factory) { return factory(); } public static AsyncLazy Lazy(Func factory) { return new AsyncLazy(factory); } public static AsyncLazy Lazy(Func> factory) { return new AsyncLazy(factory); } /// /// helper of fire and forget void action. /// public static void Void(Func asyncAction) { asyncAction().Forget(); } /// /// helper of fire and forget void action. /// public static void Void(Func asyncAction, CancellationToken cancellationToken) { asyncAction(cancellationToken).Forget(); } /// /// helper of fire and forget void action. /// public static void Void(Func asyncAction, T state) { asyncAction(state).Forget(); } /// /// helper of create add UniTaskVoid to delegate. /// For example: FooAction = UniTask.Action(async () => { /* */ }) /// public static Action Action(Func asyncAction) { return () => asyncAction().Forget(); } /// /// helper of create add UniTaskVoid to delegate. /// public static Action Action(Func asyncAction, CancellationToken cancellationToken) { return () => asyncAction(cancellationToken).Forget(); } #if UNITY_2018_3_OR_NEWER /// /// Create async void(UniTaskVoid) UnityAction. /// For exampe: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } )) /// public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction) { return () => asyncAction().Forget(); } /// /// Create async void(UniTaskVoid) UnityAction. /// For exampe: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy())) /// public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction, CancellationToken cancellationToken) { return () => asyncAction(cancellationToken).Forget(); } #endif /// /// Defer the task creation just before call await. /// public static UniTask Defer(Func factory) { return new UniTask(new DeferPromise(factory), 0); } /// /// Defer the task creation just before call await. /// public static UniTask Defer(Func> factory) { return new UniTask(new DeferPromise(factory), 0); } /// /// Never complete. /// public static UniTask Never(CancellationToken cancellationToken) { return new UniTask(new NeverPromise(cancellationToken), 0); } /// /// Never complete. /// public static UniTask Never(CancellationToken cancellationToken) { return new UniTask(new NeverPromise(cancellationToken), 0); } sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; public ExceptionResultSource(Exception exception) { this.exception = ExceptionDispatchInfo.Capture(exception); } public void GetResult(short token) { exception.Throw(); } public UniTaskStatus GetStatus(short token) { return UniTaskStatus.Faulted; } public UniTaskStatus UnsafeGetStatus() { return UniTaskStatus.Faulted; } public void OnCompleted(Action continuation, object state, short token) { continuation(state); } } sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; public ExceptionResultSource(Exception exception) { this.exception = ExceptionDispatchInfo.Capture(exception); } public T GetResult(short token) { exception.Throw(); return default; } void IUniTaskSource.GetResult(short token) { exception.Throw(); } public UniTaskStatus GetStatus(short token) { return UniTaskStatus.Faulted; } public UniTaskStatus UnsafeGetStatus() { return UniTaskStatus.Faulted; } public void OnCompleted(Action continuation, object state, short token) { continuation(state); } } sealed class CanceledResultSource : IUniTaskSource { readonly CancellationToken cancellationToken; public CanceledResultSource(CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; } public void GetResult(short token) { throw new OperationCanceledException(cancellationToken); } public UniTaskStatus GetStatus(short token) { return UniTaskStatus.Canceled; } public UniTaskStatus UnsafeGetStatus() { return UniTaskStatus.Canceled; } public void OnCompleted(Action continuation, object state, short token) { continuation(state); } } sealed class CanceledResultSource : IUniTaskSource { readonly CancellationToken cancellationToken; public CanceledResultSource(CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; } public T GetResult(short token) { throw new OperationCanceledException(cancellationToken); } void IUniTaskSource.GetResult(short token) { throw new OperationCanceledException(cancellationToken); } public UniTaskStatus GetStatus(short token) { return UniTaskStatus.Canceled; } public UniTaskStatus UnsafeGetStatus() { return UniTaskStatus.Canceled; } public void OnCompleted(Action continuation, object state, short token) { continuation(state); } } sealed class DeferPromise : IUniTaskSource { Func factory; UniTask task; UniTask.Awaiter awaiter; public DeferPromise(Func factory) { this.factory = factory; } public void GetResult(short token) { awaiter.GetResult(); } public UniTaskStatus GetStatus(short token) { var f = Interlocked.Exchange(ref factory, null); if (f != null) { task = f(); awaiter = task.GetAwaiter(); } return task.Status; } public void OnCompleted(Action continuation, object state, short token) { awaiter.SourceOnCompleted(continuation, state); } public UniTaskStatus UnsafeGetStatus() { return task.Status; } } sealed class DeferPromise : IUniTaskSource { Func> factory; UniTask task; UniTask.Awaiter awaiter; public DeferPromise(Func> factory) { this.factory = factory; } public T GetResult(short token) { return awaiter.GetResult(); } void IUniTaskSource.GetResult(short token) { awaiter.GetResult(); } public UniTaskStatus GetStatus(short token) { var f = Interlocked.Exchange(ref factory, null); if (f != null) { task = f(); awaiter = task.GetAwaiter(); } return task.Status; } public void OnCompleted(Action continuation, object state, short token) { awaiter.SourceOnCompleted(continuation, state); } public UniTaskStatus UnsafeGetStatus() { return task.Status; } } sealed class NeverPromise : IUniTaskSource { static readonly Action cancellationCallback = CancellationCallback; CancellationToken cancellationToken; UniTaskCompletionSourceCore core; public NeverPromise(CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; if (this.cancellationToken.CanBeCanceled) { this.cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); } } static void CancellationCallback(object state) { var self = (NeverPromise)state; self.core.TrySetCanceled(self.cancellationToken); } public T GetResult(short token) { return core.GetResult(token); } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCompleted(Action continuation, object state, short token) { core.OnCompleted(continuation, state, token); } void IUniTaskSource.GetResult(short token) { core.GetResult(token); } } } internal static class CompletedTasks { public static readonly UniTask AsyncUnit = UniTask.FromResult(Cysharp.Threading.Tasks.AsyncUnit.Default); public static readonly UniTask True = UniTask.FromResult(true); public static readonly UniTask False = UniTask.FromResult(false); public static readonly UniTask Zero = UniTask.FromResult(0); public static readonly UniTask MinusOne = UniTask.FromResult(-1); public static readonly UniTask One = UniTask.FromResult(1); } }