You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
467 lines
14 KiB
C#
467 lines
14 KiB
C#
#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;
|
|
|
|
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<object> continuation, object state, short token)
|
|
{
|
|
continuation(state);
|
|
}
|
|
}
|
|
|
|
sealed class ExceptionResultSource<T> : IUniTaskSource<T>
|
|
{
|
|
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<object> 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<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);
|
|
}
|
|
}
|