You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
499 lines
15 KiB
499 lines
15 KiB
#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<UniTask>(() => |
|
{ |
|
return new UniTask(new CanceledResultSource(CancellationToken.None), 0); |
|
})(); |
|
|
|
static class CanceledUniTaskCache<T> |
|
{ |
|
public static readonly UniTask<T> Task; |
|
|
|
static CanceledUniTaskCache() |
|
{ |
|
Task = new UniTask<T>(new CanceledResultSource<T>(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<T> FromException<T>(Exception ex) |
|
{ |
|
if (ex is OperationCanceledException oce) |
|
{ |
|
return FromCanceled<T>(oce.CancellationToken); |
|
} |
|
|
|
return new UniTask<T>(new ExceptionResultSource<T>(ex), 0); |
|
} |
|
|
|
public static UniTask<T> FromResult<T>(T value) |
|
{ |
|
return new UniTask<T>(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<T> FromCanceled<T>(CancellationToken cancellationToken = default) |
|
{ |
|
if (cancellationToken == CancellationToken.None) |
|
{ |
|
return CanceledUniTaskCache<T>.Task; |
|
} |
|
else |
|
{ |
|
return new UniTask<T>(new CanceledResultSource<T>(cancellationToken), 0); |
|
} |
|
} |
|
|
|
public static UniTask Create(Func<UniTask> factory) |
|
{ |
|
return factory(); |
|
} |
|
|
|
public static UniTask<T> Create<T>(Func<UniTask<T>> factory) |
|
{ |
|
return factory(); |
|
} |
|
|
|
public static AsyncLazy Lazy(Func<UniTask> factory) |
|
{ |
|
return new AsyncLazy(factory); |
|
} |
|
|
|
public static AsyncLazy<T> Lazy<T>(Func<UniTask<T>> factory) |
|
{ |
|
return new AsyncLazy<T>(factory); |
|
} |
|
|
|
/// <summary> |
|
/// helper of fire and forget void action. |
|
/// </summary> |
|
public static void Void(Func<UniTaskVoid> asyncAction) |
|
{ |
|
asyncAction().Forget(); |
|
} |
|
|
|
/// <summary> |
|
/// helper of fire and forget void action. |
|
/// </summary> |
|
public static void Void(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken) |
|
{ |
|
asyncAction(cancellationToken).Forget(); |
|
} |
|
|
|
/// <summary> |
|
/// helper of fire and forget void action. |
|
/// </summary> |
|
public static void Void<T>(Func<T, UniTaskVoid> asyncAction, T state) |
|
{ |
|
asyncAction(state).Forget(); |
|
} |
|
|
|
/// <summary> |
|
/// helper of create add UniTaskVoid to delegate. |
|
/// For example: FooAction = UniTask.Action(async () => { /* */ }) |
|
/// </summary> |
|
public static Action Action(Func<UniTaskVoid> asyncAction) |
|
{ |
|
return () => asyncAction().Forget(); |
|
} |
|
|
|
/// <summary> |
|
/// helper of create add UniTaskVoid to delegate. |
|
/// </summary> |
|
public static Action Action(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken) |
|
{ |
|
return () => asyncAction(cancellationToken).Forget(); |
|
} |
|
|
|
#if UNITY_2018_3_OR_NEWER |
|
|
|
/// <summary> |
|
/// Create async void(UniTaskVoid) UnityAction. |
|
/// For exampe: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } )) |
|
/// </summary> |
|
public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction) |
|
{ |
|
return () => asyncAction().Forget(); |
|
} |
|
|
|
/// <summary> |
|
/// Create async void(UniTaskVoid) UnityAction. |
|
/// For exampe: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy())) |
|
/// </summary> |
|
public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken) |
|
{ |
|
return () => asyncAction(cancellationToken).Forget(); |
|
} |
|
|
|
#endif |
|
|
|
/// <summary> |
|
/// Defer the task creation just before call await. |
|
/// </summary> |
|
public static UniTask Defer(Func<UniTask> factory) |
|
{ |
|
return new UniTask(new DeferPromise(factory), 0); |
|
} |
|
|
|
/// <summary> |
|
/// Defer the task creation just before call await. |
|
/// </summary> |
|
public static UniTask<T> Defer<T>(Func<UniTask<T>> factory) |
|
{ |
|
return new UniTask<T>(new DeferPromise<T>(factory), 0); |
|
} |
|
|
|
/// <summary> |
|
/// Never complete. |
|
/// </summary> |
|
public static UniTask Never(CancellationToken cancellationToken) |
|
{ |
|
return new UniTask<AsyncUnit>(new NeverPromise<AsyncUnit>(cancellationToken), 0); |
|
} |
|
|
|
/// <summary> |
|
/// Never complete. |
|
/// </summary> |
|
public static UniTask<T> Never<T>(CancellationToken cancellationToken) |
|
{ |
|
return new UniTask<T>(new NeverPromise<T>(cancellationToken), 0); |
|
} |
|
|
|
sealed class ExceptionResultSource : IUniTaskSource |
|
{ |
|
readonly ExceptionDispatchInfo exception; |
|
bool calledGet; |
|
|
|
public ExceptionResultSource(Exception exception) |
|
{ |
|
this.exception = ExceptionDispatchInfo.Capture(exception); |
|
} |
|
|
|
public void GetResult(short token) |
|
{ |
|
if (!calledGet) |
|
{ |
|
calledGet = true; |
|
GC.SuppressFinalize(this); |
|
} |
|
exception.Throw(); |
|
} |
|
|
|
public UniTaskStatus GetStatus(short token) |
|
{ |
|
return UniTaskStatus.Faulted; |
|
} |
|
|
|
public UniTaskStatus UnsafeGetStatus() |
|
{ |
|
return UniTaskStatus.Faulted; |
|
} |
|
|
|
public void OnCompleted(Action<object> continuation, object state, short token) |
|
{ |
|
continuation(state); |
|
} |
|
|
|
~ExceptionResultSource() |
|
{ |
|
if (!calledGet) |
|
{ |
|
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); |
|
} |
|
} |
|
} |
|
|
|
sealed class ExceptionResultSource<T> : IUniTaskSource<T> |
|
{ |
|
readonly ExceptionDispatchInfo exception; |
|
bool calledGet; |
|
|
|
public ExceptionResultSource(Exception exception) |
|
{ |
|
this.exception = ExceptionDispatchInfo.Capture(exception); |
|
} |
|
|
|
public T GetResult(short token) |
|
{ |
|
if (!calledGet) |
|
{ |
|
calledGet = true; |
|
GC.SuppressFinalize(this); |
|
} |
|
exception.Throw(); |
|
return default; |
|
} |
|
|
|
void IUniTaskSource.GetResult(short token) |
|
{ |
|
if (!calledGet) |
|
{ |
|
calledGet = true; |
|
GC.SuppressFinalize(this); |
|
} |
|
exception.Throw(); |
|
} |
|
|
|
public UniTaskStatus GetStatus(short token) |
|
{ |
|
return UniTaskStatus.Faulted; |
|
} |
|
|
|
public UniTaskStatus UnsafeGetStatus() |
|
{ |
|
return UniTaskStatus.Faulted; |
|
} |
|
|
|
public void OnCompleted(Action<object> continuation, object state, short token) |
|
{ |
|
continuation(state); |
|
} |
|
|
|
~ExceptionResultSource() |
|
{ |
|
if (!calledGet) |
|
{ |
|
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); |
|
} |
|
} |
|
} |
|
|
|
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<object> continuation, object state, short token) |
|
{ |
|
continuation(state); |
|
} |
|
} |
|
|
|
sealed class CanceledResultSource<T> : IUniTaskSource<T> |
|
{ |
|
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<object> continuation, object state, short token) |
|
{ |
|
continuation(state); |
|
} |
|
} |
|
|
|
sealed class DeferPromise : IUniTaskSource |
|
{ |
|
Func<UniTask> factory; |
|
UniTask task; |
|
UniTask.Awaiter awaiter; |
|
|
|
public DeferPromise(Func<UniTask> 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<object> continuation, object state, short token) |
|
{ |
|
awaiter.SourceOnCompleted(continuation, state); |
|
} |
|
|
|
public UniTaskStatus UnsafeGetStatus() |
|
{ |
|
return task.Status; |
|
} |
|
} |
|
|
|
sealed class DeferPromise<T> : IUniTaskSource<T> |
|
{ |
|
Func<UniTask<T>> factory; |
|
UniTask<T> task; |
|
UniTask<T>.Awaiter awaiter; |
|
|
|
public DeferPromise(Func<UniTask<T>> 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<object> continuation, object state, short token) |
|
{ |
|
awaiter.SourceOnCompleted(continuation, state); |
|
} |
|
|
|
public UniTaskStatus UnsafeGetStatus() |
|
{ |
|
return task.Status; |
|
} |
|
} |
|
|
|
sealed class NeverPromise<T> : IUniTaskSource<T> |
|
{ |
|
static readonly Action<object> cancellationCallback = CancellationCallback; |
|
|
|
CancellationToken cancellationToken; |
|
UniTaskCompletionSourceCore<T> 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<T>)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<object> 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> AsyncUnit = UniTask.FromResult(Cysharp.Threading.Tasks.AsyncUnit.Default); |
|
public static readonly UniTask<bool> True = UniTask.FromResult(true); |
|
public static readonly UniTask<bool> False = UniTask.FromResult(false); |
|
public static readonly UniTask<int> Zero = UniTask.FromResult(0); |
|
public static readonly UniTask<int> MinusOne = UniTask.FromResult(-1); |
|
public static readonly UniTask<int> One = UniTask.FromResult(1); |
|
} |
|
}
|
|
|