mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-17 12:40:11 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80704e489d | ||
|
|
3c0aa03643 | ||
|
|
37cd00d347 | ||
|
|
859c4d706f | ||
|
|
7289fe6e25 | ||
|
|
0c33977f5a | ||
|
|
4d4466e801 | ||
|
|
79330d7cdb | ||
|
|
680ce1098b | ||
|
|
2337d705ec | ||
|
|
d2880a818f | ||
|
|
86ea128bf4 | ||
|
|
a66f378622 | ||
|
|
265f88584b |
53
README.md
53
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.
|
||||||
|
|
||||||
@@ -665,6 +690,8 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build. And also currently due to IL2CPP limitation, in IL2CPP build, UniTask do boxing AsyncStateMachine when needed so sometimes exists `one` allocation.
|
||||||
|
|
||||||
API References
|
API References
|
||||||
---
|
---
|
||||||
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
||||||
@@ -722,6 +749,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,26 @@ 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;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -43,7 +58,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 +66,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 +117,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -113,7 +132,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 +140,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 +232,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -224,7 +247,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 +255,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 +281,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
|
||||||
{
|
{
|
||||||
@@ -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