T | IUniTaskSource

master
Yoshifumi Kawai 2020-04-18 22:11:40 +09:00
parent 2ccaf0a03b
commit b2d3423a33
5 changed files with 275 additions and 329 deletions

View File

@ -40,10 +40,10 @@ public class SandboxMain : MonoBehaviour
ucs = new UniTaskCompletionSource2();
okButton.onClick.AddListener(UniTask.VoidUnityAction(async () =>
okButton.onClick.AddListener(async () =>
{
await OuterAsync(true);
}));
await InnerAsync(false);
});
cancelButton.onClick.AddListener(async () =>
{
@ -84,7 +84,8 @@ public class SandboxMain : MonoBehaviour
}
else
{
//UnityEngine.Debug.Log("Empty END");
UnityEngine.Debug.Log("Empty END");
throw new InvalidOperationException("FOOBARBAZ");
}
}

View File

@ -298,10 +298,17 @@ namespace UniRx.Async.CompilerServices
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (promise == null)
if (promise != null)
{
promise = AutoResetUniTaskCompletionSource.Create();
return promise.Task;
}
if (runner == null)
{
return UniTask2.CompletedTask;
}
promise = AutoResetUniTaskCompletionSource.Create();
return promise.Task;
}
}
@ -317,11 +324,14 @@ namespace UniRx.Async.CompilerServices
runner = null;
}
if (promise == null)
if (promise != null)
{
promise = AutoResetUniTaskCompletionSource.Create();
promise.SetException(exception);
}
else
{
promise = AutoResetUniTaskCompletionSource.CreateFromException(exception, out _);
}
promise.SetException(exception);
}
// 4. SetResult
@ -335,11 +345,10 @@ namespace UniRx.Async.CompilerServices
runner = null;
}
if (promise == null)
if (promise != null)
{
promise = AutoResetUniTaskCompletionSource.Create();
promise.SetResult();
}
promise.SetResult();
}
// 5. AwaitOnCompleted
@ -401,6 +410,7 @@ namespace UniRx.Async.CompilerServices
// cache items.
AutoResetUniTaskCompletionSource<T> promise;
IMoveNextRunner runner;
T result;
// 1. Static Create method.
[DebuggerHidden]
@ -416,10 +426,17 @@ namespace UniRx.Async.CompilerServices
{
get
{
if (promise == null)
if (promise != null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
return promise.Task;
}
if (runner == null)
{
return UniTask2.FromResult(result);
}
promise = AutoResetUniTaskCompletionSource<T>.Create();
return promise.Task;
}
}
@ -437,9 +454,12 @@ namespace UniRx.Async.CompilerServices
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
promise = AutoResetUniTaskCompletionSource<T>.CreateFromException(exception, out _);
}
else
{
promise.SetException(exception);
}
promise.SetException(exception);
}
// 4. SetResult
@ -455,8 +475,10 @@ namespace UniRx.Async.CompilerServices
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
this.result = result;
return;
}
promise.SetResult(result);
}

View File

@ -128,5 +128,18 @@ namespace UniRx.Async
public static readonly UniTask<int> MinusOne = UniTask.FromResult(-1);
public static readonly UniTask<int> One = UniTask.FromResult(1);
}
internal static class CompletedTasks2
{
public static readonly UniTask2 Completed = new UniTask2();
public static readonly UniTask2<AsyncUnit> AsyncUnit = UniTask2.FromResult(UniRx.Async.AsyncUnit.Default);
public static readonly UniTask2<bool> True = UniTask2.FromResult(true);
public static readonly UniTask2<bool> False = UniTask2.FromResult(false);
public static readonly UniTask2<int> Zero = UniTask2.FromResult(0);
public static readonly UniTask2<int> MinusOne = UniTask2.FromResult(-1);
public static readonly UniTask2<int> One = UniTask2.FromResult(1);
}
}
#endif

View File

