mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-18 05:00:14 +00:00
more more
This commit is contained in:
@@ -34,7 +34,7 @@ namespace UniRx.Async.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
public UniTaskStatus Status
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -94,7 +94,7 @@ namespace UniRx.Async.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public AwaiterStatus Status
|
||||
public UniTaskStatus Status
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -1,395 +0,0 @@
|
||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniRx.Async.Internal
|
||||
{
|
||||
// public for some types uses it.
|
||||
|
||||
public abstract class ReusablePromise : IAwaiter
|
||||
{
|
||||
ExceptionDispatchInfo exception;
|
||||
object continuation; // Action or Queue<Action>
|
||||
AwaiterStatus status;
|
||||
|
||||
public UniTask Task => new UniTask(this);
|
||||
|
||||
// can override for control 'start/reset' timing.
|
||||
public virtual bool IsCompleted => status.IsCompleted();
|
||||
|
||||
public virtual void GetResult()
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case AwaiterStatus.Succeeded:
|
||||
return;
|
||||
case AwaiterStatus.Faulted:
|
||||
exception.Throw();
|
||||
break;
|
||||
case AwaiterStatus.Canceled:
|
||||
throw new OperationCanceledException();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Invalid Status:" + status);
|
||||
}
|
||||
|
||||
public AwaiterStatus Status => status;
|
||||
|
||||
void IAwaiter.GetResult()
|
||||
{
|
||||
GetResult();
|
||||
}
|
||||
|
||||
public void ResetStatus(bool forceReset)
|
||||
{
|
||||
if (forceReset)
|
||||
{
|
||||
status = AwaiterStatus.Pending;
|
||||
}
|
||||
else if (status == AwaiterStatus.Succeeded)
|
||||
{
|
||||
status = AwaiterStatus.Pending;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool TrySetCanceled()
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Canceled;
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetException(Exception ex)
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Faulted;
|
||||
exception = ExceptionDispatchInfo.Capture(ex);
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetResult()
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Succeeded;
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TryInvokeContinuation()
|
||||
{
|
||||
if (continuation == null) return;
|
||||
|
||||
if (continuation is Action act)
|
||||
{
|
||||
continuation = null;
|
||||
act();
|
||||
}
|
||||
else
|
||||
{
|
||||
// reuse Queue(don't null clear)
|
||||
var q = (MinimumQueue<Action>)continuation;
|
||||
var size = q.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
q.Dequeue().Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCompleted(Action action)
|
||||
{
|
||||
UnsafeOnCompleted(action);
|
||||
}
|
||||
|
||||
public void UnsafeOnCompleted(Action action)
|
||||
{
|
||||
if (continuation == null)
|
||||
{
|
||||
continuation = action;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (continuation is Action act)
|
||||
{
|
||||
var q = new MinimumQueue<Action>(4);
|
||||
q.Enqueue(act);
|
||||
q.Enqueue(action);
|
||||
continuation = q;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
((MinimumQueue<Action>)continuation).Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ReusablePromise<T> : IAwaiter<T>
|
||||
{
|
||||
T result;
|
||||
ExceptionDispatchInfo exception;
|
||||
object continuation; // Action or Queue<Action>
|
||||
AwaiterStatus status;
|
||||
|
||||
public UniTask<T> Task => new UniTask<T>(this);
|
||||
|
||||
// can override for control 'start/reset' timing.
|
||||
public virtual bool IsCompleted => status.IsCompleted();
|
||||
|
||||
protected T RawResult => result;
|
||||
|
||||
protected void ForceSetResult(T result)
|
||||
{
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public virtual T GetResult()
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case AwaiterStatus.Succeeded:
|
||||
return result;
|
||||
case AwaiterStatus.Faulted:
|
||||
exception.Throw();
|
||||
break;
|
||||
case AwaiterStatus.Canceled:
|
||||
throw new OperationCanceledException();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Invalid Status:" + status);
|
||||
}
|
||||
|
||||
public AwaiterStatus Status => status;
|
||||
|
||||
void IAwaiter.GetResult()
|
||||
{
|
||||
GetResult();
|
||||
}
|
||||
|
||||
public void ResetStatus(bool forceReset)
|
||||
{
|
||||
if (forceReset)
|
||||
{
|
||||
status = AwaiterStatus.Pending;
|
||||
}
|
||||
else if (status == AwaiterStatus.Succeeded)
|
||||
{
|
||||
status = AwaiterStatus.Pending;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool TrySetCanceled()
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Canceled;
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetException(Exception ex)
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Faulted;
|
||||
exception = ExceptionDispatchInfo.Capture(ex);
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetResult(T result)
|
||||
{
|
||||
if (status == AwaiterStatus.Pending)
|
||||
{
|
||||
status = AwaiterStatus.Succeeded;
|
||||
this.result = result;
|
||||
TryInvokeContinuation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void TryInvokeContinuation()
|
||||
{
|
||||
if (continuation == null) return;
|
||||
|
||||
if (continuation is Action act)
|
||||
{
|
||||
continuation = null;
|
||||
act();
|
||||
}
|
||||
else
|
||||
{
|
||||
// reuse Queue(don't null clear)
|
||||
var q = (MinimumQueue<Action>)continuation;
|
||||
var size = q.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
q.Dequeue().Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCompleted(Action action)
|
||||
{
|
||||
UnsafeOnCompleted(action);
|
||||
}
|
||||
|
||||
public void UnsafeOnCompleted(Action action)
|
||||
{
|
||||
if (continuation == null)
|
||||
{
|
||||
continuation = action;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (continuation is Action act)
|
||||
{
|
||||
var q = new MinimumQueue<Action>(4);
|
||||
q.Enqueue(act);
|
||||
q.Enqueue(action);
|
||||
continuation = q;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
((MinimumQueue<Action>)continuation).Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PlayerLoopReusablePromiseBase : ReusablePromise, IPlayerLoopItem
|
||||
{
|
||||
readonly PlayerLoopTiming timing;
|
||||
protected readonly CancellationToken cancellationToken;
|
||||
bool isRunning = false;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string capturedStackTraceForDebugging;
|
||||
#endif
|
||||
|
||||
public PlayerLoopReusablePromiseBase(PlayerLoopTiming timing, CancellationToken cancellationToken, int skipTrackFrameCountAdditive)
|
||||
{
|
||||
this.timing = timing;
|
||||
this.cancellationToken = cancellationToken;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
this.capturedStackTraceForDebugging = TaskTracker.CaptureStackTrace(skipTrackFrameCountAdditive + 1); // 1 is self,
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Status == AwaiterStatus.Canceled || Status == AwaiterStatus.Faulted) return true;
|
||||
|
||||
if (!isRunning)
|
||||
{
|
||||
isRunning = true;
|
||||
ResetStatus(false);
|
||||
OnRunningStart();
|
||||
#if UNITY_EDITOR
|
||||
TaskTracker.TrackActiveTask(this, capturedStackTraceForDebugging);
|
||||
#endif
|
||||
PlayerLoopHelper.AddAction(timing, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void OnRunningStart();
|
||||
|
||||
protected void Complete()
|
||||
{
|
||||
isRunning = false;
|
||||
#if UNITY_EDITOR
|
||||
TaskTracker.RemoveTracking(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract bool MoveNext();
|
||||
}
|
||||
|
||||
public abstract class PlayerLoopReusablePromiseBase<T> : ReusablePromise<T>, IPlayerLoopItem
|
||||
{
|
||||
readonly PlayerLoopTiming timing;
|
||||
protected readonly CancellationToken cancellationToken;
|
||||
bool isRunning = false;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string capturedStackTraceForDebugging;
|
||||
#endif
|
||||
|
||||
public PlayerLoopReusablePromiseBase(PlayerLoopTiming timing, CancellationToken cancellationToken, int skipTrackFrameCountAdditive)
|
||||
{
|
||||
this.timing = timing;
|
||||
this.cancellationToken = cancellationToken;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
this.capturedStackTraceForDebugging = TaskTracker.CaptureStackTrace(skipTrackFrameCountAdditive + 1); // 1 is self,
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Status == AwaiterStatus.Canceled || Status == AwaiterStatus.Faulted) return true;
|
||||
|
||||
if (!isRunning)
|
||||
{
|
||||
isRunning = true;
|
||||
ResetStatus(false);
|
||||
OnRunningStart();
|
||||
#if UNITY_EDITOR
|
||||
TaskTracker.TrackActiveTask(this, capturedStackTraceForDebugging);
|
||||
#endif
|
||||
PlayerLoopHelper.AddAction(timing, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void OnRunningStart();
|
||||
|
||||
protected void Complete()
|
||||
{
|
||||
isRunning = false;
|
||||
#if UNITY_EDITOR
|
||||
TaskTracker.RemoveTracking(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract bool MoveNext();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8cfc99b5928c0242919aac2121b02bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
57
Assets/UniRx.Async/Internal/StatePool.cs
Normal file
57
Assets/UniRx.Async/Internal/StatePool.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace UniRx.Async.Internal
|
||||
{
|
||||
internal static class StateTuple
|
||||
{
|
||||
public static StateTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
|
||||
{
|
||||
return StatePool<T1, T2>.Create(item1, item2);
|
||||
}
|
||||
}
|
||||
|
||||
internal class StateTuple<T1, T2> : IDisposable
|
||||
{
|
||||
public T1 Item1;
|
||||
public T2 Item2;
|
||||
|
||||
public void Deconstruct(out T1 item1, out T2 item2)
|
||||
{
|
||||
item1 = this.Item1;
|
||||
item2 = this.Item2;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
StatePool<T1, T2>.Return(this);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class StatePool<T1, T2>
|
||||
{
|
||||
static readonly ConcurrentQueue<StateTuple<T1, T2>> queue = new ConcurrentQueue<StateTuple<T1, T2>>();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static StateTuple<T1, T2> Create(T1 item1, T2 item2)
|
||||
{
|
||||
if (queue.TryDequeue(out var value))
|
||||
{
|
||||
value.Item1 = item1;
|
||||
value.Item2 = item2;
|
||||
return value;
|
||||
}
|
||||
|
||||
return new StateTuple<T1, T2> { Item1 = item1, Item2 = item2 };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Return(StateTuple<T1, T2> tuple)
|
||||
{
|
||||
tuple.Item1 = default;
|
||||
tuple.Item2 = default;
|
||||
queue.Enqueue(tuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ namespace UniRx.Async.Internal
|
||||
}
|
||||
|
||||
/// <summary>(trackingId, awaiterType, awaiterStatus, createdTime, stackTrace)</summary>
|
||||
public static void ForEachActiveTask(Action<int, string, AwaiterStatus, DateTime, string> action)
|
||||
public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action)
|
||||
{
|
||||
lock (listPool)
|
||||
{
|
||||
@@ -233,7 +233,7 @@ namespace UniRx.Async.Internal
|
||||
}
|
||||
|
||||
/// <summary>(trackingId, awaiterType, awaiterStatus, createdTime, stackTrace)</summary>
|
||||
public static void ForEachActiveTask(Action<int, string, AwaiterStatus, DateTime, string> action)
|
||||
public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action)
|
||||
{
|
||||
lock (listPool)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user