mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-17 12:40:11 +00:00
complete infrastructure
This commit is contained in:
@@ -3,14 +3,628 @@
|
||||
#pragma warning disable CS0436
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Sources;
|
||||
using UniRx.Async.CompilerServices;
|
||||
using UniRx.Async.Internal;
|
||||
|
||||
namespace UniRx.Async
|
||||
{
|
||||
|
||||
|
||||
public partial struct UniTask2
|
||||
{
|
||||
public static UniTask2 DelayFrame(int frameCount, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new UniTask2(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token);
|
||||
|
||||
|
||||
//return new ValueTask<int>(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class DelayPromiseCore2 : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem
|
||||
{
|
||||
static readonly PromisePool<DelayPromiseCore2> pool = new PromisePool<DelayPromiseCore2>();
|
||||
|
||||
int delayFrameCount;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
int currentFrameCount;
|
||||
UniTaskCompletionSourceCore<object> core;
|
||||
|
||||
DelayPromiseCore2()
|
||||
{
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
var result = pool.TryRent() ?? new DelayPromiseCore2();
|
||||
|
||||
result.delayFrameCount = delayFrameCount;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker2.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
try
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
pool.TryReturn(this);
|
||||
}
|
||||
}
|
||||
|
||||
public AwaiterStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public AwaiterStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
TaskTracker2.RemoveTracking(this);
|
||||
core.SetCancellation(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentFrameCount == delayFrameCount)
|
||||
{
|
||||
TaskTracker2.RemoveTracking(this);
|
||||
core.SetResult(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentFrameCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
core.Reset();
|
||||
currentFrameCount = default;
|
||||
delayFrameCount = default;
|
||||
cancellationToken = default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Lightweight unity specified task-like object.
|
||||
/// </summary>
|
||||
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2
|
||||
public partial struct UniTask2
|
||||
{
|
||||
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
|
||||
|
||||
readonly IUniTaskSource awaiter;
|
||||
readonly short token;
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UniTask2(IUniTaskSource awaiter, short token)
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return awaiter.GetStatus(token);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Awaiter GetAwaiter()
|
||||
{
|
||||
return new Awaiter(this);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void GetResult()
|
||||
{
|
||||
awaiter.GetResult(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 + ")";
|
||||
}
|
||||
|
||||
//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
|
||||
{
|
||||
readonly IUniTaskSource awaiter;
|
||||
|
||||
public IsCanceledAwaiter(IUniTaskSource awaiter)
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
// TODO: bool
|
||||
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
|
||||
{
|
||||
//return true;
|
||||
}
|
||||
|
||||
awaiter.GetResult(token);
|
||||
// return false
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public AwaiterStatus GetStatus(short token)
|
||||
{
|
||||
return awaiter.GetStatus(token);
|
||||
}
|
||||
|
||||
public AwaiterStatus UnsafeGetStatus()
|
||||
{
|
||||
return awaiter.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
awaiter.OnCompleted(continuation, state, token);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct Awaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
readonly UniTask2 task;
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Awaiter(in UniTask2 task)
|
||||
{
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return task.Status.IsCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return task.Status;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void GetResult()
|
||||
{
|
||||
task.GetResult();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
task.awaiter.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>
|
||||
{
|
||||
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
|
||||
|
||||
readonly IUniTaskSource<T> awaiter;
|
||||
readonly short token;
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UniTask2(IUniTaskSource<T> awaiter, short token)
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return awaiter.GetStatus(token);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Awaiter GetAwaiter()
|
||||
{
|
||||
return new Awaiter(this);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
T GetResult()
|
||||
{
|
||||
return awaiter.GetResult(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 + ")";
|
||||
}
|
||||
|
||||
//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
|
||||
{
|
||||
readonly IUniTaskSource awaiter;
|
||||
|
||||
public IsCanceledAwaiter(IUniTaskSource awaiter)
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
// TODO: bool
|
||||
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
|
||||
{
|
||||
//return true;
|
||||
}
|
||||
|
||||
awaiter.GetResult(token);
|
||||
// return false
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public AwaiterStatus GetStatus(short token)
|
||||
{
|
||||
return awaiter.GetStatus(token);
|
||||
}
|
||||
|
||||
public AwaiterStatus UnsafeGetStatus()
|
||||
{
|
||||
return awaiter.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
awaiter.OnCompleted(continuation, state, token);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct Awaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
readonly UniTask2<T> task;
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Awaiter(in UniTask2<T> task)
|
||||
{
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return task.Status.IsCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
{
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return task.Status;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T GetResult()
|
||||
{
|
||||
return task.GetResult();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Lightweight unity specified task-like object.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user