@ -29,9 +29,17 @@ namespace UniRx.Async
//return new ValueTask<int>(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token);
}
public static readonly UniTask2 CompletedTask = new UniTask2();
public static UniTask2<T> FromResult<T>(T result)
{
return new UniTask2<T>(result);
}
}
public class DelayPromiseCore2 : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem
{
static readonly PromisePool<DelayPromiseCore2> pool = new PromisePool<DelayPromiseCore2>();
@ -70,6 +78,7 @@ namespace UniRx.Async
{
try
{
TaskTracker2.RemoveTracking(this);
core.GetResult(token);
}
finally
@ -97,14 +106,12 @@ namespace UniRx.Async
{
if (cancellationToken.IsCancellationRequested)
{
TaskTracker2.RemoveTracking(this);
core.SetCancellation(cancellationToken);
return false;
}
if (currentFrameCount == delayFrameCount)
{
TaskTracker2.RemoveTracking(this);
core.SetResult(null);
return false;
}
@ -126,25 +133,30 @@ namespace UniRx.Async
internal static class AwaiterActions
{
internal static readonly Action<object> InvokeActionDelegate = InvokeAction;
static void InvokeAction(object state)
{
((Action)state).Invoke();
}
}
/// <summary>
/// Lightweight unity specified task-like object.
/// </summary>
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2
public partial struct UniTask2
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))]
public readonly partial struct UniTask2
{
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
readonly IUniTaskSource awaiter;
readonly IUniTaskSource source;
readonly short token;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UniTask2(IUniTaskSource awaiter, short token)
public UniTask2(IUniTaskSource source, short token)
{
this.awaiter = awaiter;
this.source = source;
this.token = token;
}
@ -154,7 +166,8 @@ namespace UniRx.Async
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return awaiter.GetStatus(token);
if (source == null) return AwaiterStatus.Succeeded;
return source.GetStatus(token);
}
}
@ -165,154 +178,112 @@ namespace UniRx.Async
return new Awaiter(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void GetResult()
/// <summary>
/// returns (bool IsCanceled) instead of throws OperationCanceledException.
/// </summary>
public UniTask2<bool> SuppressCancellationThrow()
{
awaiter.GetResult(token);
var status = Status;
if (status == AwaiterStatus.Succeeded) return CompletedTasks2.False;
if (status == AwaiterStatus.Canceled) return CompletedTasks2.True;
return new UniTask2<bool>(new IsCanceledSource(source), token);
}
// TODO:can be suppress?
///// <summary>
///// returns (bool IsCanceled) instead of throws OperationCanceledException.
///// </summary>
//public UniTask<bool> SuppressCancellationThrow()
//{
// var status = Status;
// if (status == AwaiterStatus.Succeeded) return CompletedTasks.False;
// if (status == AwaiterStatus.Canceled) return CompletedTasks.True;
// //return new UniTask<bool>(new IsCanceledAwaiter(awaiter));
//}
public override string ToString()
{
var status = this.awaiter.UnsafeGetStatus();
return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")";
if (source == null) return "()";
return "(" + source.UnsafeGetStatus() + ")";
}
//public static implicit operator UniTask<AsyncUnit>(UniTask2 task)
//{
// // TODO:
// throw new NotImplementedException();
// TODO:AsTask???
// //if (task.awaiter != null)
// //{
// // if (task.awaiter.IsCompleted)
// // {
// // return DefaultAsyncUnitTask;
// // }
// // else
// // {
// // // UniTask<T> -> UniTask is free but UniTask -> UniTask<T> requires wrapping cost.
// // return new UniTask<AsyncUnit>(new AsyncUnitAwaiter(task.awaiter));
// // }
// //}
// //else
// //{
// // return DefaultAsyncUnitTask;
// //}
//}
//class AsyncUnitAwaiter : IAwaiter<AsyncUnit>
//{
// readonly IAwaiter2 awaiter;
// public AsyncUnitAwaiter(IAwaiter2 awaiter)
// {
// this.awaiter = awaiter;
// }
// public bool IsCompleted => awaiter.IsCompleted;
// public AwaiterStatus Status => awaiter.Status;
// public AsyncUnit GetResult()
// {
// awaiter.GetResult();
// return AsyncUnit.Default;
// }
// public void OnCompleted(Action continuation)
// {
// awaiter.OnCompleted(continuation);
// }
// public void UnsafeOnCompleted(Action continuation)
// {
// awaiter.UnsafeOnCompleted(continuation);
// }
// void IAwaiter.GetResult()
// {
// awaiter.GetResult();
// }
//}
class IsCanceledAwaiter : IUniTaskSource
public static implicit operator UniTask2<AsyncUnit>(UniTask2 task)
{
readonly IUniTaskSource awaiter;
if (task.source == null) return CompletedTasks2.AsyncUnit;
public IsCanceledAwaiter(IUniTaskSource awaiter)
var status = task.source.GetStatus(task.token);
if (status.IsCompletedSuccessfully())
{
this.awaiter = awaiter;
return CompletedTasks2.AsyncUnit;
}
//public bool IsCompleted => awaiter.IsCompleted;
return new UniTask2<AsyncUnit>(new AsyncUnitSource(task.source), task.token);
}
//public AwaiterStatus Status => awaiter.Status;
class AsyncUnitSource : IUniTaskSource<AsyncUnit>
{
readonly IUniTaskSource source;
//public bool GetResult()
//{
// if (awaiter.Status == AwaiterStatus.Canceled)
// {
// return true;
// }
// awaiter.GetResult();
// return false;
//}
//public void OnCompleted(Action continuation)
//{
// awaiter.OnCompleted(continuation);
//}
//public void UnsafeOnCompleted(Action continuation)
//{
// awaiter.UnsafeOnCompleted(continuation);
//}
//void IAwaiter.GetResult()
//{
// awaiter.GetResult();
//}
public void GetResult(short token)
public AsyncUnitSource(IUniTaskSource source)
{
// TODO: bool
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
{
//return true;
}
this.source = source;
}
awaiter.GetResult(token);
// return false
throw new NotImplementedException();
public AsyncUnit GetResult(short token)
{
source.GetResult(token);
return AsyncUnit.Default;
}
public AwaiterStatus GetStatus(short token)
{
return awaiter.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return awaiter.UnsafeGetStatus();
return source.GetStatus(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
awaiter.OnCompleted(continuation, state, token);
source.OnCompleted(continuation, state, token);
}
public AwaiterStatus UnsafeGetStatus()
{
return source.UnsafeGetStatus();
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
}
class IsCanceledSource : IUniTaskSource<bool>
{
readonly IUniTaskSource source;
public IsCanceledSource(IUniTaskSource source)
{
this.source = source;
}
public bool GetResult(short token)
{
if (source.GetStatus(token) == AwaiterStatus.Canceled)
{
return true;
}
source.GetResult(token);
return false;
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public AwaiterStatus GetStatus(short token)
{
return source.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return source.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
source.OnCompleted(continuation, state, token);
}
}
@ -337,69 +308,70 @@ namespace UniRx.Async
}
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status;
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void GetResult()
{
task.GetResult();
if (task.source == null) return;
task.source.GetResult(task.token);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
if (task.source == null)
{
continuation();
}
else
{
task.source.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnsafeOnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
if (task.source == null)
{
continuation();
}
else
{
task.source.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
}
}
internal static class AwaiterActions
{
internal static readonly Action<object> InvokeActionDelegate = InvokeAction;
static void InvokeAction(object state)
{
((Action)state).Invoke();
}
}
/// <summary>
/// Lightweight unity specified task-like object.
/// </summary>
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2~T
public struct UniTask2<T>
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder<>))]
public readonly struct UniTask2<T>
{
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
readonly IUniTaskSource<T> awaiter;
readonly IUniTaskSource<T> source;
readonly T result;
readonly short token;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UniTask2(IUniTaskSource<T> awaiter, short token)
public UniTask2(T result)
{
this.awaiter = awaiter;
this.source = default;
this.token = default;
this.result = result;
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UniTask2(IUniTaskSource<T> source, short token)
{
this.source = source;
this.token = token;
this.result = default;
}
public AwaiterStatus Status
@ -408,7 +380,7 @@ namespace UniRx.Async
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return awaiter.GetStatus(token);
return (source == null) ? AwaiterStatus.Succeeded : source.GetStatus(token);
}
}
@ -419,154 +391,77 @@ namespace UniRx.Async
return new Awaiter(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
T GetResult()
// TODO:AsTask???
/// <summary>
/// returns (bool IsCanceled, T Result) instead of throws OperationCanceledException.
/// </summary>
public UniTask2<(bool IsCanceled, T Result)> SuppressCancellationThrow()
{
return awaiter.GetResult(token);
if (source == null)
{
return new UniTask2<(bool IsCanceled, T Result)>((false, result));
}
return new UniTask2<(bool, T)>(new IsCanceledSource(source), token);
}
// TODO:can be suppress?
///// <summary>
///// returns (bool IsCanceled) instead of throws OperationCanceledException.
///// </summary>
//public UniTask<bool> SuppressCancellationThrow()
//{
// var status = Status;
// if (status == AwaiterStatus.Succeeded) return CompletedTasks.False;
// if (status == AwaiterStatus.Canceled) return CompletedTasks.True;
// //return new UniTask<bool>(new IsCanceledAwaiter(awaiter));
//}
public override string ToString()
{
var status = this.awaiter.UnsafeGetStatus();
return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")";
return (this.source == null) ? result?.ToString()
: "(" + this.source.UnsafeGetStatus() + ")";
}
//public static implicit operator UniTask<AsyncUnit>(UniTask2 task)
//{
// // TODO:
// throw new NotImplementedException();
// //if (task.awaiter != null)
// //{
// // if (task.awaiter.IsCompleted)
// // {
// // return DefaultAsyncUnitTask;
// // }
// // else
// // {
// // // UniTask<T> -> UniTask is free but UniTask -> UniTask<T> requires wrapping cost.
// // return new UniTask<AsyncUnit>(new AsyncUnitAwaiter(task.awaiter));
// // }
// //}
// //else
// //{
// // return DefaultAsyncUnitTask;
// //}
//}
//class AsyncUnitAwaiter : IAwaiter<AsyncUnit>
//{
// readonly IAwaiter2 awaiter;
// public AsyncUnitAwaiter(IAwaiter2 awaiter)
// {
// this.awaiter = awaiter;
// }
// public bool IsCompleted => awaiter.IsCompleted;
// public AwaiterStatus Status => awaiter.Status;
// public AsyncUnit GetResult()
// {
// awaiter.GetResult();
// return AsyncUnit.Default;
// }
// public void OnCompleted(Action continuation)
// {
// awaiter.OnCompleted(continuation);
// }
// public void UnsafeOnCompleted(Action continuation)
// {
// awaiter.UnsafeOnCompleted(continuation);
// }
// void IAwaiter.GetResult()
// {
// awaiter.GetResult();
// }
//}
class IsCanceledAwaiter : IUniTaskSource
class IsCanceledSource : IUniTaskSource<(bool, T)>
{
readonly IUniTaskSource awaiter;
readonly IUniTaskSource<T> source;
public IsCanceledAwaiter(IUniTaskSource awaiter)
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IsCanceledSource(IUniTaskSource<T> source)
{
this.awaiter = awaiter;
this.source = source;
}
//public bool IsCompleted => awaiter.IsCompleted;
//public AwaiterStatus Status => awaiter.Status;
//public bool GetResult()
//{
// if (awaiter.Status == AwaiterStatus.Canceled)
// {
// return true;
// }
// awaiter.GetResult();
// return false;
//}
//public void OnCompleted(Action continuation)
//{
// awaiter.OnCompleted(continuation);
//}
//public void UnsafeOnCompleted(Action continuation)
//{
// awaiter.UnsafeOnCompleted(continuation);
//}
//void IAwaiter.GetResult()
//{
// awaiter.GetResult();
//}
public void GetResult(short token)
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public (bool, T) GetResult(short token)
{
// TODO: bool
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
if (source.GetStatus(token) == AwaiterStatus.Canceled)
{
//return true;
return (true, default);
}
awaiter.GetResult(token);
// return false
throw new NotImplementedException();
var result = source.GetResult(token);
return (false, result);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AwaiterStatus GetStatus(short token)
{
return awaiter.GetStatus(token);
return source.GetStatus(token);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AwaiterStatus UnsafeGetStatus()
{
return awaiter.UnsafeGetStatus();
return source.UnsafeGetStatus();
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action<object> continuation, object state, short token)
{
awaiter.OnCompleted(continuation, state, token);
source.OnCompleted(continuation, state, token);
}
}
@ -591,35 +486,49 @@ namespace UniRx.Async
}
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status;
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetResult()
{
return task.GetResult();
var s = task.source;
if (s == null)
{
return task.result;
}
else
{
return s.GetResult(task.token);
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
var s = task.source;
if (s == null)
{
continuation();
}
else
{
s.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnsafeOnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
var s = task.source;
if (s == null)
{
continuation();
}
else
{
s.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
}
}
@ -1045,7 +954,7 @@ namespace UniRx.Async
readonly UniTask<T> task;
[DebuggerHidden]
public Awaiter(UniTask<T> task)
public Awaiter(in UniTask<T> task)
{
this.task = task;
}

View File

@ -693,8 +693,9 @@ namespace UniRx.Async
public static AutoResetUniTaskCompletionSource Create()
{
// TODO:Add TaskTracker
return pool.TryRent() ?? new AutoResetUniTaskCompletionSource();
var value = pool.TryRent() ?? new AutoResetUniTaskCompletionSource();
TaskTracker2.TrackActiveTask(value, 2);
return value;
}
public static AutoResetUniTaskCompletionSource CreateFromCanceled(CancellationToken cancellationToken, out short token)
@ -748,7 +749,7 @@ namespace UniRx.Async
{
try
{
// TODO:Remove TaskTracker
TaskTracker2.RemoveTracking(this);
core.GetResult(token);
}
finally
@ -795,7 +796,7 @@ namespace UniRx.Async
public UniTaskCompletionSource2()
{
// TODO: TaskTracker.TrackActiveTask
TaskTracker2.TrackActiveTask(this, 2);
}
[Conditional("UNITY_EDITOR")]
@ -804,8 +805,7 @@ namespace UniRx.Async
if (!handled)
{
handled = true;
// TODO:
// TaskTracker.RemoveTracking(this);
TaskTracker2.RemoveTracking(this);
}
}
@ -819,9 +819,9 @@ namespace UniRx.Async
public void Reset()
{
// TODO:Reset, reactive tracker: TaskTracker.TrackActiveTask
handled = false;
core.Reset();
TaskTracker2.TrackActiveTask(this, 2);
}
public void SetResult(T result)
@ -884,8 +884,9 @@ namespace UniRx.Async
public static AutoResetUniTaskCompletionSource<T> Create()
{
// TODO:Add TaskTracker
return pool.TryRent() ?? new AutoResetUniTaskCompletionSource<T>();
var result = pool.TryRent() ?? new AutoResetUniTaskCompletionSource<T>();
TaskTracker2.TrackActiveTask(result, 2);
return result;
}
public static AutoResetUniTaskCompletionSource<T> CreateFromCanceled(CancellationToken cancellationToken, out short token)
@ -939,7 +940,7 @@ namespace UniRx.Async
{
try
{
// TODO:Remove TaskTracker
TaskTracker2.RemoveTracking(this);
return core.GetResult(token);
}
finally