500 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			500 lines
		
	
	
		
			15 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;
 | |
|             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);
 | |
|     }
 | |
| }
 |