mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-15 11:30:09 +00:00
Compare commits
12 Commits
2.0.14
...
fix-il2cpp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37cd00d347 | ||
|
|
859c4d706f | ||
|
|
7289fe6e25 | ||
|
|
0c33977f5a | ||
|
|
4d4466e801 | ||
|
|
79330d7cdb | ||
|
|
680ce1098b | ||
|
|
2337d705ec | ||
|
|
d2880a818f | ||
|
|
86ea128bf4 | ||
|
|
a66f378622 | ||
|
|
265f88584b |
55
README.md
55
README.md
@@ -53,21 +53,33 @@ async UniTask<string> DemoAsync()
|
|||||||
{
|
{
|
||||||
// You can await Unity's AsyncObject
|
// You can await Unity's AsyncObject
|
||||||
var asset = await Resources.LoadAsync<TextAsset>("foo");
|
var asset = await Resources.LoadAsync<TextAsset>("foo");
|
||||||
|
var txt = (await UnityWebRequest.Get("https://...").SendWebRequest()).downloadHandler.text;
|
||||||
|
await SceneManager.LoadSceneAsync("scene2");
|
||||||
|
|
||||||
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
||||||
var asset2 = await Resources.LoadAsync<TextAsset>("foo").WithCancellation(this.GetCancellationTokenOnDestroy());
|
var asset2 = await Resources.LoadAsync<TextAsset>("bar").WithCancellation(this.GetCancellationTokenOnDestroy());
|
||||||
|
|
||||||
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
||||||
await SceneManager.LoadSceneAsync("scene2").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
var asset3 = await Resources.LoadAsync<TextAsset>("baz").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
||||||
|
|
||||||
// await frame-based operation like coroutine
|
// await frame-based operation like coroutine
|
||||||
await UniTask.DelayFrame(100);
|
await UniTask.DelayFrame(100);
|
||||||
|
|
||||||
// replacement of WaitForSeconds/WaitForSecondsRealtime
|
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(10), ignoreTimeScale: false);
|
await UniTask.Delay(TimeSpan.FromSeconds(10), ignoreTimeScale: false);
|
||||||
|
|
||||||
// replacement of WaitForEndOfFrame(or other timing like yield return null, yield return WaitForFixedUpdate)
|
// yield any playerloop timing(PreUpdate, Update, LateUpdate, etc...)
|
||||||
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
await UniTask.Yield(PlayerLoopTiming.PreLateUpdate);
|
||||||
|
|
||||||
|
// replacement of yield return null
|
||||||
|
await UniTask.Yield();
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
|
||||||
|
// replacement of WaitForEndOfFrame(same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate))
|
||||||
|
await UniTask.WaitForEndOfFrame();
|
||||||
|
|
||||||
|
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
||||||
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
|
||||||
// replacement of yield return WaitUntil
|
// replacement of yield return WaitUntil
|
||||||
await UniTask.WaitUntil(() => isActive == false);
|
await UniTask.WaitUntil(() => isActive == false);
|
||||||
@@ -81,9 +93,14 @@ async UniTask<string> DemoAsync()
|
|||||||
// You can await standard task
|
// You can await standard task
|
||||||
await Task.Run(() => 100);
|
await Task.Run(() => 100);
|
||||||
|
|
||||||
// Multithreading, run on ThreadPool under this code(use SwitchToMainThread, same as `ObserveOnMainThreadDispatcher`)
|
// Multithreading, run on ThreadPool under this code
|
||||||
await UniTask.SwitchToThreadPool();
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
/* work on ThreadPool */
|
||||||
|
|
||||||
|
// return to MainThread(same as `ObserveOnMainThread` in UniRx)
|
||||||
|
await UniTask.SwitchToMainThread();
|
||||||
|
|
||||||
// get async webrequest
|
// get async webrequest
|
||||||
async UniTask<string> GetTextAsync(UnityWebRequest req)
|
async UniTask<string> GetTextAsync(UnityWebRequest req)
|
||||||
{
|
{
|
||||||
@@ -127,6 +144,8 @@ UniTask provides three pattern of extension methods.
|
|||||||
|
|
||||||
`WithCancellation` is a simple version of `ToUniTask`, both returns `UniTask`. Details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
`WithCancellation` is a simple version of `ToUniTask`, both returns `UniTask`. Details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
||||||
|
|
||||||
|
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
||||||
|
|
||||||
The type of `UniTask` can use utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
The type of `UniTask` can use utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
@@ -321,9 +340,15 @@ public enum PlayerLoopTiming
|
|||||||
|
|
||||||
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
||||||
|
|
||||||
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update is called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). If change timing to `PlayerLoopTiming.LastUpdate`, called after these Unity's update methods.
|
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
||||||
|
|
||||||
`PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
`yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`.
|
||||||
|
|
||||||
|
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
|
||||||
|
|
||||||
|
AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
|
||||||
|
|
||||||
|
In UniTask, await directly and `WithCancellation` use native timing, `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, causes different order of Start and continuation after await. so recommend not to use `LoadSceneAsync.ToUniTask`.
|
||||||
|
|
||||||
In stacktrace, you can check where is running in playerloop.
|
In stacktrace, you can check where is running in playerloop.
|
||||||
|
|
||||||
@@ -722,6 +747,16 @@ public class ZeroAllocAsyncAwaitInDotNetCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UniTask does not return to original SynchronizationContext but you can use helper `ReturnToCurrentSynchronizationContext`.
|
||||||
|
public ValueTask TestAsync()
|
||||||
|
{
|
||||||
|
await using (UniTask.ReturnToCurrentSynchronizationContext())
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
// do anything..
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskMethodBuilder
|
public struct AsyncUniTaskMethodBuilder
|
||||||
{
|
{
|
||||||
internal IStateMachineRunnerPromise runnerPromise;
|
IStateMachineRunnerPromise runnerPromise;
|
||||||
Exception ex;
|
Exception ex;
|
||||||
|
|
||||||
// 1. Static Create method.
|
// 1. Static Create method.
|
||||||
@@ -80,7 +80,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -96,7 +96,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -138,7 +138,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskMethodBuilder<T>
|
public struct AsyncUniTaskMethodBuilder<T>
|
||||||
{
|
{
|
||||||
internal IStateMachineRunnerPromise<T> runnerPromise;
|
IStateMachineRunnerPromise<T> runnerPromise;
|
||||||
Exception ex;
|
Exception ex;
|
||||||
T result;
|
T result;
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -227,7 +227,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskVoidMethodBuilder
|
public struct AsyncUniTaskVoidMethodBuilder
|
||||||
{
|
{
|
||||||
internal IStateMachineRunner runner;
|
IStateMachineRunner runner;
|
||||||
|
|
||||||
// 1. Static Create method.
|
// 1. Static Create method.
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
@@ -70,7 +70,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runner == null)
|
if (runner == null)
|
||||||
{
|
{
|
||||||
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runner.MoveNext);
|
awaiter.OnCompleted(runner.MoveNext);
|
||||||
@@ -86,7 +86,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runner == null)
|
if (runner == null)
|
||||||
{
|
{
|
||||||
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runner.MoveNext);
|
awaiter.UnsafeOnCompleted(runner.MoveNext);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -29,12 +30,22 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
void SetException(Exception exception);
|
void SetException(Exception exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static class StateMachineUtility
|
||||||
|
{
|
||||||
|
public static int GetState(IAsyncStateMachine stateMachine)
|
||||||
|
{
|
||||||
|
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
||||||
|
.First(x => x.Name.EndsWith("__state"));
|
||||||
|
return (int)info.GetValue(stateMachine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
|
internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
|
||||||
where TStateMachine : IAsyncStateMachine
|
where TStateMachine : IAsyncStateMachine
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -43,7 +54,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskVoidMethodBuilder builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -51,7 +62,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runner = result; // set runner before copied.
|
runnerFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +113,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -113,7 +124,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -121,7 +132,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runnerPromise = result; // set runner before copied.
|
runnerPromiseFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +224,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -224,7 +235,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskMethodBuilder<T> builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -232,10 +243,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runnerPromise = result; // set runner before copied.
|
runnerPromiseFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
|
|
||||||
|
// UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
||||||
|
|
||||||
static AsyncUniTask()
|
static AsyncUniTask()
|
||||||
@@ -255,6 +269,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void Run()
|
void Run()
|
||||||
{
|
{
|
||||||
|
// UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
|
||||||
stateMachine.MoveNext();
|
stateMachine.MoveNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (handle.IsDone) return UniTask.CompletedTask;
|
if (handle.IsDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationHandleWithCancellationSource.Create(handle, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -77,6 +77,132 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle> continuationAction;
|
||||||
|
AsyncOperationHandle handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperationHandle handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||||
@@ -210,7 +336,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<T>(AsyncOperationHandleWithCancellationSource<T>.Create(handle, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -265,6 +391,137 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource<T>>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource<T>> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource<T> NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource<T>), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
||||||
|
AsyncOperationHandle<T> handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle<T> _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(handle.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(Application.dataPath, "");
|
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(PlayerLoopHelper.ApplicationDataPath, "");
|
||||||
var withAssetsPath = "Assets/" + fname;
|
var withAssetsPath = "Assets/" + fname;
|
||||||
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
|
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// UnityEngine.Debug.Log("Called ToArray");
|
||||||
|
|
||||||
var pool = ArrayPool<TSource>.Shared;
|
var pool = ArrayPool<TSource>.Shared;
|
||||||
var array = pool.Rent(16);
|
var array = pool.Rent(16);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
@@ -22,16 +23,34 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (dueTimeFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (dueTimeFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
if (periodFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (intervalFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
||||||
|
}
|
||||||
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +83,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
bool dueTimePhase;
|
bool dueTimePhase;
|
||||||
bool completed;
|
bool completed;
|
||||||
@@ -80,6 +100,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
if (this.period <= 0) this.period = 1;
|
if (this.period <= 0) this.period = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.initialFrame = Time.frameCount;
|
||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
@@ -119,9 +140,19 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
|
if (elapsed == 0)
|
||||||
|
{
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
||||||
|
|
||||||
if (elapsed >= dueTime)
|
if (elapsed >= dueTime)
|
||||||
{
|
{
|
||||||
dueTimePhase = false;
|
dueTimePhase = false;
|
||||||
@@ -137,6 +168,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
||||||
|
|
||||||
if (elapsed >= period)
|
if (elapsed >= period)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(true);
|
completionSource.TrySetResult(true);
|
||||||
@@ -172,6 +205,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
int currentFrame;
|
int currentFrame;
|
||||||
bool dueTimePhase;
|
bool dueTimePhase;
|
||||||
bool completed;
|
bool completed;
|
||||||
@@ -185,6 +219,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
if (periodFrameCount <= 0) periodFrameCount = 1;
|
if (periodFrameCount <= 0) periodFrameCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.initialFrame = Time.frameCount;
|
||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
@@ -228,11 +263,30 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
if (currentFrame++ >= dueTimeFrameCount)
|
if (currentFrame == 0)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount == 0)
|
||||||
|
{
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrame >= dueTimeFrameCount)
|
||||||
{
|
{
|
||||||
dueTimePhase = false;
|
dueTimePhase = false;
|
||||||
completionSource.TrySetResult(true);
|
completionSource.TrySetResult(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,8 +92,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
||||||
public static int MainThreadId => mainThreadId;
|
public static int MainThreadId => mainThreadId;
|
||||||
|
internal static string ApplicationDataPath => applicationDataPath;
|
||||||
|
|
||||||
static int mainThreadId;
|
static int mainThreadId;
|
||||||
|
static string applicationDataPath;
|
||||||
static SynchronizationContext unitySynchronizationContetext;
|
static SynchronizationContext unitySynchronizationContetext;
|
||||||
static ContinuationQueue[] yielders;
|
static ContinuationQueue[] yielders;
|
||||||
static PlayerLoopRunner[] runners;
|
static PlayerLoopRunner[] runners;
|
||||||
@@ -177,6 +179,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
// capture default(unity) sync-context.
|
// capture default(unity) sync-context.
|
||||||
unitySynchronizationContetext = SynchronizationContext.Current;
|
unitySynchronizationContetext = SynchronizationContext.Current;
|
||||||
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
applicationDataPath = Application.dataPath;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
|
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
|
||||||
// When domain reload is disabled, re-initialization is required when entering play mode;
|
// When domain reload is disabled, re-initialization is required when entering play mode;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
@@ -21,6 +20,46 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask NextFrame(PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate).
|
||||||
|
/// </summary>
|
||||||
|
public static YieldAwaitable WaitForEndOfFrame()
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken).
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate).
|
||||||
|
/// </summary>
|
||||||
|
public static YieldAwaitable WaitForFixedUpdate()
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken).
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (delayFrameCount < 0)
|
if (delayFrameCount < 0)
|
||||||
@@ -152,27 +191,25 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayFramePromise> pool;
|
static TaskPool<NextFramePromise> pool;
|
||||||
public DelayFramePromise NextNode { get; set; }
|
public NextFramePromise NextNode { get; set; }
|
||||||
|
|
||||||
static DelayFramePromise()
|
static NextFramePromise()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(NextFramePromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int delayFrameCount;
|
int frameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
int currentFrameCount;
|
NextFramePromise()
|
||||||
UniTaskCompletionSourceCore<object> core;
|
|
||||||
|
|
||||||
DelayFramePromise()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -181,10 +218,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
result = new DelayFramePromise();
|
result = new NextFramePromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.delayFrameCount = delayFrameCount;
|
result.frameCount = Time.frameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
@@ -230,13 +267,133 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentFrameCount == delayFrameCount)
|
if (frameCount == Time.frameCount)
|
||||||
{
|
{
|
||||||
core.TrySetResult(null);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~NextFramePromise()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
||||||
|
{
|
||||||
|
static TaskPool<DelayFramePromise> pool;
|
||||||
|
public DelayFramePromise NextNode { get; set; }
|
||||||
|
|
||||||
|
static DelayFramePromise()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
|
int delayFrameCount;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int currentFrameCount;
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
DelayFramePromise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new DelayFramePromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.delayFrameCount = delayFrameCount;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFrameCount == 0)
|
||||||
|
{
|
||||||
|
if (delayFrameCount == 0) // same as Yield
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrameCount >= delayFrameCount)
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrameCount++;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +426,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
float delayFrameTimeSpan;
|
float delayFrameTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
@@ -294,6 +452,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.elapsed = 0.0f;
|
result.elapsed = 0.0f;
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -338,6 +497,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elapsed == 0.0f)
|
||||||
|
{
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elapsed += Time.deltaTime;
|
elapsed += Time.deltaTime;
|
||||||
if (elapsed >= delayFrameTimeSpan)
|
if (elapsed >= delayFrameTimeSpan)
|
||||||
{
|
{
|
||||||
@@ -379,6 +546,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
float delayFrameTimeSpan;
|
float delayFrameTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
|
int initialFrame;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
@@ -401,6 +569,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.elapsed = 0.0f;
|
result.elapsed = 0.0f;
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
@@ -446,6 +615,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elapsed == 0.0f)
|
||||||
|
{
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elapsed += Time.unscaledDeltaTime;
|
elapsed += Time.unscaledDeltaTime;
|
||||||
if (elapsed >= delayFrameTimeSpan)
|
if (elapsed >= delayFrameTimeSpan)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -621,9 +621,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
{
|
{
|
||||||
// throw exception on iterator (main)thread.
|
exception.Throw();
|
||||||
// unfortunately unity test-runner can not handle throw exception on hand-write IEnumerator.MoveNext.
|
return false;
|
||||||
UnityEngine.Debug.LogException(exception.SourceException);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !completed;
|
return !completed;
|
||||||
@@ -692,9 +691,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
{
|
{
|
||||||
// throw exception on iterator (main)thread.
|
exception.Throw();
|
||||||
// unfortunately unity test-runner can not handle throw exception on hand-write IEnumerator.MoveNext.
|
return false;
|
||||||
UnityEngine.Debug.LogException(exception.SourceException);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !completed;
|
return !completed;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -75,7 +75,127 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
sealed class AsyncOperationWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationWithCancellationSource> pool;
|
||||||
|
public AsyncOperationWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AsyncOperation asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationConfiguredSource> pool;
|
static TaskPool<AsyncOperationConfiguredSource> pool;
|
||||||
public AsyncOperationConfiguredSource NextNode { get; set; }
|
public AsyncOperationConfiguredSource NextNode { get; set; }
|
||||||
@@ -124,7 +244,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -133,6 +252,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
return core.GetStatus(token);
|
return core.GetStatus(token);
|
||||||
@@ -203,7 +323,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(ResourceRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -257,7 +377,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
sealed class ResourceRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<ResourceRequestWithCancellationSource> pool;
|
||||||
|
public ResourceRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(ResourceRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
ResourceRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new ResourceRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<ResourceRequestConfiguredSource> pool;
|
static TaskPool<ResourceRequestConfiguredSource> pool;
|
||||||
public ResourceRequestConfiguredSource NextNode { get; set; }
|
public ResourceRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -306,7 +550,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -390,7 +633,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(AssetBundleRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -444,7 +687,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
sealed class AssetBundleRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AssetBundleRequestWithCancellationSource> pool;
|
||||||
|
public AssetBundleRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AssetBundleRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AssetBundleRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
||||||
public AssetBundleRequestConfiguredSource NextNode { get; set; }
|
public AssetBundleRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -545,11 +912,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +943,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<AssetBundle>(AssetBundleCreateRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -630,7 +997,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
sealed class AssetBundleCreateRequestWithCancellationSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AssetBundleCreateRequestWithCancellationSource> pool;
|
||||||
|
public AssetBundleCreateRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AssetBundleCreateRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AssetBundleCreateRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AssetBundle> core;
|
||||||
|
|
||||||
|
AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<AssetBundle>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AssetBundleCreateRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.assetBundle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBundle GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
||||||
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
|
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -731,11 +1222,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,7 +1254,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
||||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -817,7 +1308,132 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
sealed class UnityWebRequestAsyncOperationWithCancellationSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<UnityWebRequestAsyncOperationWithCancellationSource> pool;
|
||||||
|
public UnityWebRequestAsyncOperationWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(UnityWebRequestAsyncOperationWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
UnityWebRequestAsyncOperation asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
||||||
|
|
||||||
|
UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityWebRequest>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new UnityWebRequestAsyncOperationWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityWebRequest GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
||||||
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
|
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
|
||||||
@@ -866,7 +1482,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -920,11 +1535,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# if(t.returnType == "UnityWebRequest") { #>
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST
|
||||||
<# } #>
|
<# } #>
|
||||||
#region <#= t.typeName #>
|
#region <#= t.typeName #>
|
||||||
|
|
||||||
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
||||||
{
|
{
|
||||||
@@ -45,18 +45,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new <#= t.typeName #>Awaiter(asyncOperation);
|
return new <#= t.typeName #>Awaiter(asyncOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, CancellationToken.None, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>WithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ConfigureAwait(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellation = default(CancellationToken))
|
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellation, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
||||||
@@ -106,14 +106,153 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public void UnsafeOnCompleted(Action continuation)
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
{
|
{
|
||||||
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||||
continuationAction = continuation.AsFuncOfT<AsyncOperation>(); // allocate delegate.
|
continuationAction = PooledDelegate<AsyncOperation>.Create(continuation);
|
||||||
asyncOperation.completed += continuationAction;
|
asyncOperation.completed += continuationAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, IPromisePoolItem
|
sealed class <#= t.typeName #>WithCancellationSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>WithCancellationSource>
|
||||||
{
|
{
|
||||||
static readonly PromisePool<<#= t.typeName #>ConfiguredSource> pool = new PromisePool<<#= t.typeName #>ConfiguredSource>();
|
static TaskPool<<#= t.typeName #>WithCancellationSource> pool;
|
||||||
|
public <#= t.typeName #>WithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static <#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>WithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
<#= t.typeName #> asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
||||||
|
|
||||||
|
<#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new <#= t.typeName #>WithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <#= t.returnType #> GetResult(short token)
|
||||||
|
{
|
||||||
|
<# if (!IsVoid(t)) { #>
|
||||||
|
return core.GetResult(token);
|
||||||
|
<# } else { #>
|
||||||
|
core.GetResult(token);
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
|
|
||||||
|
<# if (!IsVoid(t)) { #>
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~<#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
||||||
|
{
|
||||||
|
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
||||||
|
public <#= t.typeName #>ConfiguredSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static <#= t.typeName #>ConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>ConfiguredSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
<#= t.typeName #> asyncOperation;
|
<#= t.typeName #> asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
@@ -133,7 +272,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = pool.TryRent() ?? new <#= t.typeName #>ConfiguredSource();
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new <#= t.typeName #>ConfiguredSource();
|
||||||
|
}
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
@@ -151,8 +293,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
|
|
||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
@@ -161,7 +301,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
pool.TryReturn(this);
|
TryReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +331,9 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -209,24 +352,26 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
~<#= t.typeName #>ConfiguredSource()
|
~<#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
if (pool.TryReturn(this))
|
if (TryReturn())
|
||||||
{
|
{
|
||||||
GC.ReRegisterForFinalize(this);
|
GC.ReRegisterForFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# endregion
|
#endregion
|
||||||
<# if(t.returnType == "UnityWebRequest") { #>
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
#endif
|
#endif
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"version": "2.0.14",
|
"version": "2.0.15",
|
||||||
"unity": "2018.4",
|
"unity": "2018.4",
|
||||||
"description": "Provides an efficient async/await integration to Unity.",
|
"description": "Provides an efficient async/await integration to Unity.",
|
||||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||||
|
|||||||
@@ -21,13 +21,15 @@ public class ExceptionExamples : MonoBehaviour
|
|||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
UnityEngine.Debug.Log("ExceptionScene, LoopType:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
|
||||||
ThrowFromAsyncVoid();
|
//TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||||
_ = ThrowFromTask();
|
|
||||||
_ = ThrowFromUniTask();
|
|
||||||
|
|
||||||
ThrowFromNonAsync();
|
//ThrowFromAsyncVoid();
|
||||||
|
//_ = ThrowFromTask();
|
||||||
|
//_ = ThrowFromUniTask();
|
||||||
|
|
||||||
|
//ThrowFromNonAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.LowLevel;
|
using UnityEngine.LowLevel;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
|
||||||
// using DG.Tweening;
|
// using DG.Tweening;
|
||||||
@@ -265,11 +266,14 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//var r = UniAsync("https://bing.com/", cts.Token);
|
//var r = UniAsync("https://bing.com/", cts.Token);
|
||||||
//cts.Cancel();
|
//cts.Cancel();
|
||||||
//await r;
|
//await r;
|
||||||
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
Debug.Log("UNIASYNC1 ");
|
|
||||||
|
|
||||||
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
|
||||||
Debug.Log("UNIASYNC2");
|
// var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
||||||
|
// foo.downloadHandler.text;
|
||||||
|
//
|
||||||
|
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None);
|
||||||
|
Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -302,15 +306,207 @@ public class SandboxMain : MonoBehaviour
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async UniTask<int> Ex()
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
//throw new Exception();
|
||||||
|
await UniTask.Delay(TimeSpan.FromSeconds(15));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineRun()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before Coroutine yield return null," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
yield return null;
|
||||||
|
UnityEngine.Debug.Log("After Coroutine yield return null," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineRun2()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before Coroutine yield return WaitForEndOfFrame," + Time.frameCount);
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
UnityEngine.Debug.Log("After Coroutine yield return WaitForEndOfFrame," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
UnityEngine.Debug.Log("Onemore After Coroutine yield return WaitForEndOfFrame," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncRun()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(default)," + Time.frameCount);
|
||||||
|
await UniTask.Yield();
|
||||||
|
UnityEngine.Debug.Log("After async Yield(default)," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncLastUpdate()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(LastUpdate)," + Time.frameCount);
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
UnityEngine.Debug.Log("After async Yield(LastUpdate)," + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncLastLast()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(LastPostLateUpdate)," + Time.frameCount);
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
|
UnityEngine.Debug.Log("After async Yield(LastPostLateUpdate)," + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid Yieldding()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
StartCoroutine(CoroutineRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncFixedUpdate()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
Debug.Log("Async:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineFixedUpdate()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
yield return new WaitForFixedUpdate();
|
||||||
|
Debug.Log("Coroutine:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
// Debug.Log("FixedUpdate:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid DelayFrame3_Pre()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
Debug.Log("Before framecount:" + Time.frameCount);
|
||||||
|
await UniTask.DelayFrame(3);
|
||||||
|
Debug.Log("After framecount:" + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid DelayFrame3_Post()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
Debug.Log("Before framecount:" + Time.frameCount);
|
||||||
|
await UniTask.DelayFrame(3);
|
||||||
|
Debug.Log("After framecount:" + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask TestCoroutine()
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
throw new Exception("foobarbaz");
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask DelayCheck()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
Debug.Log("before");
|
||||||
|
var t = UniTask.Delay(TimeSpan.FromSeconds(1), ignoreTimeScale: false);
|
||||||
|
|
||||||
|
await t;
|
||||||
|
Debug.Log("after");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async UniTaskVoid ExecuteAsync()
|
||||||
|
{
|
||||||
|
Debug.Log("1");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
Debug.Log("------------------");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
Debug.Log("2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
//_ = UniTask.Run(async () =>
|
PlayerLoopInfo.Inject();
|
||||||
//{
|
|
||||||
// var watch = System.Diagnostics.Stopwatch.StartNew();
|
//_ = AsyncFixedUpdate();
|
||||||
// await UniTask.Delay(new TimeSpan(0, 0, seconds: 10));
|
//StartCoroutine(CoroutineFixedUpdate());
|
||||||
// Debug.Log(watch.Elapsed);
|
|
||||||
//});
|
//StartCoroutine(TestCoroutine().ToCoroutine());
|
||||||
|
|
||||||
|
// Application.logMessageReceived += Application_logMessageReceived;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
{
|
||||||
|
_ = ExecuteAsync();
|
||||||
|
|
||||||
|
await UniTask.Yield();
|
||||||
|
|
||||||
|
//await DelayCheck();
|
||||||
|
/*
|
||||||
|
UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
StartCoroutine(CoroutineRun());
|
||||||
|
StartCoroutine(CoroutineRun2());
|
||||||
|
_ = AsyncRun();
|
||||||
|
_ = AsyncLastUpdate();
|
||||||
|
_ = AsyncLastLast();
|
||||||
|
*/
|
||||||
|
//await UniTask.Yield();
|
||||||
|
//_ = Test2();
|
||||||
|
// EarlyUpdate.ExecuteMainThreadJobs
|
||||||
|
// _ = Test2();
|
||||||
|
|
||||||
|
//var t = await Resources.LoadAsync<TextAsset>(Application.streamingAssetsPath + "test.txt");
|
||||||
|
//Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + (t != null));
|
||||||
|
//Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + ((TextAsset)t).text);
|
||||||
|
|
||||||
|
|
||||||
|
//await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
//UnityEngine.Debug.Log("after update:" + Time.frameCount);
|
||||||
|
////await UniTask.NextFrame();
|
||||||
|
////await UniTask.Yield();
|
||||||
|
////UnityEngine.Debug.Log("after update nextframe:" + Time.frameCount);
|
||||||
|
|
||||||
|
//StartCoroutine(CoroutineRun2());
|
||||||
|
////StartCoroutine(CoroutineRun());
|
||||||
|
//UnityEngine.Debug.Log("FOO?");
|
||||||
|
|
||||||
|
//_ = DelayFrame3_Pre();
|
||||||
|
//await UniTask.Yield();
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
{
|
||||||
|
_ = DelayFrame3_Post();
|
||||||
|
await UniTask.Yield();
|
||||||
|
|
||||||
|
//await UniTask.Yield(PlayerLoopTiming.LastPreUpdate);
|
||||||
|
//UnityEngine.Debug.Log("before update:" + Time.frameCount);
|
||||||
|
//await UniTask.NextFrame();
|
||||||
|
//await UniTask.Yield();
|
||||||
|
//UnityEngine.Debug.Log("before update nextframe:" + Time.frameCount);
|
||||||
|
|
||||||
|
//StartCoroutine(CoroutineRun());
|
||||||
|
|
||||||
|
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
//_ = Yieldding();
|
||||||
|
|
||||||
|
//var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
//var la = SceneManager.LoadSceneAsync("Scenes/ExceptionExamples").WithCancellation(cts.Token);
|
||||||
|
////cts.Cancel();
|
||||||
|
//await la;
|
||||||
|
//UnityEngine.Debug.Log("End LoadSceneAsync" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
}));
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
//await UniTask.SwitchToMainThread();
|
//await UniTask.SwitchToMainThread();
|
||||||
@@ -423,7 +619,7 @@ public class SandboxMain : MonoBehaviour
|
|||||||
|
|
||||||
//okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
|
//okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
|
||||||
|
|
||||||
PlayerLoopInfo.Inject();
|
|
||||||
|
|
||||||
//UpdateUniTask().Forget();
|
//UpdateUniTask().Forget();
|
||||||
|
|
||||||
@@ -437,10 +633,16 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//GameObject.Destroy(this.gameObject);
|
//GameObject.Destroy(this.gameObject);
|
||||||
|
|
||||||
|
|
||||||
SynchronizationContext.Current.Post(_ =>
|
}
|
||||||
{
|
|
||||||
//UnityEngine.Debug.Log("Post:" + PlayerLoopInfo.CurrentLoopType);
|
private void Application_logMessageReceived2(string condition, string stackTrace, LogType type)
|
||||||
}, null);
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Application_logMessageReceived1(string condition, string stackTrace, LogType type)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
async UniTaskVoid UpdateUniTask()
|
async UniTaskVoid UpdateUniTask()
|
||||||
|
|||||||
@@ -126,15 +126,15 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
||||||
});
|
});
|
||||||
|
|
||||||
[UnityTest]
|
//[UnityTest]
|
||||||
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
//public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
//{
|
||||||
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
// var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
||||||
JobHandle.ScheduleBatchedJobs();
|
// JobHandle.ScheduleBatchedJobs();
|
||||||
await job.Schedule();
|
// await job.Schedule();
|
||||||
job.inOut[0].Should().Be(999);
|
// job.inOut[0].Should().Be(999);
|
||||||
job.inOut.Dispose();
|
// job.inOut.Dispose();
|
||||||
});
|
//});
|
||||||
|
|
||||||
class MyMyClass
|
class MyMyClass
|
||||||
{
|
{
|
||||||
@@ -197,7 +197,7 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
//await UniTask.SwitchToThreadPool();
|
//await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -269,7 +269,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
var first = Time.frameCount;
|
var first = Time.frameCount;
|
||||||
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
|
|
||||||
(Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
var r = (Time.frameCount - first);
|
||||||
|
(9 < r && r < 11).Should().BeTrue();
|
||||||
canceled.Should().Be(true);
|
canceled.Should().Be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -369,6 +370,24 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
throw new Exception("MyException");
|
throw new Exception("MyException");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator NextFrame1() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
var frame = Time.frameCount;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
Time.frameCount.Should().Be(frame + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator NextFrame2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
var frame = Time.frameCount;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
Time.frameCount.Should().Be(frame + 1);
|
||||||
|
});
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
|||||||
97
src/UniTask/Assets/Tests/CachelikeTest.cs
Normal file
97
src/UniTask/Assets/Tests/CachelikeTest.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class Cachelike
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator Check() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var v = await CachedCheck("foo", 10);
|
||||||
|
v.Should().Be(10);
|
||||||
|
|
||||||
|
var v2 = await CachedCheck("bar", 20);
|
||||||
|
v2.Should().Be(20);
|
||||||
|
|
||||||
|
var v3 = await CachedCheck("baz", 30);
|
||||||
|
v3.Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = await CachedCheck("foo", 10);
|
||||||
|
v.Should().Be(10);
|
||||||
|
|
||||||
|
var v2 = await CachedCheck("bar", 20);
|
||||||
|
v2.Should().Be(20);
|
||||||
|
|
||||||
|
var v3 = await CachedCheck("baz", 30);
|
||||||
|
v3.Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = CachedCheck("foo", 10);
|
||||||
|
var v2 = CachedCheck("bar", 20);
|
||||||
|
var v3 = CachedCheck("baz", 30);
|
||||||
|
|
||||||
|
(await v).Should().Be(10);
|
||||||
|
(await v2).Should().Be(20);
|
||||||
|
(await v3).Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = CachedCheck("foo", 10, true);
|
||||||
|
var v2 = CachedCheck("bar", 20, true);
|
||||||
|
var v3 = CachedCheck("baz", 30, true);
|
||||||
|
|
||||||
|
(await v).Should().Be(10);
|
||||||
|
(await v2).Should().Be(20);
|
||||||
|
(await v3).Should().Be(30);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
static Dictionary<string, int> cacheDict = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
async UniTask<int> CachedCheck(string cache, int value, bool yield = false)
|
||||||
|
{
|
||||||
|
if (!cacheDict.ContainsKey(cache))
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yield)
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheDict.TryGetValue(cache, out var v))
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheDict.Add(cache, value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
src/UniTask/Assets/Tests/CachelikeTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/CachelikeTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 416e0e77b4408b0498792eb218ed2870
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
394
src/UniTask/Assets/Tests/DelayTest.cs
Normal file
394
src/UniTask/Assets/Tests/DelayTest.cs
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class DelayTest
|
||||||
|
{
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator DelayFrame() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// for (int i = 1; i < 5; i++)
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(i);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 1; i < 5; i++)
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(i);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + i);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator DelayFrameZero() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(0);
|
||||||
|
// Time.frameCount.Should().Be(frameCount); // same frame
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(0);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + 1); // next frame
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFramePre() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
|
||||||
|
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
|
||||||
|
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
|
||||||
|
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFramePost() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
|
||||||
|
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
|
||||||
|
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
|
||||||
|
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameTest() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(0, 0).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame);
|
||||||
|
// xs[1].Should().Be(initialFrame + 1);
|
||||||
|
// xs[2].Should().Be(initialFrame + 2);
|
||||||
|
// xs[3].Should().Be(initialFrame + 3);
|
||||||
|
// xs[4].Should().Be(initialFrame + 4);
|
||||||
|
//});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
//Debug.Log("------------------");
|
||||||
|
//{
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await new MyTimerFrame(0, null)/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
|
||||||
|
// Debug.Log("OK 0 ------------------");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// var xs = await new MyTimerFrame(1, null)/*.Select(_ =>
|
||||||
|
// {
|
||||||
|
// var t = Time.frameCount;
|
||||||
|
// UnityEngine.Debug.Log("store frameCount:" + t);
|
||||||
|
// return t;
|
||||||
|
// })*/.ToArrayAsync();
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePre() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame);
|
||||||
|
// Debug.Log("OK 0 ------------------");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// Debug.Log("initialFrame:" + initialFrame);
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ =>
|
||||||
|
// {
|
||||||
|
// var t = Time.frameCount;
|
||||||
|
// UnityEngine.Debug.Log("store frameCount:" + t);
|
||||||
|
// return t;
|
||||||
|
// })*/.ToArrayAsync();
|
||||||
|
// Debug.Log("xs len:" + xs.Length);
|
||||||
|
// Debug.Log("xs[0]:" + xs[0]);
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 1);
|
||||||
|
// Debug.Log("OK 1");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// Debug.Log("OK 2");
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePost() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// //var initialFrame = Time.frameCount;
|
||||||
|
// //var xs = await UniTaskAsyncEnumerable.TimerFrame(0).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// //xs[0].Should().Be(initialFrame);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 1);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator Timer() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// {
|
||||||
|
// var initialSeconds = Time.realtimeSinceStartup;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Timer(TimeSpan.FromSeconds(2)).Select(_ => Time.realtimeSinceStartup).ToArrayAsync();
|
||||||
|
|
||||||
|
// Mathf.Approximately(initialSeconds, xs[0]).Should().BeFalse();
|
||||||
|
// Debug.Log("Init:" + initialSeconds);
|
||||||
|
// Debug.Log("After:" + xs[0]);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DelayTest2
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
Debug.Log("------------------");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ThreadRunner
|
||||||
|
{
|
||||||
|
Thread thread;
|
||||||
|
|
||||||
|
public void Start(IPlayerLoopItem runner)
|
||||||
|
{
|
||||||
|
thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
Thread.Sleep(30);
|
||||||
|
while (runner.MoveNext())
|
||||||
|
{
|
||||||
|
Thread.Sleep(30);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MyTimerFrame : IUniTaskAsyncEnumerable<AsyncUnit>
|
||||||
|
{
|
||||||
|
//readonly PlayerLoopTiming updateTiming;
|
||||||
|
readonly int dueTimeFrameCount;
|
||||||
|
readonly int? periodFrameCount;
|
||||||
|
|
||||||
|
public MyTimerFrame(int dueTimeFrameCount, int? periodFrameCount)
|
||||||
|
{
|
||||||
|
//this.updateTiming = updateTiming;
|
||||||
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
|
{
|
||||||
|
readonly int dueTimeFrameCount;
|
||||||
|
readonly int? periodFrameCount;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
|
int currentFrame;
|
||||||
|
bool dueTimePhase;
|
||||||
|
bool completed;
|
||||||
|
bool disposed;
|
||||||
|
ThreadRunner runner;
|
||||||
|
|
||||||
|
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
||||||
|
if (periodFrameCount != null)
|
||||||
|
{
|
||||||
|
if (periodFrameCount <= 0) periodFrameCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this.initialFrame = Time.frameCount;
|
||||||
|
this.dueTimePhase = true;
|
||||||
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
|
||||||
|
//TaskTracker.TrackActiveTask(this, 2);
|
||||||
|
//PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
|
|
||||||
|
runner = new ThreadRunner();
|
||||||
|
runner.Start(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncUnit Current => default;
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
// return false instead of throw
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested || completed) return default;
|
||||||
|
|
||||||
|
|
||||||
|
// reset value here.
|
||||||
|
this.currentFrame = 0;
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (!disposed)
|
||||||
|
{
|
||||||
|
disposed = true;
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Called MoveNext");
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Disposing");
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dueTimePhase)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("In DueTime Phase");
|
||||||
|
if (currentFrame == 0)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount == 0)
|
||||||
|
{
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
/*
|
||||||
|
UnityEngine.Debug.Log("(Init, frameConut)" + (initialFrame, Time.frameCount));
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Skip Here");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Debug.Log("Which Go?");
|
||||||
|
if (++currentFrame >= dueTimeFrameCount)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("END Go?");
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("NG Go?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (periodFrameCount == null)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("PERIOD");
|
||||||
|
completed = true;
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrame >= periodFrameCount)
|
||||||
|
{
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
src/UniTask/Assets/Tests/DelayTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/DelayTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1376b93d9e1083a4a9b4081e08f3a7b7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,400 +1,400 @@
|
|||||||
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
//#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine.SceneManagement;
|
//using UnityEngine.SceneManagement;
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
#endif
|
//#endif
|
||||||
using UnityEngine.Networking;
|
//using UnityEngine.Networking;
|
||||||
|
|
||||||
#if !UNITY_2019_3_OR_NEWER
|
//#if !UNITY_2019_3_OR_NEWER
|
||||||
using UnityEngine.Experimental.LowLevel;
|
//using UnityEngine.Experimental.LowLevel;
|
||||||
#else
|
//#else
|
||||||
using UnityEngine.LowLevel;
|
//using UnityEngine.LowLevel;
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
using Unity.Jobs;
|
//using Unity.Jobs;
|
||||||
#endif
|
//#endif
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class AsyncTest
|
// public class AsyncTest
|
||||||
{
|
// {
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
|
|
||||||
public struct MyJob : IJob
|
// public struct MyJob : IJob
|
||||||
{
|
// {
|
||||||
public int loopCount;
|
// public int loopCount;
|
||||||
public NativeArray<int> inOut;
|
// public NativeArray<int> inOut;
|
||||||
public int result;
|
// public int result;
|
||||||
|
|
||||||
public void Execute()
|
// public void Execute()
|
||||||
{
|
// {
|
||||||
result = 0;
|
// result = 0;
|
||||||
for (int i = 0; i < loopCount; i++)
|
// for (int i = 0; i < loopCount; i++)
|
||||||
{
|
// {
|
||||||
result++;
|
// result++;
|
||||||
}
|
// }
|
||||||
inOut[0] = result;
|
// inOut[0] = result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
Time.timeScale = 0.5f;
|
// Time.timeScale = 0.5f;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(3));
|
// await UniTask.Delay(TimeSpan.FromSeconds(3));
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
Time.timeScale = 1.0f;
|
// Time.timeScale = 1.0f;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
Time.timeScale = 0.5f;
|
// Time.timeScale = 0.5f;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
|
// await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
Time.timeScale = 1.0f;
|
// Time.timeScale = 1.0f;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var a = UniTask.FromResult(999);
|
// var a = UniTask.FromResult(999);
|
||||||
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
// var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
||||||
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
// var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
||||||
|
|
||||||
var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
|
// var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
|
||||||
a2.Should().Be(999);
|
// a2.Should().Be(999);
|
||||||
b2.Should().Be(AsyncUnit.Default);
|
// b2.Should().Be(AsyncUnit.Default);
|
||||||
c2.Should().Be(AsyncUnit.Default);
|
// c2.Should().Be(AsyncUnit.Default);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var a = UniTask.FromResult(999);
|
// var a = UniTask.FromResult(999);
|
||||||
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
// var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
||||||
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
// var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
||||||
|
|
||||||
var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
|
// var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
|
||||||
win.Should().Be(0);
|
// win.Should().Be(0);
|
||||||
a2.Should().Be(999);
|
// a2.Should().Be(999);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
// await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
// var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
||||||
JobHandle.ScheduleBatchedJobs();
|
// JobHandle.ScheduleBatchedJobs();
|
||||||
await job.Schedule();
|
// await job.Schedule();
|
||||||
job.inOut[0].Should().Be(999);
|
// job.inOut[0].Should().Be(999);
|
||||||
job.inOut.Dispose();
|
// job.inOut.Dispose();
|
||||||
});
|
// });
|
||||||
|
|
||||||
class MyMyClass
|
// class MyMyClass
|
||||||
{
|
// {
|
||||||
public int MyProperty { get; set; }
|
// public int MyProperty { get; set; }
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool t = false;
|
// bool t = false;
|
||||||
|
|
||||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget();
|
// UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool t = true;
|
// bool t = true;
|
||||||
|
|
||||||
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget();
|
// UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var v = new MyMyClass { MyProperty = 99 };
|
// var v = new MyMyClass { MyProperty = 99 };
|
||||||
|
|
||||||
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget();
|
// UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
|
|
||||||
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
|
// var currentThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await UniTask.SwitchToThreadPool();
|
// await UniTask.SwitchToThreadPool();
|
||||||
//await UniTask.SwitchToThreadPool();
|
// //await UniTask.SwitchToThreadPool();
|
||||||
//await UniTask.SwitchToThreadPool();
|
// //await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
|
// var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
currentThreadId.Should().NotBe(switchedThreadId);
|
// currentThreadId.Should().NotBe(switchedThreadId);
|
||||||
|
|
||||||
|
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
|
|
||||||
var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
|
// var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
currentThreadId.Should().Be(switchedThreadId2);
|
// currentThreadId.Should().Be(switchedThreadId2);
|
||||||
});
|
// });
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var v = await Observable.Range(1, 10).ToUniTask();
|
// // var v = await Observable.Range(1, 10).ToUniTask();
|
||||||
// v.Is(10);
|
// // v.Is(10);
|
||||||
|
|
||||||
// v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
|
// // v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
|
||||||
// v.Is(1);
|
// // v.Is(1);
|
||||||
|
|
||||||
// v = await UniTask.DelayFrame(10).ToObservable().ToTask();
|
// // v = await UniTask.DelayFrame(10).ToObservable().ToTask();
|
||||||
// v.Is(10);
|
// // v.Is(10);
|
||||||
|
|
||||||
// v = await UniTask.FromResult(99).ToObservable();
|
// // v = await UniTask.FromResult(99).ToObservable();
|
||||||
// v.Is(99);
|
// // v.Is(99);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var rp1 = new ReactiveProperty<int>(99);
|
// // var rp1 = new ReactiveProperty<int>(99);
|
||||||
|
|
||||||
// UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
|
// // UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
|
||||||
|
|
||||||
// await rp1;
|
// // await rp1;
|
||||||
|
|
||||||
// rp1.Value.Is(100);
|
// // rp1.Value.Is(100);
|
||||||
|
|
||||||
// // var delay2 = UniTask.DelayFrame(10);
|
// // // var delay2 = UniTask.DelayFrame(10);
|
||||||
// // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
|
// // // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
|
||||||
|
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var rc = new ReactiveCommand<int>();
|
// // var rc = new ReactiveCommand<int>();
|
||||||
|
|
||||||
// UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
|
// // UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
|
||||||
|
|
||||||
// var v = await rc;
|
// // var v = await rc;
|
||||||
|
|
||||||
// v.Is(100);
|
// // v.Is(100);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
// UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
||||||
|
|
||||||
var first = Time.frameCount;
|
// var first = Time.frameCount;
|
||||||
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
// var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
|
|
||||||
(Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
// (Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
||||||
canceled.Should().Be(true);
|
// canceled.Should().Be(true);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
// UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
||||||
|
|
||||||
bool occur = false;
|
// bool occur = false;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.DelayFrame(100, cancellationToken: cts.Token);
|
// await UniTask.DelayFrame(100, cancellationToken: cts.Token);
|
||||||
}
|
// }
|
||||||
catch (OperationCanceledException)
|
// catch (OperationCanceledException)
|
||||||
{
|
// {
|
||||||
occur = true;
|
// occur = true;
|
||||||
}
|
// }
|
||||||
occur.Should().BeTrue();
|
// occur.Should().BeTrue();
|
||||||
});
|
// });
|
||||||
|
|
||||||
IEnumerator ToaruCoroutineEnumerator()
|
// IEnumerator ToaruCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool calledEx = false;
|
// bool calledEx = false;
|
||||||
Action<Exception> action = exx =>
|
// Action<Exception> action = exx =>
|
||||||
{
|
// {
|
||||||
calledEx = true;
|
// calledEx = true;
|
||||||
exx.Message.Should().Be("MyException");
|
// exx.Message.Should().Be("MyException");
|
||||||
};
|
// };
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException += action;
|
// UniTaskScheduler.UnobservedTaskException += action;
|
||||||
|
|
||||||
var ex = InException1();
|
// var ex = InException1();
|
||||||
ex = default(UniTask);
|
// ex = default(UniTask);
|
||||||
|
|
||||||
await UniTask.DelayFrame(3);
|
// await UniTask.DelayFrame(3);
|
||||||
|
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
// GC.WaitForPendingFinalizers();
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
|
|
||||||
await UniTask.DelayFrame(1);
|
// await UniTask.DelayFrame(1);
|
||||||
|
|
||||||
calledEx.Should().BeTrue();
|
// calledEx.Should().BeTrue();
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException -= action;
|
// UniTaskScheduler.UnobservedTaskException -= action;
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool calledEx = false;
|
// bool calledEx = false;
|
||||||
Action<Exception> action = exx =>
|
// Action<Exception> action = exx =>
|
||||||
{
|
// {
|
||||||
calledEx = true;
|
// calledEx = true;
|
||||||
exx.Message.Should().Be("MyException");
|
// exx.Message.Should().Be("MyException");
|
||||||
};
|
// };
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException += action;
|
// UniTaskScheduler.UnobservedTaskException += action;
|
||||||
|
|
||||||
var ex = InException2();
|
// var ex = InException2();
|
||||||
ex = default(UniTask<int>);
|
// ex = default(UniTask<int>);
|
||||||
|
|
||||||
await UniTask.DelayFrame(3);
|
// await UniTask.DelayFrame(3);
|
||||||
|
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
// GC.WaitForPendingFinalizers();
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
|
|
||||||
await UniTask.DelayFrame(1);
|
// await UniTask.DelayFrame(1);
|
||||||
|
|
||||||
calledEx.Should().BeTrue();
|
// calledEx.Should().BeTrue();
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException -= action;
|
// UniTaskScheduler.UnobservedTaskException -= action;
|
||||||
});
|
// });
|
||||||
|
|
||||||
async UniTask InException1()
|
// async UniTask InException1()
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
throw new Exception("MyException");
|
// throw new Exception("MyException");
|
||||||
}
|
// }
|
||||||
|
|
||||||
async UniTask<int> InException2()
|
// async UniTask<int> InException2()
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
throw new Exception("MyException");
|
// throw new Exception("MyException");
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
await ParentCoroutineEnumerator();
|
// await ParentCoroutineEnumerator();
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
||||||
});
|
// });
|
||||||
|
|
||||||
IEnumerator ParentCoroutineEnumerator()
|
// IEnumerator ParentCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return ChildCoroutineEnumerator();
|
// yield return ChildCoroutineEnumerator();
|
||||||
}
|
// }
|
||||||
|
|
||||||
IEnumerator ChildCoroutineEnumerator()
|
// IEnumerator ChildCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return new WaitForSeconds(3);
|
// yield return new WaitForSeconds(3);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
//#endif
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -1,95 +1,95 @@
|
|||||||
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
//#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine.SceneManagement;
|
//using UnityEngine.SceneManagement;
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
#endif
|
//#endif
|
||||||
using UnityEngine.Networking;
|
//using UnityEngine.Networking;
|
||||||
|
|
||||||
#if !UNITY_2019_3_OR_NEWER
|
//#if !UNITY_2019_3_OR_NEWER
|
||||||
using UnityEngine.Experimental.LowLevel;
|
//using UnityEngine.Experimental.LowLevel;
|
||||||
#else
|
//#else
|
||||||
using UnityEngine.LowLevel;
|
//using UnityEngine.LowLevel;
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
using Unity.Jobs;
|
//using Unity.Jobs;
|
||||||
#endif
|
//#endif
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class RunTest
|
// public class RunTest
|
||||||
{
|
// {
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var main = Thread.CurrentThread.ManagedThreadId;
|
// // var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
// var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
|
// // var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
|
||||||
// UnityEngine.Debug.Log("Ret Value is:" + v);
|
// // UnityEngine.Debug.Log("Ret Value is:" + v);
|
||||||
// UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
// // UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||||
// //v.Should().Be(3);
|
// // //v.Should().Be(3);
|
||||||
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
// // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var main = Thread.CurrentThread.ManagedThreadId;
|
// var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
var v = await UniTask.Run(() => 3, true);
|
// var v = await UniTask.Run(() => 3, true);
|
||||||
v.Should().Be(3);
|
// v.Should().Be(3);
|
||||||
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
// main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
||||||
});
|
// });
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var main = Thread.CurrentThread.ManagedThreadId;
|
// // var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
// try
|
// // try
|
||||||
// {
|
// // {
|
||||||
// await UniTask.Run<int>(() => throw new Exception(), false);
|
// // await UniTask.Run<int>(() => throw new Exception(), false);
|
||||||
// }
|
// // }
|
||||||
// catch
|
// // catch
|
||||||
// {
|
// // {
|
||||||
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
// // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
||||||
// }
|
// // }
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var main = Thread.CurrentThread.ManagedThreadId;
|
// var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Run<int>(() => throw new Exception(), true);
|
// await UniTask.Run<int>(() => throw new Exception(), true);
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
// main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
//#endif
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -1,43 +1,43 @@
|
|||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#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
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class WhenAnyTest
|
// public class WhenAnyTest
|
||||||
{
|
// {
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
|
// var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
|
||||||
var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
|
// var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
|
||||||
cts.CancelAfterSlim(200);
|
// cts.CancelAfterSlim(200);
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
|
// var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
ex.Should().BeAssignableTo<OperationCanceledException>();
|
// ex.Should().BeAssignableTo<OperationCanceledException>();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -6,13 +6,20 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.TestTools;
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
namespace Cysharp.Threading.TasksTests
|
||||||
{
|
{
|
||||||
public class Preserve
|
public class Preserve
|
||||||
{
|
{
|
||||||
|
public Preserve()
|
||||||
|
{
|
||||||
|
// TaskPool.SetMaxPoolSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () =>
|
public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -33,12 +40,17 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () =>
|
public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.Update);
|
||||||
|
|
||||||
var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve();
|
var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve();
|
||||||
var before = UnityEngine.Time.frameCount;
|
|
||||||
|
var before = UnityEngine.Time.frameCount; // 0
|
||||||
|
|
||||||
await delay;
|
await delay;
|
||||||
var afterOne = UnityEngine.Time.frameCount;
|
var afterOne = UnityEngine.Time.frameCount; // 5
|
||||||
|
|
||||||
await delay;
|
await delay;
|
||||||
var afterTwo = UnityEngine.Time.frameCount;
|
var afterTwo = UnityEngine.Time.frameCount; // 5
|
||||||
|
|
||||||
(afterOne - before).Should().Be(5);
|
(afterOne - before).Should().Be(5);
|
||||||
afterOne.Should().Be(afterTwo);
|
afterOne.Should().Be(afterTwo);
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"UnityEditor.TestRunner",
|
"UnityEditor.TestRunner",
|
||||||
"UniTask",
|
"UniTask",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager",
|
||||||
"DOTween.Modules"
|
"DOTween.Modules",
|
||||||
|
"UniTask.Linq"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ EditorBuildSettings:
|
|||||||
- enabled: 1
|
- enabled: 1
|
||||||
path: Assets/Scenes/SandboxMain.unity
|
path: Assets/Scenes/SandboxMain.unity
|
||||||
guid: 2cda990e2423bbf4892e6590ba056729
|
guid: 2cda990e2423bbf4892e6590ba056729
|
||||||
- enabled: 0
|
- enabled: 1
|
||||||
path:
|
path: Assets/Scenes/ExceptionExamples.unity
|
||||||
guid: 00000000000000000000000000000000
|
guid: b5fed17e3ece238439bc796d8747df5d
|
||||||
m_configObjects: {}
|
m_configObjects: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user