mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-15 11:30:09 +00:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53907a3719 | ||
|
|
4937aeee3f | ||
|
|
5e5b8aff89 | ||
|
|
a2cbbd82d0 | ||
|
|
7eac5d8ba8 | ||
|
|
e2b1ed55ae | ||
|
|
727c7102d3 | ||
|
|
1494ea6717 | ||
|
|
f1ce64dbd3 | ||
|
|
3bad5cd2bf | ||
|
|
7432c0073a | ||
|
|
f1813a7c94 | ||
|
|
9e45c0a4d1 | ||
|
|
2c652cdde7 | ||
|
|
7718d345c8 | ||
|
|
9f39708325 | ||
|
|
bb6dbfa920 | ||
|
|
ba265005bb | ||
|
|
4d7cc7ed61 | ||
|
|
b64f31eb0b | ||
|
|
38d159b69e | ||
|
|
d5455f3716 | ||
|
|
a72ceeba11 | ||
|
|
c6b7d332b2 | ||
|
|
f37278f2a6 | ||
|
|
3f3e03b83d | ||
|
|
c99d3eb3c3 | ||
|
|
08d5183e7e | ||
|
|
51769b2224 | ||
|
|
6ec0ed8d61 | ||
|
|
2e35324403 | ||
|
|
e9474649c4 | ||
|
|
a8e0ce50c8 | ||
|
|
db7ddba735 | ||
|
|
1999d94b33 | ||
|
|
44af123b6c | ||
|
|
547b700ba7 | ||
|
|
6b87d5d2b0 | ||
|
|
023894d45e | ||
|
|
009715c0da | ||
|
|
c2824027d4 | ||
|
|
65b6553a1a | ||
|
|
9d3b7adc8e | ||
|
|
3724fc204c | ||
|
|
b97451a915 | ||
|
|
9ddcac4c6c | ||
|
|
b61e3c347f | ||
|
|
0bb44066c0 | ||
|
|
305c4aaa07 | ||
|
|
42d627f3ba | ||
|
|
6dd2b464a3 | ||
|
|
32f24cf8f8 | ||
|
|
4a89e3ea86 | ||
|
|
887db5b281 | ||
|
|
fee5518a82 | ||
|
|
551128e64c | ||
|
|
c65ae8d18e | ||
|
|
c1f75d9ebd | ||
|
|
73a5ff6648 | ||
|
|
1c264f380e | ||
|
|
f02bfa0a1e | ||
|
|
9d684006fc | ||
|
|
c49f1ed028 | ||
|
|
d935b226c0 | ||
|
|
d9e20de8a5 | ||
|
|
23997f0f93 | ||
|
|
529272d11b | ||
|
|
1194c38568 | ||
|
|
f0d2ee2beb | ||
|
|
68cdda086a | ||
|
|
54ceca6ceb | ||
|
|
50bdf7460c | ||
|
|
c06e45d0bb | ||
|
|
3ed6e28a00 | ||
|
|
ab76098895 | ||
|
|
0a447e43b0 | ||
|
|
8df44f2768 | ||
|
|
a7ec64d644 | ||
|
|
868e104d85 | ||
|
|
7ced7f5764 | ||
|
|
12b39c6ba1 | ||
|
|
93df9d7693 | ||
|
|
3980f314fa | ||
|
|
c2538da1cd | ||
|
|
5ed943bca2 | ||
|
|
d6a0563319 | ||
|
|
af82a94b87 | ||
|
|
82219e6111 | ||
|
|
81f9c55c7f | ||
|
|
0640f278cc | ||
|
|
769b5c6bab | ||
|
|
bdd569e213 | ||
|
|
5bfff5bc24 | ||
|
|
edf32496e4 | ||
|
|
785f5837d1 | ||
|
|
8c9272bc9f | ||
|
|
3e00735b3d | ||
|
|
00a1be8666 | ||
|
|
a2783d3c8a | ||
|
|
85d1a8a4a4 |
7
.github/workflows/build-debug.yml
vendored
7
.github/workflows/build-debug.yml
vendored
@@ -42,13 +42,6 @@ jobs:
|
||||
steps:
|
||||
- run: apt update && apt install git -y
|
||||
- uses: actions/checkout@v2
|
||||
# create unity activation file and store to artifacts.
|
||||
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logFile -createManualActivationFile || exit 0
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Unity_v${{ matrix.unity }}.alf
|
||||
path: ./Unity_v${{ matrix.unity }}.alf
|
||||
# activate Unity from manual license file(ulf)
|
||||
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
||||
env:
|
||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||
|
||||
48
.gitignore
vendored
48
.gitignore
vendored
@@ -205,3 +205,51 @@ src/UniTask/UnityEngine.Monetization.csproj
|
||||
src/UniTask/UnityEngine.TestRunner.csproj
|
||||
|
||||
src/UniTask/UnityEngine.UI.csproj
|
||||
|
||||
src/UniTask/TempAsm.csproj
|
||||
|
||||
src/UniTask/UniTask.Addressables.csproj
|
||||
|
||||
src/UniTask/UniTask.DOTween.csproj
|
||||
|
||||
src/UniTask/UniTask.TextMeshPro.csproj
|
||||
|
||||
src/UniTask/RuntimeUnitTestToolkit.Player.csproj
|
||||
|
||||
src/UniTask/TempAsm.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.Addressables.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.DOTween.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.Linq.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.Tests.Player.csproj
|
||||
|
||||
src/UniTask/UniTask.TextMeshPro.Player.csproj
|
||||
|
||||
src/UniTask/Unity.Addressables.Player.csproj
|
||||
|
||||
src/UniTask/Unity.Analytics.DataPrivacy.Player.csproj
|
||||
|
||||
src/UniTask/Unity.ResourceManager.Player.csproj
|
||||
|
||||
src/UniTask/Unity.ScriptableBuildPipeline.Player.csproj
|
||||
|
||||
src/UniTask/Unity.TextMeshPro.Player.csproj
|
||||
|
||||
src/UniTask/Unity.Timeline.Player.csproj
|
||||
|
||||
src/UniTask/UnityEngine.Advertisements.Player.csproj
|
||||
|
||||
src/UniTask/UnityEngine.Monetization.Player.csproj
|
||||
|
||||
src/UniTask/UnityEngine.TestRunner.Player.csproj
|
||||
|
||||
src/UniTask/UnityEngine.UI.Player.csproj
|
||||
|
||||
src/UniTask/DOTween.Modules.Player.csproj
|
||||
|
||||
src/UniTask/Assembly-CSharp.Player.csproj
|
||||
|
||||
153
README.md
153
README.md
@@ -34,6 +34,8 @@ Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await f
|
||||
- [For Unit Testing](#for-unit-testing)
|
||||
- [Compare with Standard Task API](#compare-with-standard-task-api)
|
||||
- [Pooling Configuration](#pooling-configuration)
|
||||
- [Allocation on Profiler](#allocation-on-profiler)
|
||||
- [UniTaskSynchronizationContext](#unitasksynchronizationcontext)
|
||||
- [API References](#api-references)
|
||||
- [UPM Package](#upm-package)
|
||||
- [Install via git URL](#install-via-git-url)
|
||||
@@ -136,7 +138,7 @@ UniTask feature rely on C# 7.0([task-like custom async method builder feature](h
|
||||
|
||||
Why UniTask(custom task-like object) is required? Because Task is too heavy, not matched to Unity threading(single-thread). UniTask does not use thread and SynchronizationContext/ExecutionContext because almost Unity's asynchronous object is automaticaly dispatched by Unity's engine layer. It acquires more fast and more less allocation, completely integrated with Unity.
|
||||
|
||||
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
||||
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `AsyncGPUReadbackRequest`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
||||
|
||||
UniTask provides three pattern of extension methods.
|
||||
|
||||
@@ -150,25 +152,24 @@ UniTask provides three pattern of extension methods.
|
||||
|
||||
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
||||
|
||||
> Note: AssetBundleRequest has `asset` and `allAssets`, in default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
||||
|
||||
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
|
||||
public class SceneAssets
|
||||
public async UniTaskVoid LoadManyAsync()
|
||||
{
|
||||
public SceneAssets()
|
||||
{
|
||||
// parallel load.
|
||||
var (a, b, c) = await UniTask.WhenAll(
|
||||
LoadAsSprite("foo"),
|
||||
LoadAsSprite("bar"),
|
||||
LoadAsSprite("baz"));
|
||||
}
|
||||
// parallel load.
|
||||
var (a, b, c) = await UniTask.WhenAll(
|
||||
LoadAsSprite("foo"),
|
||||
LoadAsSprite("bar"),
|
||||
LoadAsSprite("baz"));
|
||||
}
|
||||
|
||||
async UniTask<Sprite> LoadAsSprite(string path)
|
||||
{
|
||||
var resource = await Resources.LoadAsync<Sprite>(path);
|
||||
return (resource as Sprite);
|
||||
}
|
||||
async UniTask<Sprite> LoadAsSprite(string path)
|
||||
{
|
||||
var resource = await Resources.LoadAsync<Sprite>(path);
|
||||
return (resource as Sprite);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -208,7 +209,7 @@ await task;
|
||||
await task; // NG, throws Exception
|
||||
```
|
||||
|
||||
Store to the class field, you can use `UniTask.Lazy` that gurantee call multipletimes. `.Prevent()` allows for multiple calls (internally cached results). This is useful when multiple calls in a function scope.
|
||||
Store to the class field, you can use `UniTask.Lazy` that gurantee call multipletimes. `.Preserve()` allows for multiple calls (internally cached results). This is useful when multiple calls in a function scope.
|
||||
|
||||
Cancellation and Exception handling
|
||||
---
|
||||
@@ -384,9 +385,19 @@ var playerLoop = ScriptBehaviourUpdateOrder.CurrentPlayerLoop;
|
||||
PlayerLoopHelper.Initialize(ref playerLoop);
|
||||
```
|
||||
|
||||
You can diagnostic UniTask's player loop is ready by `PlayerLoopHelper.IsInjectedUniTaskPlayerLoop()`. And also `PlayerLoopHelper.DumpCurrentPlayerLoop` shows current all playerloop to console.
|
||||
|
||||
```csharp
|
||||
void Start()
|
||||
{
|
||||
UnityEngine.Debug.Log("UniTaskPlayerLoop ready? " + PlayerLoopHelper.IsInjectedUniTaskPlayerLoop());
|
||||
PlayerLoopHelper.DumpCurrentPlayerLoop();
|
||||
}
|
||||
```
|
||||
|
||||
async void vs async UniTaskVoid
|
||||
---
|
||||
`async void` is a standard C# taks system so does not run on UniTask systems. It is better not to use. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and report error immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require to await it(fire and forget), use `UniTaskVoid` is better. Unfortunately to dismiss warning, require to using with `Forget()`.
|
||||
`async void` is a standard C# task system so does not run on UniTask systems. It is better not to use. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and report error immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require to await it(fire and forget), use `UniTaskVoid` is better. Unfortunately to dismiss warning, require to using with `Forget()`.
|
||||
|
||||
```csharp
|
||||
public async UniTaskVoid FireAndForgetMethod()
|
||||
@@ -431,6 +442,18 @@ actEvent += UniTask.Action(async () => { await UniTask.Yield(); });
|
||||
unityEvent += UniTask.UnityAction(async () => { await UniTask.Yield(); });
|
||||
```
|
||||
|
||||
`UniTaskVoid` can also use in MonoBehaviour's `Start` method.
|
||||
|
||||
```csharp
|
||||
class Sample : MonoBehaviour
|
||||
{
|
||||
async UniTaskVoid Start()
|
||||
{
|
||||
// async init code.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
UniTaskTracker
|
||||
---
|
||||
useful for check(leak) UniTasks. You can open tracker window in `Window -> UniTask Tracker`.
|
||||
@@ -447,9 +470,11 @@ For debug use, enable tracking and capture stacktrace is useful but it it declin
|
||||
|
||||
External Assets
|
||||
---
|
||||
In default, UniTask supports DOTween and Addressables(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
||||
In default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField` event extensions like standard uGUI `InputField`), DOTween(`Tween` as awaitable) and Addressables(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
||||
|
||||
For DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||
There are defined in separated asmdef like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
||||
|
||||
TextMeshPro and Addressables support are automatically enabled when import there package from package manager. However DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||
|
||||
```csharp
|
||||
// sequential
|
||||
@@ -464,6 +489,8 @@ await UniTask.WhenAll(
|
||||
transform.DOScale(10, 3).WithCancellation(ct));
|
||||
```
|
||||
|
||||
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works both Complete(true/false) and Kill(true/false). But if you want to tween reuse(`SetAutoKill(false)`), it does not work you expected. Or, if you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
||||
|
||||
AsyncEnumerable and Async LINQ
|
||||
---
|
||||
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.
|
||||
@@ -494,11 +521,19 @@ await okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).ForEachAsy
|
||||
});
|
||||
```
|
||||
|
||||
Fire and Forget style(for example, event handling), also you can use `Subscribe`.
|
||||
|
||||
```csharp
|
||||
okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).Subscribe(_ =>
|
||||
{
|
||||
});
|
||||
```
|
||||
|
||||
Async LINQ is enabled when `using Cysharp.Threading.Tasks.Linq;`, and `UniTaskAsyncEnumerable` is defined in `UniTask.Linq` asmdef.
|
||||
|
||||
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
|
||||
|
||||
`UniTaskAsyncEnumerable` is the entry point like `Enumerbale`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`, `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`.
|
||||
`UniTaskAsyncEnumerable` is the entry point like `Enumerbale`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`, `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
|
||||
|
||||
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
||||
|
||||
@@ -510,6 +545,38 @@ SelectAwaitWithCancellation(Func<T, CancellationToken, UniTask<TR>> selector)
|
||||
|
||||
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
|
||||
|
||||
How to create async iterator, C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
|
||||
|
||||
```csharp
|
||||
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
|
||||
public async IAsyncEnumerable<int> MyEveryUpdate([EnumeratorCancellation]CancellationToken cancelationToken = default)
|
||||
{
|
||||
var frameCount = 0;
|
||||
await UniTask.Yield();
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
yield return frameCount++;
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
// UniTaskAsyncEnumerable.Create and use `await writer.YieldAsync` instead of `yield return`.
|
||||
public IUniTaskAsyncEnumerable<int> MyEveryUpdate()
|
||||
{
|
||||
// writer(IAsyncWriter<T>) has `YieldAsync(value)` method.
|
||||
return UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
var frameCount = 0;
|
||||
await UniTask.Yield();
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
await writer.YieldAsync(frameCount++); // instead of `yield return`
|
||||
await UniTask.Yield();
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Awaitable Events
|
||||
---
|
||||
All uGUI component implements `***AsAsyncEnumerable` to convert asynchronous streams of events.
|
||||
@@ -616,10 +683,10 @@ A pull-type asynchronous stream does not get the next values until the asynchron
|
||||
|
||||
```csharp
|
||||
// can not get click event during 3 seconds complete.
|
||||
await button.OnClickAsAsyncEnumerable().ForEachAwaitAsync()
|
||||
await button.OnClickAsAsyncEnumerable().ForEachAwaitAsync(async x =>
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(3));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
It is useful(prevent double-click) but not useful in sometimes.
|
||||
@@ -628,10 +695,19 @@ Using `Queue()` method, which will also queue events during asynchronous process
|
||||
|
||||
```csharp
|
||||
// queued message in asynchronous processing
|
||||
await button.OnClickAsAsyncEnumerable().Queue().ForEachAwaitAsync()
|
||||
await button.OnClickAsAsyncEnumerable().Queue().ForEachAwaitAsync(async x =>
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(3));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Or use `Subscribe`, fire and forget style.
|
||||
|
||||
```csharp
|
||||
button.OnClickAsAsyncEnumerable().Subscribe(async x =>
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(3));
|
||||
});
|
||||
```
|
||||
|
||||
Channel
|
||||
@@ -761,7 +837,32 @@ 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.
|
||||
Allocation on Profiler
|
||||
---
|
||||
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.
|
||||
|
||||
After Unity 2020.1 supports Code Optimization option on UnityEditor(right, footer).
|
||||
|
||||

|
||||
|
||||
You can change C# compiler optimization to release, it removes AsyncStateMachine allocation. Andalso optimization option can set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
||||
|
||||
UniTaskSynchronizationContext
|
||||
---
|
||||
Unity's default SynchronizationContext(`UnitySynchronizationContext`) is poor implementation for performance. UniTask itself is bypass `SynchronizationContext`(and `ExecutionContext`) so does not use it but if exists in `async Task`, still used it. `UniTaskSynchronizationContext` is replacement of `UnitySynchronizationContext`, it is better for performance.
|
||||
|
||||
```csharp
|
||||
public class SyncContextInjecter
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void Inject()
|
||||
{
|
||||
SynchronizationContext.SetSynchronizationContext(new UniTaskSynchronizationContext());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is an optional choice and is not always recommended; `UniTaskSynchronizationContext` is less performance than `async UniTask` and is not a complete UniTask replacement. It also does not guarantee full behavioral compatibility with the `UnitySynchronizationContext`.
|
||||
|
||||
API References
|
||||
---
|
||||
@@ -781,7 +882,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
|
||||
|
||||
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
||||
|
||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.15`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.15`.
|
||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.31`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.31`.
|
||||
|
||||
### Install via OpenUPM
|
||||
|
||||
|
||||
101
src/UniTask.NetCore/NetCore/AsyncEnumerableExtensions.cs
Normal file
101
src/UniTask.NetCore/NetCore/AsyncEnumerableExtensions.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
#pragma warning disable 0649
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Sources;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static class AsyncEnumerableExtensions
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<T> AsUniTaskAsyncEnumerable<T>(this IAsyncEnumerable<T> source)
|
||||
{
|
||||
return new AsyncEnumerableToUniTaskAsyncEnumerable<T>(source);
|
||||
}
|
||||
|
||||
public static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IUniTaskAsyncEnumerable<T> source)
|
||||
{
|
||||
return new UniTaskAsyncEnumerableToAsyncEnumerable<T>(source);
|
||||
}
|
||||
|
||||
sealed class AsyncEnumerableToUniTaskAsyncEnumerable<T> : IUniTaskAsyncEnumerable<T>
|
||||
{
|
||||
readonly IAsyncEnumerable<T> source;
|
||||
|
||||
public AsyncEnumerableToUniTaskAsyncEnumerable(IAsyncEnumerable<T> source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
||||
}
|
||||
|
||||
sealed class Enumerator : IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
readonly IAsyncEnumerator<T> enumerator;
|
||||
|
||||
public Enumerator(IAsyncEnumerator<T> enumerator)
|
||||
{
|
||||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
public T Current => enumerator.Current;
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
await enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
public async UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
return await enumerator.MoveNextAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UniTaskAsyncEnumerableToAsyncEnumerable<T> : IAsyncEnumerable<T>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<T> source;
|
||||
|
||||
public UniTaskAsyncEnumerableToAsyncEnumerable(IUniTaskAsyncEnumerable<T> source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
||||
}
|
||||
|
||||
sealed class Enumerator : IAsyncEnumerator<T>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerator<T> enumerator;
|
||||
|
||||
public Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
|
||||
{
|
||||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
public T Current => enumerator.Current;
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
public ValueTask<bool> MoveNextAsync()
|
||||
{
|
||||
return enumerator.MoveNextAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -26,15 +26,14 @@ namespace Cysharp.Threading.Tasks
|
||||
#endif
|
||||
}
|
||||
|
||||
public static UniTask<T> AsUniTask<T>(this ValueTask<T> task, bool useCurrentSynchronizationContext = true)
|
||||
public static async UniTask<T> AsUniTask<T>(this ValueTask<T> task)
|
||||
{
|
||||
// NOTE: get _obj and _token directly for low overhead conversion but not yet implemented.
|
||||
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
||||
return await task;
|
||||
}
|
||||
|
||||
public static UniTask AsUniTask(this ValueTask task, bool useCurrentSynchronizationContext = true)
|
||||
public static async UniTask AsUniTask(this ValueTask task)
|
||||
{
|
||||
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
||||
await task;
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\DiagnosticsExtensions.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\PlayerLoopRunner.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\ContinuationQueue.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityWebRequestExtensions.cs;
|
||||
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
|
||||
@@ -44,9 +46,7 @@
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Bridge.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.WaitUntil.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.uGUI.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.MonoBehaviour.cs;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.*;
|
||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
|
||||
" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
#pragma warning disable CS1998
|
||||
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
using System.Linq;
|
||||
using System;
|
||||
@@ -56,6 +58,24 @@ namespace NetCoreSandbox
|
||||
|
||||
}
|
||||
|
||||
class Foo
|
||||
{
|
||||
public async UniTask MethodFooAsync()
|
||||
{
|
||||
await MethodBarAsync();
|
||||
}
|
||||
|
||||
private async UniTask MethodBarAsync()
|
||||
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
|
||||
private void Throw()
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public struct TestAwaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
@@ -275,53 +295,25 @@ namespace NetCoreSandbox
|
||||
//await new ComparisonBenchmarks().ViaUniTaskT();
|
||||
return;
|
||||
#endif
|
||||
// await new AllocationCheck().ViaUniTaskVoid();
|
||||
|
||||
// AsyncTest().Forge
|
||||
|
||||
Console.WriteLine("A?");
|
||||
var a = await new ZeroAllocAsyncAwaitInDotNetCore().NanikaAsync(1, 2);
|
||||
Console.WriteLine("RET:" + a);
|
||||
await WhereSelect();
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext(new MySyncContext());
|
||||
|
||||
await Aaa();
|
||||
|
||||
|
||||
|
||||
|
||||
//AsyncTest().Forget();
|
||||
|
||||
// AsyncTest().Forget();
|
||||
|
||||
ThreadPool.SetMinThreads(100, 100);
|
||||
|
||||
//List<UniTask<int>> list = new List<UniTask<int>>();
|
||||
for (int i = 0; i < short.MaxValue; i++)
|
||||
var e = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
//// list.Add(AsyncTest());
|
||||
await YieldCore();
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
Console.WriteLine($"Start {i}");
|
||||
await writer.YieldAsync(i);
|
||||
Console.WriteLine($"End {i}");
|
||||
}
|
||||
});
|
||||
|
||||
var ee = e.GetAsyncEnumerator();
|
||||
while (await ee.MoveNextAsync())
|
||||
{
|
||||
Console.WriteLine("ForEach " + ee.Current);
|
||||
}
|
||||
//await UniTask.WhenAll(list);
|
||||
|
||||
//Console.WriteLine("TOGO");
|
||||
|
||||
//var a = await AsyncTest();
|
||||
//var b = AsyncTest();
|
||||
//var c = AsyncTest();
|
||||
await YieldCore();
|
||||
|
||||
//await b;
|
||||
//await c;
|
||||
|
||||
|
||||
//foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPool.GetCacheSizeInfo())
|
||||
//{
|
||||
// Console.WriteLine(item);
|
||||
//}
|
||||
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async UniTask YieldCore()
|
||||
|
||||
167
src/UniTask.NetCoreTests/AsyncLazyTest.cs
Normal file
167
src/UniTask.NetCoreTests/AsyncLazyTest.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using Cysharp.Threading.Tasks.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace NetCoreTests
|
||||
{
|
||||
public class AsyncLazyTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task LazyLazy()
|
||||
{
|
||||
{
|
||||
var l = UniTask.Lazy(() => After());
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await a;
|
||||
await b;
|
||||
await c;
|
||||
}
|
||||
{
|
||||
var l = UniTask.Lazy(() => AfterException());
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LazyImmediate()
|
||||
{
|
||||
{
|
||||
var l = UniTask.Lazy(() => UniTask.FromResult(1).AsUniTask());
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await a;
|
||||
await b;
|
||||
await c;
|
||||
}
|
||||
{
|
||||
var l = UniTask.Lazy(() => UniTask.FromException(new TaskTestException()));
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
||||
}
|
||||
}
|
||||
|
||||
static async UniTask AwaitAwait(UniTask t)
|
||||
{
|
||||
await t;
|
||||
}
|
||||
|
||||
|
||||
async UniTask After()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
await UniTask.Yield();
|
||||
await UniTask.Yield();
|
||||
}
|
||||
|
||||
async UniTask AfterException()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
await UniTask.Yield();
|
||||
throw new TaskTestException();
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncLazyTest2
|
||||
{
|
||||
[Fact]
|
||||
public async Task LazyLazy()
|
||||
{
|
||||
{
|
||||
var l = UniTask.Lazy(() => After());
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
var a2 = await a;
|
||||
var b2 = await b;
|
||||
var c2 = await c;
|
||||
(a2, b2, c2).Should().Be((10, 10, 10));
|
||||
}
|
||||
{
|
||||
var l = UniTask.Lazy(() => AfterException());
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LazyImmediate()
|
||||
{
|
||||
{
|
||||
var l = UniTask.Lazy(() => UniTask.FromResult(1));
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
var a2 = await a;
|
||||
var b2 = await b;
|
||||
var c2 = await c;
|
||||
(a2, b2, c2).Should().Be((1, 1, 1));
|
||||
}
|
||||
{
|
||||
var l = UniTask.Lazy(() => UniTask.FromException<int>(new TaskTestException()));
|
||||
var a = AwaitAwait(l.Task);
|
||||
var b = AwaitAwait(l.Task);
|
||||
var c = AwaitAwait(l.Task);
|
||||
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
||||
}
|
||||
}
|
||||
|
||||
static async UniTask<int> AwaitAwait(UniTask<int> t)
|
||||
{
|
||||
return await t;
|
||||
}
|
||||
|
||||
|
||||
async UniTask<int> After()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
await UniTask.Yield();
|
||||
await UniTask.Yield();
|
||||
return 10;
|
||||
}
|
||||
|
||||
async UniTask<int> AfterException()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
await UniTask.Yield();
|
||||
throw new TaskTestException();
|
||||
}
|
||||
}
|
||||
}
|
||||
590
src/UniTask.NetCoreTests/CompletionSourceTest.cs
Normal file
590
src/UniTask.NetCoreTests/CompletionSourceTest.cs
Normal file
@@ -0,0 +1,590 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using Cysharp.Threading.Tasks.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace NetCoreTests
|
||||
{
|
||||
public class CompletionSourceTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task SetFirst()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
tcs.TrySetResult();
|
||||
await tcs.Task; // ok.
|
||||
await tcs.Task; // ok.
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SingleOnFirst()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetResult();
|
||||
await a;
|
||||
await tcs.Task; // ok.
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultiOne()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
tcs.TrySetResult();
|
||||
await a;
|
||||
await b;
|
||||
await tcs.Task; // ok.
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultiTwo()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
tcs.TrySetResult();
|
||||
await a;
|
||||
await b;
|
||||
await c;
|
||||
await tcs.Task; // ok.
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await c);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
|
||||
async UniTask Await()
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
class TestException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class CompletionSourceTest2
|
||||
{
|
||||
[Fact]
|
||||
public async Task SetFirst()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
tcs.TrySetResult(10);
|
||||
var a = await tcs.Task; // ok.
|
||||
var b = await tcs.Task; // ok.
|
||||
a.Should().Be(10);
|
||||
b.Should().Be(10);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SingleOnFirst()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetResult(10);
|
||||
var r1 = await a;
|
||||
var r2 = await tcs.Task; // ok.
|
||||
r1.Should().Be(10);
|
||||
r2.Should().Be(10);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultiOne()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
tcs.TrySetResult(10);
|
||||
var r1 = await a;
|
||||
var r2 = await b;
|
||||
var r3 = await tcs.Task; // ok.
|
||||
(r1, r2, r3).Should().Be((10, 10, 10));
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultiTwo()
|
||||
{
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
tcs.TrySetResult(10);
|
||||
var r1 = await a;
|
||||
var r2 = await b;
|
||||
var r3 = await c;
|
||||
var r4 = await tcs.Task; // ok.
|
||||
(r1, r2, r3, r4).Should().Be((10, 10, 10, 10));
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetException(new TestException());
|
||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await c);
|
||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<int>();
|
||||
|
||||
async UniTask<int> Await()
|
||||
{
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
var a = Await();
|
||||
var b = Await();
|
||||
var c = Await();
|
||||
|
||||
tcs.TrySetCanceled(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||
}
|
||||
}
|
||||
|
||||
class TestException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
170
src/UniTask.NetCoreTests/Linq/CreateTest.cs
Normal file
170
src/UniTask.NetCoreTests/Linq/CreateTest.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
#pragma warning disable CS1998
|
||||
#pragma warning disable CS0162
|
||||
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks.Linq;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace NetCoreTests.Linq
|
||||
{
|
||||
public class CreateTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task SyncCreation()
|
||||
{
|
||||
var from = 10;
|
||||
var count = 100;
|
||||
|
||||
var xs = await UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
await writer.YieldAsync(from + i);
|
||||
}
|
||||
}).ToArrayAsync();
|
||||
|
||||
var ys = await Range(from, count).AsUniTaskAsyncEnumerable().ToArrayAsync();
|
||||
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SyncManually()
|
||||
{
|
||||
var list = new List<int>();
|
||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
list.Add(100);
|
||||
await writer.YieldAsync(10);
|
||||
|
||||
list.Add(200);
|
||||
await writer.YieldAsync(20);
|
||||
|
||||
list.Add(300);
|
||||
await writer.YieldAsync(30);
|
||||
|
||||
list.Add(400);
|
||||
});
|
||||
|
||||
list.Should().BeEmpty();
|
||||
var e = xs.GetAsyncEnumerator();
|
||||
|
||||
list.Should().BeEmpty();
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100);
|
||||
e.Current.Should().Be(10);
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100, 200);
|
||||
e.Current.Should().Be(20);
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100, 200, 300);
|
||||
e.Current.Should().Be(30);
|
||||
|
||||
(await e.MoveNextAsync()).Should().BeFalse();
|
||||
list.Should().BeEquivalentTo(100, 200, 300, 400);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SyncExceptionFirst()
|
||||
{
|
||||
var from = 10;
|
||||
var count = 100;
|
||||
|
||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
throw new UniTaskTestException();
|
||||
await writer.YieldAsync(from + i);
|
||||
}
|
||||
});
|
||||
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SyncException()
|
||||
{
|
||||
var from = 10;
|
||||
var count = 100;
|
||||
|
||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
await writer.YieldAsync(from + i);
|
||||
|
||||
if (i == 15)
|
||||
{
|
||||
throw new UniTaskTestException();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ASyncManually()
|
||||
{
|
||||
var list = new List<int>();
|
||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
await UniTask.Yield();
|
||||
|
||||
list.Add(100);
|
||||
await writer.YieldAsync(10);
|
||||
|
||||
await UniTask.Yield();
|
||||
|
||||
list.Add(200);
|
||||
await writer.YieldAsync(20);
|
||||
|
||||
await UniTask.Yield();
|
||||
list.Add(300);
|
||||
await UniTask.Yield();
|
||||
await writer.YieldAsync(30);
|
||||
|
||||
await UniTask.Yield();
|
||||
|
||||
list.Add(400);
|
||||
});
|
||||
|
||||
list.Should().BeEmpty();
|
||||
var e = xs.GetAsyncEnumerator();
|
||||
|
||||
list.Should().BeEmpty();
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100);
|
||||
e.Current.Should().Be(10);
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100, 200);
|
||||
e.Current.Should().Be(20);
|
||||
|
||||
await e.MoveNextAsync();
|
||||
list.Should().BeEquivalentTo(100, 200, 300);
|
||||
e.Current.Should().Be(30);
|
||||
|
||||
(await e.MoveNextAsync()).Should().BeFalse();
|
||||
list.Should().BeEquivalentTo(100, 200, 300, 400);
|
||||
}
|
||||
|
||||
async IAsyncEnumerable<int> Range(int from, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
yield return from + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace NetCoreTests.Linq
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeUntil()
|
||||
public async Task TakeUntilCanceled()
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace NetCoreTests.Linq
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SkipUntil()
|
||||
public async Task SkipUntilCanceled()
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace NetCoreTests.Linq
|
||||
await c;
|
||||
var foo = await xs;
|
||||
|
||||
foo.Should().BeEquivalentTo(new[] { 30, 40 });
|
||||
foo.Should().BeEquivalentTo(new[] { 20, 30, 40 });
|
||||
|
||||
async Task CancelAsync()
|
||||
{
|
||||
@@ -102,5 +102,64 @@ namespace NetCoreTests.Linq
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeUntil()
|
||||
{
|
||||
var cts = new AsyncReactiveProperty<int>(0);
|
||||
|
||||
var rp = new AsyncReactiveProperty<int>(1);
|
||||
|
||||
var xs = rp.TakeUntil(cts.WaitAsync()).ToArrayAsync();
|
||||
|
||||
var c = CancelAsync();
|
||||
|
||||
await c;
|
||||
var foo = await xs;
|
||||
|
||||
foo.Should().BeEquivalentTo(new[] { 1, 10, 20 });
|
||||
|
||||
async Task CancelAsync()
|
||||
{
|
||||
rp.Value = 10;
|
||||
await Task.Yield();
|
||||
rp.Value = 20;
|
||||
await Task.Yield();
|
||||
cts.Value = 9999;
|
||||
rp.Value = 30;
|
||||
await Task.Yield();
|
||||
rp.Value = 40;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SkipUntil()
|
||||
{
|
||||
var cts = new AsyncReactiveProperty<int>(0);
|
||||
|
||||
var rp = new AsyncReactiveProperty<int>(1);
|
||||
|
||||
var xs = rp.SkipUntil(cts.WaitAsync()).ToArrayAsync();
|
||||
|
||||
var c = CancelAsync();
|
||||
|
||||
await c;
|
||||
var foo = await xs;
|
||||
|
||||
foo.Should().BeEquivalentTo(new[] { 20, 30, 40 });
|
||||
|
||||
async Task CancelAsync()
|
||||
{
|
||||
rp.Value = 10;
|
||||
await Task.Yield();
|
||||
rp.Value = 20;
|
||||
await Task.Yield();
|
||||
cts.Value = 9999;
|
||||
rp.Value = 30;
|
||||
await Task.Yield();
|
||||
rp.Value = 40;
|
||||
|
||||
rp.Dispose(); // complete.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
src/UniTask.NetCoreTests/WithCancellationTest.cs
Normal file
40
src/UniTask.NetCoreTests/WithCancellationTest.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace NetCoreTests
|
||||
{
|
||||
public class WithCancellationTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task Standard()
|
||||
{
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
|
||||
var v = await UniTask.Run(() => 10).WithCancellation(cts.Token);
|
||||
|
||||
v.Should().Be(10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cancel()
|
||||
{
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
|
||||
var t = UniTask.Create(async () =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
return 10;
|
||||
}).WithCancellation(cts.Token);
|
||||
|
||||
cts.Cancel();
|
||||
|
||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await t)).CancellationToken.Should().Be(cts.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
|
||||
@@ -7,113 +7,239 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public class AsyncLazy
|
||||
{
|
||||
Func<UniTask> valueFactory;
|
||||
UniTask target;
|
||||
static Action<object> continuation = SetCompletionSource;
|
||||
|
||||
Func<UniTask> taskFactory;
|
||||
UniTaskCompletionSource completionSource;
|
||||
UniTask.Awaiter awaiter;
|
||||
|
||||
object syncLock;
|
||||
bool initialized;
|
||||
|
||||
public AsyncLazy(Func<UniTask> valueFactory)
|
||||
public AsyncLazy(Func<UniTask> taskFactory)
|
||||
{
|
||||
this.valueFactory = valueFactory;
|
||||
this.target = default;
|
||||
this.taskFactory = taskFactory;
|
||||
this.completionSource = new UniTaskCompletionSource();
|
||||
this.syncLock = new object();
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
internal AsyncLazy(UniTask value)
|
||||
internal AsyncLazy(UniTask task)
|
||||
{
|
||||
this.valueFactory = null;
|
||||
this.target = value;
|
||||
this.taskFactory = null;
|
||||
this.completionSource = new UniTaskCompletionSource();
|
||||
this.syncLock = null;
|
||||
this.initialized = true;
|
||||
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
SetCompletionSource(awaiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
awaiter.SourceOnCompleted(continuation, this);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask Task => EnsureInitialized();
|
||||
public UniTask Task
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return completionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask.Awaiter GetAwaiter() => EnsureInitialized().GetAwaiter();
|
||||
|
||||
UniTask EnsureInitialized()
|
||||
public UniTask.Awaiter GetAwaiter() => Task.GetAwaiter();
|
||||
|
||||
void EnsureInitialized()
|
||||
{
|
||||
if (Volatile.Read(ref initialized))
|
||||
{
|
||||
return target;
|
||||
return;
|
||||
}
|
||||
|
||||
return EnsureInitializedCore();
|
||||
EnsureInitializedCore();
|
||||
}
|
||||
|
||||
UniTask EnsureInitializedCore()
|
||||
void EnsureInitializedCore()
|
||||
{
|
||||
lock (syncLock)
|
||||
{
|
||||
if (!Volatile.Read(ref initialized))
|
||||
{
|
||||
var f = Interlocked.Exchange(ref valueFactory, null);
|
||||
var f = Interlocked.Exchange(ref taskFactory, null);
|
||||
if (f != null)
|
||||
{
|
||||
target = f().Preserve(); // with preserve(allow multiple await).
|
||||
var task = f();
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
SetCompletionSource(awaiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
awaiter.SourceOnCompleted(continuation, this);
|
||||
}
|
||||
|
||||
Volatile.Write(ref initialized, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
void SetCompletionSource(in UniTask.Awaiter awaiter)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult();
|
||||
completionSource.TrySetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCompletionSource(object state)
|
||||
{
|
||||
var self = (AsyncLazy)state;
|
||||
try
|
||||
{
|
||||
self.awaiter.GetResult();
|
||||
self.completionSource.TrySetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
self.awaiter = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncLazy<T>
|
||||
{
|
||||
Func<UniTask<T>> valueFactory;
|
||||
UniTask<T> target;
|
||||
static Action<object> continuation = SetCompletionSource;
|
||||
|
||||
Func<UniTask<T>> taskFactory;
|
||||
UniTaskCompletionSource<T> completionSource;
|
||||
UniTask<T>.Awaiter awaiter;
|
||||
|
||||
object syncLock;
|
||||
bool initialized;
|
||||
|
||||
public AsyncLazy(Func<UniTask<T>> valueFactory)
|
||||
public AsyncLazy(Func<UniTask<T>> taskFactory)
|
||||
{
|
||||
this.valueFactory = valueFactory;
|
||||
this.target = default;
|
||||
this.taskFactory = taskFactory;
|
||||
this.completionSource = new UniTaskCompletionSource<T>();
|
||||
this.syncLock = new object();
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
internal AsyncLazy(UniTask<T> value)
|
||||
internal AsyncLazy(UniTask<T> task)
|
||||
{
|
||||
this.valueFactory = null;
|
||||
this.target = value;
|
||||
this.taskFactory = null;
|
||||
this.completionSource = new UniTaskCompletionSource<T>();
|
||||
this.syncLock = null;
|
||||
this.initialized = true;
|
||||
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
SetCompletionSource(awaiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
awaiter.SourceOnCompleted(continuation, this);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask<T> Task => EnsureInitialized();
|
||||
public UniTask<T> Task
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return completionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask<T>.Awaiter GetAwaiter() => EnsureInitialized().GetAwaiter();
|
||||
|
||||
UniTask<T> EnsureInitialized()
|
||||
public UniTask<T>.Awaiter GetAwaiter() => Task.GetAwaiter();
|
||||
|
||||
void EnsureInitialized()
|
||||
{
|
||||
if (Volatile.Read(ref initialized))
|
||||
{
|
||||
return target;
|
||||
return;
|
||||
}
|
||||
|
||||
return EnsureInitializedCore();
|
||||
EnsureInitializedCore();
|
||||
}
|
||||
|
||||
UniTask<T> EnsureInitializedCore()
|
||||
void EnsureInitializedCore()
|
||||
{
|
||||
lock (syncLock)
|
||||
{
|
||||
if (!Volatile.Read(ref initialized))
|
||||
{
|
||||
var f = Interlocked.Exchange(ref valueFactory, null);
|
||||
var f = Interlocked.Exchange(ref taskFactory, null);
|
||||
if (f != null)
|
||||
{
|
||||
target = f().Preserve(); // with preserve(allow multiple await).
|
||||
var task = f();
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
SetCompletionSource(awaiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.awaiter = awaiter;
|
||||
awaiter.SourceOnCompleted(continuation, this);
|
||||
}
|
||||
|
||||
Volatile.Write(ref initialized, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
void SetCompletionSource(in UniTask<T>.Awaiter awaiter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = awaiter.GetResult();
|
||||
completionSource.TrySetResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCompletionSource(object state)
|
||||
{
|
||||
var self = (AsyncLazy<T>)state;
|
||||
try
|
||||
{
|
||||
var result = self.awaiter.GetResult();
|
||||
self.completionSource.TrySetResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
self.awaiter = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,14 +143,6 @@ namespace Cysharp.Threading.Tasks
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitAsyncSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (WaitAsyncSource)state;
|
||||
@@ -468,14 +460,6 @@ namespace Cysharp.Threading.Tasks
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitAsyncSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (WaitAsyncSource)state;
|
||||
|
||||
@@ -11,6 +11,55 @@ namespace Cysharp.Threading.Tasks
|
||||
static readonly Action<object> cancellationTokenCallback = Callback;
|
||||
static readonly Action<object> disposeCallback = DisposeCallback;
|
||||
|
||||
public static CancellationToken ToCancellationToken(this UniTask task)
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
ToCancellationTokenCore(task, cts).Forget();
|
||||
return cts.Token;
|
||||
}
|
||||
|
||||
public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken)
|
||||
{
|
||||
if (linkToken.IsCancellationRequested)
|
||||
{
|
||||
return linkToken;
|
||||
}
|
||||
|
||||
if (!linkToken.CanBeCanceled)
|
||||
{
|
||||
return ToCancellationToken(task);
|
||||
}
|
||||
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(linkToken);
|
||||
ToCancellationTokenCore(task, cts).Forget();
|
||||
|
||||
return cts.Token;
|
||||
}
|
||||
|
||||
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
|
||||
{
|
||||
return ToCancellationToken(task.AsUniTask());
|
||||
}
|
||||
|
||||
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)
|
||||
{
|
||||
return ToCancellationToken(task.AsUniTask(), linkToken);
|
||||
}
|
||||
|
||||
static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
cts.Cancel();
|
||||
cts.Dispose();
|
||||
}
|
||||
|
||||
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
|
||||
@@ -9,15 +9,15 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static class CancellationTokenSourceExtensions
|
||||
{
|
||||
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||
{
|
||||
var delay = UniTask.Delay(millisecondsDelay, ignoreTimeScale, delayTiming, cts.Token);
|
||||
var delay = UniTask.Delay(millisecondsDelay, delayType, delayTiming, cts.Token);
|
||||
CancelAfterCore(cts, delay).Forget();
|
||||
}
|
||||
|
||||
public static void CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||
public static void CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||
{
|
||||
var delay = UniTask.Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cts.Token);
|
||||
var delay = UniTask.Delay(delayTimeSpan, delayType, delayTiming, cts.Token);
|
||||
CancelAfterCore(cts, delay).Forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
@@ -8,6 +8,10 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
{
|
||||
// #ENABLE_IL2CPP in this file is to avoid bug of IL2CPP VM.
|
||||
// Issue is tracked on https://issuetracker.unity3d.com/issues/il2cpp-incorrect-results-when-calling-a-method-from-outside-class-in-a-struct
|
||||
// but currently it is labeled `Won't Fix`.
|
||||
|
||||
internal interface IStateMachineRunner
|
||||
{
|
||||
Action MoveNext { get; }
|
||||
@@ -239,14 +243,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~AsyncUniTask()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
|
||||
@@ -376,14 +372,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~AsyncUniTask()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
IEnumerator innerEnumerator;
|
||||
CancellationToken cancellationToken;
|
||||
int initialFrame;
|
||||
|
||||
UniTaskCompletionSourceCore<object> core;
|
||||
|
||||
@@ -66,10 +67,13 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.initialFrame = -1;
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
|
||||
result.MoveNext(); // run immediately.
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -108,6 +112,19 @@ namespace Cysharp.Threading.Tasks
|
||||
return false;
|
||||
}
|
||||
|
||||
if (initialFrame == -1)
|
||||
{
|
||||
// Time can not touch in threadpool.
|
||||
if (PlayerLoopHelper.IsMainThread)
|
||||
{
|
||||
initialFrame = Time.frameCount;
|
||||
}
|
||||
}
|
||||
else if (initialFrame == Time.frameCount)
|
||||
{
|
||||
return true; // already executed in first frame, skip.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (innerEnumerator.MoveNext())
|
||||
@@ -134,14 +151,6 @@ namespace Cysharp.Threading.Tasks
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~EnumeratorPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrap YieldInstructions
|
||||
|
||||
static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
|
||||
@@ -216,12 +225,12 @@ namespace Cysharp.Threading.Tasks
|
||||
static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
|
||||
{
|
||||
var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
|
||||
var startTime = DateTimeOffset.UtcNow;
|
||||
var elapsed = 0.0f;
|
||||
while (true)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
var elapsed = (DateTimeOffset.UtcNow - startTime).TotalSeconds;
|
||||
elapsed += Time.deltaTime;
|
||||
if (elapsed >= second)
|
||||
{
|
||||
break;
|
||||
|
||||
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/Addressables.meta
vendored
Normal file
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/Addressables.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5b9231662e24c942b544bd85d4b39cb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -11,24 +11,38 @@ using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static class AddressableAsyncExtensions
|
||||
public static class AddressablesAsyncExtensions
|
||||
{
|
||||
#region AsyncOperationHandle
|
||||
|
||||
public static AsyncOperationHandleAwaiter GetAwaiter(this AsyncOperationHandle handle)
|
||||
public static UniTask.Awaiter GetAwaiter(this AsyncOperationHandle handle)
|
||||
{
|
||||
return new AsyncOperationHandleAwaiter(handle);
|
||||
return ToUniTask(handle).GetAwaiter();
|
||||
}
|
||||
|
||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
||||
{
|
||||
if (handle.IsDone) return UniTask.CompletedTask;
|
||||
return new UniTask(AsyncOperationHandleWithCancellationSource.Create(handle, cancellationToken, out var token), token);
|
||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (handle.IsDone) return UniTask.CompletedTask;
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||
|
||||
if (!handle.IsValid())
|
||||
{
|
||||
throw new Exception("Attempting to use an invalid operation handle");
|
||||
}
|
||||
|
||||
if (handle.IsDone)
|
||||
{
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
return UniTask.FromException(handle.OperationException);
|
||||
}
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
@@ -77,29 +91,30 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AsyncOperationHandleWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource>
|
||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||
{
|
||||
static TaskPool<AsyncOperationHandleWithCancellationSource> pool;
|
||||
public AsyncOperationHandleWithCancellationSource NextNode { get; set; }
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
|
||||
|
||||
static AsyncOperationHandleWithCancellationSource()
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource), () => pool.Size);
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||
}
|
||||
|
||||
readonly Action<AsyncOperationHandle> continuationAction;
|
||||
AsyncOperationHandle handle;
|
||||
CancellationToken cancellationToken;
|
||||
IProgress<float> progress;
|
||||
bool completed;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
AsyncOperationHandleWithCancellationSource()
|
||||
AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
continuationAction = Continuation;
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(AsyncOperationHandle handle, CancellationToken cancellationToken, out short token)
|
||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -108,16 +123,17 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AsyncOperationHandleWithCancellationSource();
|
||||
result = new AsyncOperationHandleConfiguredSource();
|
||||
}
|
||||
|
||||
result.handle = handle;
|
||||
result.progress = progress;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.completed = false;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
handle.Completed += result.continuationAction;
|
||||
|
||||
@@ -136,7 +152,11 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
else if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
core.TrySetException(handle.OperationException);
|
||||
}
|
||||
@@ -182,238 +202,84 @@ namespace Cysharp.Threading.Tasks
|
||||
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>
|
||||
{
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
|
||||
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||
}
|
||||
|
||||
AsyncOperationHandle handle;
|
||||
IProgress<float> progress;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AsyncOperationHandleConfiguredSource();
|
||||
}
|
||||
|
||||
result.handle = handle;
|
||||
result.progress = progress;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
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 (progress != null)
|
||||
if (progress != null && handle.IsValid())
|
||||
{
|
||||
progress.Report(handle.PercentComplete);
|
||||
}
|
||||
|
||||
if (handle.IsDone)
|
||||
{
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
core.TrySetException(handle.OperationException);
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryReturn()
|
||||
{
|
||||
core.Reset();
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
handle = default;
|
||||
progress = default;
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AsyncOperationHandle_T
|
||||
|
||||
public static AsyncOperationHandleAwaiter<T> GetAwaiter<T>(this AsyncOperationHandle<T> handle)
|
||||
public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> handle)
|
||||
{
|
||||
return new AsyncOperationHandleAwaiter<T>(handle);
|
||||
return ToUniTask(handle).GetAwaiter();
|
||||
}
|
||||
|
||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
||||
{
|
||||
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||
return new UniTask<T>(AsyncOperationHandleWithCancellationSource<T>.Create(handle, cancellationToken, out var token), token);
|
||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
||||
|
||||
if (!handle.IsValid())
|
||||
{
|
||||
throw new Exception("Attempting to use an invalid operation handle");
|
||||
}
|
||||
|
||||
if (handle.IsDone)
|
||||
{
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
return UniTask.FromException<T>(handle.OperationException);
|
||||
}
|
||||
return UniTask.FromResult(handle.Result);
|
||||
}
|
||||
|
||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
public struct AsyncOperationHandleAwaiter<T> : ICriticalNotifyCompletion
|
||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||
{
|
||||
AsyncOperationHandle<T> handle;
|
||||
Action<AsyncOperationHandle> continuationAction;
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
|
||||
|
||||
public AsyncOperationHandleAwaiter(AsyncOperationHandle<T> handle)
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
this.handle = handle;
|
||||
this.continuationAction = null;
|
||||
}
|
||||
|
||||
public bool IsCompleted => handle.IsDone;
|
||||
|
||||
public T GetResult()
|
||||
{
|
||||
if (continuationAction != null)
|
||||
{
|
||||
handle.CompletedTypeless -= continuationAction;
|
||||
continuationAction = null;
|
||||
}
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
var e = handle.OperationException;
|
||||
handle = default;
|
||||
ExceptionDispatchInfo.Capture(e).Throw();
|
||||
}
|
||||
|
||||
var result = handle.Result;
|
||||
handle = default;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
UnsafeOnCompleted(continuation);
|
||||
}
|
||||
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||
continuationAction = PooledDelegate<AsyncOperationHandle>.Create(continuation);
|
||||
handle.CompletedTypeless += continuationAction;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||
}
|
||||
|
||||
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
||||
AsyncOperationHandle<T> handle;
|
||||
CancellationToken cancellationToken;
|
||||
IProgress<float> progress;
|
||||
bool completed;
|
||||
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
|
||||
AsyncOperationHandleWithCancellationSource()
|
||||
AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
continuationAction = Continuation;
|
||||
}
|
||||
|
||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, CancellationToken cancellationToken, out short token)
|
||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -422,16 +288,17 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AsyncOperationHandleWithCancellationSource<T>();
|
||||
result = new AsyncOperationHandleConfiguredSource<T>();
|
||||
}
|
||||
|
||||
result.handle = handle;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.completed = false;
|
||||
result.progress = progress;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
handle.Completed += result.continuationAction;
|
||||
|
||||
@@ -439,7 +306,7 @@ namespace Cysharp.Threading.Tasks
|
||||
return result;
|
||||
}
|
||||
|
||||
void Continuation(AsyncOperationHandle<T> _)
|
||||
void Continuation(AsyncOperationHandle<T> argHandle)
|
||||
{
|
||||
handle.Completed -= continuationAction;
|
||||
|
||||
@@ -450,13 +317,17 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetException(handle.OperationException);
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
core.TrySetException(argHandle.OperationException);
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(handle.Result);
|
||||
core.TrySetResult(argHandle.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,130 +372,11 @@ namespace Cysharp.Threading.Tasks
|
||||
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>>
|
||||
{
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
|
||||
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||
}
|
||||
|
||||
AsyncOperationHandle<T> handle;
|
||||
IProgress<float> progress;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
|
||||
AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AsyncOperationHandleConfiguredSource<T>();
|
||||
}
|
||||
|
||||
result.handle = handle;
|
||||
result.progress = progress;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
return result;
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
try
|
||||
{
|
||||
return core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryReturn();
|
||||
}
|
||||
}
|
||||
|
||||
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 (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (progress != null)
|
||||
if (progress != null && handle.IsValid())
|
||||
{
|
||||
progress.Report(handle.PercentComplete);
|
||||
}
|
||||
|
||||
if (handle.IsDone)
|
||||
{
|
||||
if (handle.Status == AsyncOperationStatus.Failed)
|
||||
{
|
||||
core.TrySetException(handle.OperationException);
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(handle.Result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -637,14 +389,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef
vendored
Normal file
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "UniTask.Addressables",
|
||||
"references": [
|
||||
"UniTask",
|
||||
"Unity.ResourceManager"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.addressables",
|
||||
"expression": "",
|
||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 593a5b492d29ac6448b1ebf7f035ef33
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween.meta
vendored
Normal file
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25cb2f742bfeb1d48a4e65d3140b955d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -11,7 +11,6 @@ using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
// The idea of TweenCancelBehaviour is borrowed from https://www.shibuya24.info/entry/dotween_async_await
|
||||
public enum TweenCancelBehaviour
|
||||
{
|
||||
Kill,
|
||||
@@ -29,6 +28,16 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public static class DOTweenAsyncExtensions
|
||||
{
|
||||
enum CallbackType
|
||||
{
|
||||
Kill,
|
||||
Complete,
|
||||
Pause,
|
||||
Play,
|
||||
Rewind,
|
||||
StepComplete
|
||||
}
|
||||
|
||||
public static TweenAwaiter GetAwaiter(this Tween tween)
|
||||
{
|
||||
return new TweenAwaiter(tween);
|
||||
@@ -39,7 +48,7 @@ namespace Cysharp.Threading.Tasks
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, out var token), token);
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, CallbackType.Kill, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
@@ -47,7 +56,47 @@ namespace Cysharp.Threading.Tasks
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, out var token), token);
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Kill, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Complete, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForPause(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Pause, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForPlay(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Play, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForRewind(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Rewind, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForStepComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.StepComplete, out var token), token);
|
||||
}
|
||||
|
||||
public struct TweenAwaiter : ICriticalNotifyCompletion
|
||||
@@ -95,12 +144,13 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
static readonly TweenCallback EmptyTweenCallback = () => { };
|
||||
|
||||
readonly TweenCallback onKillDelegate;
|
||||
readonly TweenCallback onCompleteCallbackDelegate;
|
||||
readonly TweenCallback onUpdateDelegate;
|
||||
|
||||
Tween tween;
|
||||
TweenCancelBehaviour cancelBehaviour;
|
||||
CancellationToken cancellationToken;
|
||||
CallbackType callbackType;
|
||||
bool canceled;
|
||||
|
||||
TweenCallback originalUpdateAction;
|
||||
@@ -108,11 +158,11 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
TweenConfiguredSource()
|
||||
{
|
||||
onKillDelegate = OnKill;
|
||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
||||
onUpdateDelegate = OnUpdate;
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
|
||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -128,6 +178,7 @@ namespace Cysharp.Threading.Tasks
|
||||
result.tween = tween;
|
||||
result.cancelBehaviour = cancelBehaviour;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.callbackType = callbackType;
|
||||
|
||||
result.originalUpdateAction = tween.onUpdate;
|
||||
result.canceled = false;
|
||||
@@ -138,7 +189,30 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
tween.onUpdate = result.onUpdateDelegate;
|
||||
tween.onKill = result.onKillDelegate;
|
||||
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
@@ -146,7 +220,7 @@ namespace Cysharp.Threading.Tasks
|
||||
return result;
|
||||
}
|
||||
|
||||
void OnKill()
|
||||
void OnCompleteCallbackDelegate()
|
||||
{
|
||||
if (canceled)
|
||||
{
|
||||
@@ -199,7 +273,31 @@ namespace Cysharp.Threading.Tasks
|
||||
this.tween.Complete(true);
|
||||
break;
|
||||
case TweenCancelBehaviour.CancelAwait:
|
||||
this.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||
// replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = EmptyTweenCallback;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.core.TrySetCanceled(this.cancellationToken);
|
||||
break;
|
||||
}
|
||||
@@ -272,20 +370,36 @@ namespace Cysharp.Threading.Tasks
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
tween.onUpdate = originalUpdateAction;
|
||||
tween.onKill = null;
|
||||
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = null;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = null;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = null;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = null;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = null;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tween = default;
|
||||
cancellationToken = default;
|
||||
originalUpdateAction = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~TweenConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef
vendored
Normal file
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "UniTask.DOTween",
|
||||
"references": [
|
||||
"UniTask",
|
||||
"DOTween.Modules"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.demigiant.dotween",
|
||||
"expression": "",
|
||||
"define": "UNITASK_DOTWEEN_SUPPORT"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef.meta
vendored
Normal file
7
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef.meta
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 029c1c1b674aaae47a6841a0b89ad80e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro.meta
vendored
Normal file
8
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f89da606bde9a4e4e94ae1189a029887
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,224 @@
|
||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using TMPro;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class TextMeshProAsyncExtensions
|
||||
{
|
||||
public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<string> OnSelectAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<string> OnSelectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, cancellationToken);
|
||||
}
|
||||
|
||||
public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79f4f2475e0b2c44e97ed1dee760627b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
<#@ template debug="false" hostspecific="false" language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#
|
||||
var handlers = new (string name, string type)[] {
|
||||
("ValueChanged", "string"),
|
||||
("EndEdit", "string"),
|
||||
("EndTextSelection", "(string, int, int)"),
|
||||
("TextSelection", "(string, int, int)"),
|
||||
("Deselect", "string"),
|
||||
("Select", "string"),
|
||||
("Submit", "string"),
|
||||
};
|
||||
|
||||
Func<string, bool> shouldConvert = x => x.EndsWith("TextSelection");
|
||||
Func<string, string> eventName = x => shouldConvert(x) ? $"new TextSelectionEventConverter(inputField.on{x})" : $"inputField.on{x}";
|
||||
#>
|
||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using TMPro;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class TextMeshProAsyncExtensions
|
||||
{
|
||||
<# foreach(var (name, type) in handlers) { #>
|
||||
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), false);
|
||||
}
|
||||
|
||||
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField)
|
||||
{
|
||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, true).OnInvokeAsync();
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
||||
{
|
||||
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, cancellationToken);
|
||||
}
|
||||
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9bb9fc551a975d44a7180e022a2debe
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
130
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs
vendored
Normal file
130
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using TMPro;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class TextMeshProAsyncExtensions
|
||||
{
|
||||
// <string> -> Text
|
||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||
}
|
||||
|
||||
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||
{
|
||||
var repeat = false;
|
||||
BIND_AGAIN:
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
bool moveNext;
|
||||
try
|
||||
{
|
||||
moveNext = await e.MoveNextAsync();
|
||||
repeat = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
if (rebindOnError && !repeat)
|
||||
{
|
||||
repeat = true;
|
||||
goto BIND_AGAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (!moveNext) return;
|
||||
|
||||
text.text = e.Current;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <T> -> Text
|
||||
|
||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo<T>(this AsyncReactiveProperty<T> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||
{
|
||||
var repeat = false;
|
||||
BIND_AGAIN:
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
bool moveNext;
|
||||
try
|
||||
{
|
||||
moveNext = await e.MoveNextAsync();
|
||||
repeat = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
if (rebindOnError && !repeat)
|
||||
{
|
||||
repeat = true;
|
||||
goto BIND_AGAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (!moveNext) return;
|
||||
|
||||
text.text = e.Current.ToString();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6ba480edafb67d4e91bb10feb64fae5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef
vendored
Normal file
22
src/UniTask/Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "UniTask.TextMeshPro",
|
||||
"references": [
|
||||
"UniTask",
|
||||
"Unity.TextMeshPro"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.textmeshpro",
|
||||
"expression": "",
|
||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc47925d1a5fa2946bdd37746b2b5d48
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,7 +9,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
{
|
||||
const int MaxArrayLength = 0X7FEFFFFF;
|
||||
const int InitialSize = 16;
|
||||
|
||||
|
||||
readonly PlayerLoopTiming timing;
|
||||
|
||||
SpinLock gate = new SpinLock();
|
||||
@@ -173,7 +173,14 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
var action = actionList[i];
|
||||
actionList[i] = null;
|
||||
|
||||
action();
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Internal
|
||||
{
|
||||
internal static class UnityWebRequestResultExtensions
|
||||
{
|
||||
public static bool IsError(this UnityWebRequest unityWebRequest)
|
||||
{
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
var result = unityWebRequest.result;
|
||||
return (result == UnityWebRequest.Result.ConnectionError)
|
||||
|| (result == UnityWebRequest.Result.DataProcessingError)
|
||||
|| (result == UnityWebRequest.Result.ProtocolError);
|
||||
#else
|
||||
return unityWebRequest.isHttpError || unityWebRequest.isNetworkError;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 111ba0e639de1d7428af6c823ead4918
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Internal
|
||||
{
|
||||
internal readonly struct ValueStopwatch
|
||||
{
|
||||
static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
|
||||
|
||||
readonly long startTimestamp;
|
||||
|
||||
public static ValueStopwatch StartNew() => new ValueStopwatch(Stopwatch.GetTimestamp());
|
||||
|
||||
ValueStopwatch(long startTimestamp)
|
||||
{
|
||||
this.startTimestamp = startTimestamp;
|
||||
}
|
||||
|
||||
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
|
||||
|
||||
public long ElapsedTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (startTimestamp == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Detected invalid initialization(use 'default'), only to create from StartNew().");
|
||||
}
|
||||
|
||||
var delta = Stopwatch.GetTimestamp() - startTimestamp;
|
||||
return (long)(delta * TimestampToTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f16fb466974ad034c8732c79c7fd67ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
174
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Create.cs
Normal file
174
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Create.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<T> Create<T>(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
||||
{
|
||||
Error.ThrowArgumentNullException(create, nameof(create));
|
||||
return new Create<T>(create);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAsyncWriter<T>
|
||||
{
|
||||
UniTask YieldAsync(T value);
|
||||
}
|
||||
|
||||
internal sealed class Create<T> : IUniTaskAsyncEnumerable<T>
|
||||
{
|
||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
||||
|
||||
public Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
||||
{
|
||||
this.create = create;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _Create(create, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Create : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
AsyncWriter writer;
|
||||
|
||||
public _Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create, CancellationToken cancellationToken)
|
||||
{
|
||||
this.create = create;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public T Current { get; private set; }
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return default;
|
||||
}
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
{
|
||||
writer = new AsyncWriter(this);
|
||||
RunWriterTask(create(writer, cancellationToken)).Forget();
|
||||
if (Volatile.Read(ref state) == -2)
|
||||
{
|
||||
return; // complete synchronously
|
||||
}
|
||||
state = 0; // wait YieldAsync, it set TrySetResult(true)
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
writer.SignalWriter();
|
||||
return;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
|
||||
async UniTaskVoid RunWriterTask(UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
goto DONE;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Volatile.Write(ref state, -2);
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
Volatile.Write(ref state, -2);
|
||||
completionSource.TrySetResult(false);
|
||||
}
|
||||
|
||||
public void SetResult(T value)
|
||||
{
|
||||
Current = value;
|
||||
completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
|
||||
{
|
||||
readonly _Create enumerator;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
public AsyncWriter(_Create enumerator)
|
||||
{
|
||||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
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 UniTask YieldAsync(T value)
|
||||
{
|
||||
core.Reset();
|
||||
enumerator.SetResult(value);
|
||||
return new UniTask(this, core.Version);
|
||||
}
|
||||
|
||||
public void SignalWriter()
|
||||
{
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0202f723469f93945afa063bfb440d15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -88,6 +88,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -156,6 +157,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -195,6 +197,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -263,6 +266,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -302,6 +306,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -382,6 +387,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -422,6 +428,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -502,6 +509,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -541,6 +549,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -621,6 +630,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -661,6 +671,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
@@ -741,6 +752,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
187
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/SkipUntil.cs
Normal file
187
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/SkipUntil.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, UniTask other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return new SkipUntil<TSource>(source, other, null);
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<CancellationToken, UniTask> other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(source, nameof(other));
|
||||
|
||||
return new SkipUntil<TSource>(source, default, other);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SkipUntil<TSource> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly UniTask other;
|
||||
readonly Func<CancellationToken, UniTask> other2;
|
||||
|
||||
public SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, Func<CancellationToken, UniTask> other2)
|
||||
{
|
||||
this.source = source;
|
||||
this.other = other;
|
||||
this.other2 = other2;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (other2 != null)
|
||||
{
|
||||
return new _SkipUntil(source, this.other2(cancellationToken), cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new _SkipUntil(source, this.other, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class _SkipUntil : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken1;
|
||||
|
||||
bool completed;
|
||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
bool continueNext;
|
||||
Exception exception;
|
||||
|
||||
public _SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, CancellationToken cancellationToken1)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken1 = cancellationToken1;
|
||||
if (cancellationToken1.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
RunOther(other).Forget();
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
return UniTask.FromException<bool>(exception);
|
||||
}
|
||||
|
||||
if (cancellationToken1.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled<bool>(cancellationToken1);
|
||||
}
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken1);
|
||||
}
|
||||
completionSource.Reset();
|
||||
|
||||
if (completed)
|
||||
{
|
||||
SourceMoveNext();
|
||||
}
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void SourceMoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
LOOP:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
continueNext = true;
|
||||
MoveNextCore(this);
|
||||
if (continueNext)
|
||||
{
|
||||
continueNext = false;
|
||||
goto LOOP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void MoveNextCore(object state)
|
||||
{
|
||||
var self = (_SkipUntil)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
self.Current = self.enumerator.Current;
|
||||
self.completionSource.TrySetResult(true);
|
||||
if (self.continueNext)
|
||||
{
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async UniTaskVoid RunOther(UniTask other)
|
||||
{
|
||||
try
|
||||
{
|
||||
await other;
|
||||
completed = true;
|
||||
SourceMoveNext();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnCanceled1(object state)
|
||||
{
|
||||
var self = (_SkipUntil)state;
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
cancellationTokenRegistration1.Dispose();
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de932d79c8d9f3841a066d05ff29edc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -32,13 +32,17 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
sealed class _SkipUntilCanceled : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
||||
static readonly Action<object> CancelDelegate2 = OnCanceled2;
|
||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken1;
|
||||
CancellationToken cancellationToken2;
|
||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
||||
CancellationTokenRegistration cancellationTokenRegistration2;
|
||||
|
||||
bool isCanceled;
|
||||
int isCanceled;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
bool continueNext;
|
||||
@@ -48,6 +52,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.source = source;
|
||||
this.cancellationToken1 = cancellationToken1;
|
||||
this.cancellationToken2 = cancellationToken2;
|
||||
if (cancellationToken1.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
||||
}
|
||||
if (cancellationToken1 != cancellationToken2 && cancellationToken2.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(CancelDelegate2, this);
|
||||
}
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
@@ -55,15 +67,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (cancellationToken1.IsCancellationRequested) isCanceled = true;
|
||||
if (cancellationToken2.IsCancellationRequested) isCanceled = true;
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
if (cancellationToken1.IsCancellationRequested) isCanceled = 1;
|
||||
if (cancellationToken2.IsCancellationRequested) isCanceled = 1;
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken2); // use only AsyncEnumerator provided token.
|
||||
}
|
||||
completionSource.Reset();
|
||||
SourceMoveNext();
|
||||
|
||||
if (isCanceled != 0)
|
||||
{
|
||||
SourceMoveNext();
|
||||
}
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
@@ -102,25 +117,11 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
AGAIN:
|
||||
|
||||
if (self.isCanceled)
|
||||
self.Current = self.enumerator.Current;
|
||||
self.completionSource.TrySetResult(true);
|
||||
if (self.continueNext)
|
||||
{
|
||||
self.continueNext = false;
|
||||
self.Current = self.enumerator.Current;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.cancellationToken1.IsCancellationRequested) self.isCanceled = true;
|
||||
if (self.cancellationToken2.IsCancellationRequested) self.isCanceled = true;
|
||||
|
||||
if (self.isCanceled) goto AGAIN;
|
||||
|
||||
if (!self.continueNext)
|
||||
{
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -130,9 +131,37 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
}
|
||||
}
|
||||
|
||||
static void OnCanceled1(object state)
|
||||
{
|
||||
var self = (_SkipUntilCanceled)state;
|
||||
if (self.isCanceled == 0)
|
||||
{
|
||||
if (Interlocked.Increment(ref self.isCanceled) == 1)
|
||||
{
|
||||
self.cancellationTokenRegistration2.Dispose();
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OnCanceled2(object state)
|
||||
{
|
||||
var self = (_SkipUntilCanceled)state;
|
||||
if (self.isCanceled == 0)
|
||||
{
|
||||
if (Interlocked.Increment(ref self.isCanceled) == 1)
|
||||
{
|
||||
self.cancellationTokenRegistration2.Dispose();
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
cancellationTokenRegistration1.Dispose();
|
||||
cancellationTokenRegistration2.Dispose();
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
|
||||
@@ -29,6 +29,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(action, nameof(action));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
@@ -45,6 +55,50 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(action, nameof(action));
|
||||
|
||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// OnNext, OnError
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
|
||||
@@ -87,6 +141,46 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// OnNext, OnCompleted
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
|
||||
@@ -129,6 +223,46 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// IObserver
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
|
||||
@@ -177,7 +311,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
onNext(e.Current);
|
||||
try
|
||||
{
|
||||
onNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
@@ -209,7 +350,53 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
onNext(e.Current).Forget();
|
||||
try
|
||||
{
|
||||
onNext(e.Current).Forget();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (onError == NopError)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
onError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
onNext(e.Current, cancellationToken).Forget();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
@@ -241,7 +428,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
observer.OnNext(e.Current);
|
||||
try
|
||||
{
|
||||
observer.OnNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
observer.OnCompleted();
|
||||
}
|
||||
@@ -259,5 +453,84 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
await onNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (onError == NopError)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
onError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
await onNext(e.Current, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (onError == NopError)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
onError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 263479eb04c189741931fc0e2f615c2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
190
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/TakeUntil.cs
Normal file
190
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/TakeUntil.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<TSource> TakeUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, UniTask other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return new TakeUntil<TSource>(source, other, null);
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TSource> TakeUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<CancellationToken, UniTask> other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(source, nameof(other));
|
||||
|
||||
return new TakeUntil<TSource>(source, default, other);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class TakeUntil<TSource> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly UniTask other;
|
||||
readonly Func<CancellationToken, UniTask> other2;
|
||||
|
||||
public TakeUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, Func<CancellationToken, UniTask> other2)
|
||||
{
|
||||
this.source = source;
|
||||
this.other = other;
|
||||
this.other2 = other2;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (other2 != null)
|
||||
{
|
||||
return new _TakeUntil(source, this.other2(cancellationToken), cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new _TakeUntil(source, this.other, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class _TakeUntil : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken1;
|
||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
||||
|
||||
bool completed;
|
||||
Exception exception;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
|
||||
public _TakeUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, CancellationToken cancellationToken1)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken1 = cancellationToken1;
|
||||
|
||||
if (cancellationToken1.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
|
||||
RunOther(other).Forget();
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
return CompletedTasks.False;
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
return UniTask.FromException<bool>(exception);
|
||||
}
|
||||
|
||||
if (cancellationToken1.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled<bool>(cancellationToken1);
|
||||
}
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken1);
|
||||
}
|
||||
|
||||
completionSource.Reset();
|
||||
SourceMoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void SourceMoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
MoveNextCore(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void MoveNextCore(object state)
|
||||
{
|
||||
var self = (_TakeUntil)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
if (self.exception != null)
|
||||
{
|
||||
self.completionSource.TrySetException(self.exception);
|
||||
}
|
||||
else if (self.cancellationToken1.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.Current = self.enumerator.Current;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async UniTaskVoid RunOther(UniTask other)
|
||||
{
|
||||
try
|
||||
{
|
||||
await other;
|
||||
completed = true;
|
||||
completionSource.TrySetResult(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnCanceled1(object state)
|
||||
{
|
||||
var self = (_TakeUntil)state;
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
cancellationTokenRegistration1.Dispose();
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12bda324162f15349afefc2c152ac07f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -19,8 +19,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||
{
|
||||
// UnityEngine.Debug.Log("Called ToArray");
|
||||
|
||||
var pool = ArrayPool<TSource>.Shared;
|
||||
var array = pool.Rent(16);
|
||||
|
||||
|
||||
@@ -208,7 +208,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
UnityEngine.Debug.Log("TRY_RESULT:" + target.TryGetTarget(out var _));
|
||||
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
|
||||
{
|
||||
completionSource.TrySetResult(false);
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
if (this.period <= 0) this.period = 1;
|
||||
}
|
||||
|
||||
this.initialFrame = Time.frameCount;
|
||||
this.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
this.dueTimePhase = true;
|
||||
this.updateTiming = updateTiming;
|
||||
this.ignoreTimeScale = ignoreTimeScale;
|
||||
@@ -220,7 +220,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
if (periodFrameCount <= 0) periodFrameCount = 1;
|
||||
}
|
||||
|
||||
this.initialFrame = Time.frameCount;
|
||||
this.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
this.dueTimePhase = true;
|
||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||
this.periodFrameCount = periodFrameCount;
|
||||
|
||||
@@ -88,6 +88,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -165,6 +166,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -204,6 +206,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -281,6 +284,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -320,6 +324,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -410,6 +415,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -450,6 +456,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -540,6 +547,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -579,6 +587,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -669,6 +678,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -709,6 +719,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
this.predicate = predicate;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
@@ -799,6 +810,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,8 @@ namespace Cysharp.Threading.Tasks
|
||||
public static int MainThreadId => mainThreadId;
|
||||
internal static string ApplicationDataPath => applicationDataPath;
|
||||
|
||||
public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadId;
|
||||
|
||||
static int mainThreadId;
|
||||
static string applicationDataPath;
|
||||
static SynchronizationContext unitySynchronizationContetext;
|
||||
@@ -173,6 +175,32 @@ namespace Cysharp.Threading.Tasks
|
||||
return dest;
|
||||
}
|
||||
|
||||
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
|
||||
{
|
||||
var loop = new PlayerLoopSystem
|
||||
{
|
||||
type = typeof(UniTaskSynchronizationContext),
|
||||
updateDelegate = UniTaskSynchronizationContext.Run
|
||||
};
|
||||
|
||||
// Remove items from previous initializations.
|
||||
var source = loopSystem.subSystemList
|
||||
.Where(ls => ls.type != typeof(UniTaskSynchronizationContext))
|
||||
.ToArray();
|
||||
|
||||
var dest = new System.Collections.Generic.List<PlayerLoopSystem>(source);
|
||||
|
||||
var index = dest.FindIndex(x => x.type.Name == "ScriptRunDelayedTasks");
|
||||
if (index == -1)
|
||||
{
|
||||
index = dest.FindIndex(x => x.type.Name == "UniTaskLoopRunnerUpdate");
|
||||
}
|
||||
|
||||
dest.Insert(index + 1, loop);
|
||||
|
||||
return dest.ToArray();
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
static void Init()
|
||||
{
|
||||
@@ -244,6 +272,8 @@ namespace Cysharp.Threading.Tasks
|
||||
if (item != null) item.Run();
|
||||
}
|
||||
}
|
||||
|
||||
UniTaskSynchronizationContext.Run();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -291,6 +321,9 @@ namespace Cysharp.Threading.Tasks
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(PlayerLoopTiming.PostLateUpdate),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner(PlayerLoopTiming.LastPostLateUpdate));
|
||||
|
||||
// Insert UniTaskSynchronizationContext to Update loop
|
||||
copyList[4].subSystemList = InsertUniTaskSynchronizationContext(copyList[4]);
|
||||
|
||||
playerLoop.subSystemList = copyList;
|
||||
PlayerLoop.SetPlayerLoop(playerLoop);
|
||||
}
|
||||
@@ -304,6 +337,56 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
yielders[(int)timing].Enqueue(continuation);
|
||||
}
|
||||
|
||||
// Diagnostics helper
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
|
||||
public static void DumpCurrentPlayerLoop()
|
||||
{
|
||||
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop();
|
||||
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine($"PlayerLoop List");
|
||||
foreach (var header in playerLoop.subSystemList)
|
||||
{
|
||||
sb.AppendFormat("------{0}------", header.type.Name);
|
||||
sb.AppendLine();
|
||||
foreach (var subSystem in header.subSystemList)
|
||||
{
|
||||
sb.AppendFormat("{0}", subSystem.type.Name);
|
||||
sb.AppendLine();
|
||||
|
||||
if (subSystem.subSystemList != null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("More Subsystem:" + subSystem.subSystemList.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnityEngine.Debug.Log(sb.ToString());
|
||||
}
|
||||
|
||||
public static bool IsInjectedUniTaskPlayerLoop()
|
||||
{
|
||||
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop();
|
||||
|
||||
foreach (var header in playerLoop.subSystemList)
|
||||
{
|
||||
foreach (var subSystem in header.subSystemList)
|
||||
{
|
||||
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
@@ -7,6 +8,16 @@ using UnityEngine;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public enum DelayType
|
||||
{
|
||||
/// <summary>use Time.deltaTime.</summary>
|
||||
DeltaTime,
|
||||
/// <summary>Ignore timescale, use Time.unscaledDeltaTime.</summary>
|
||||
UnscaledDeltaTime,
|
||||
/// <summary>use Stopwatch.GetTimestamp().</summary>
|
||||
Realtime
|
||||
}
|
||||
|
||||
public partial struct UniTask
|
||||
{
|
||||
public static YieldAwaitable Yield(PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
||||
@@ -73,26 +84,44 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||
if (delayTimeSpan < TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Delay does not allow minus millisecondsDelay. millisecondsDelay:" + millisecondsDelay);
|
||||
}
|
||||
|
||||
return (ignoreTimeScale)
|
||||
? new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token)
|
||||
: new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out token), token);
|
||||
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (delayTimeSpan < TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayTimeSpan. delayTimeSpan:" + delayTimeSpan);
|
||||
}
|
||||
|
||||
return (ignoreTimeScale)
|
||||
? new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token)
|
||||
: new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out token), token);
|
||||
switch (delayType)
|
||||
{
|
||||
case DelayType.UnscaledDeltaTime:
|
||||
{
|
||||
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||
}
|
||||
case DelayType.Realtime:
|
||||
{
|
||||
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||
}
|
||||
case DelayType.DeltaTime:
|
||||
default:
|
||||
{
|
||||
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
|
||||
@@ -181,14 +210,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~YieldPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
||||
@@ -221,7 +242,7 @@ namespace Cysharp.Threading.Tasks
|
||||
result = new NextFramePromise();
|
||||
}
|
||||
|
||||
result.frameCount = Time.frameCount;
|
||||
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
@@ -283,14 +304,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~NextFramePromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
||||
@@ -328,7 +341,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
result.delayFrameCount = delayFrameCount;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.initialFrame = Time.frameCount;
|
||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
@@ -406,14 +419,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~DelayFramePromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
|
||||
@@ -427,7 +432,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
int initialFrame;
|
||||
float delayFrameTimeSpan;
|
||||
float delayTimeSpan;
|
||||
float elapsed;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
@@ -437,7 +442,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -450,9 +455,9 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
result.elapsed = 0.0f;
|
||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.initialFrame = Time.frameCount;
|
||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
@@ -506,7 +511,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
elapsed += Time.deltaTime;
|
||||
if (elapsed >= delayFrameTimeSpan)
|
||||
if (elapsed >= delayTimeSpan)
|
||||
{
|
||||
core.TrySetResult(null);
|
||||
return false;
|
||||
@@ -519,19 +524,11 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
delayFrameTimeSpan = default;
|
||||
delayTimeSpan = default;
|
||||
elapsed = default;
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~DelayPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayIgnoreTimeScalePromise>
|
||||
@@ -569,7 +566,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
result.elapsed = 0.0f;
|
||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||
result.initialFrame = Time.frameCount;
|
||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
@@ -642,13 +639,103 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
|
||||
~DelayIgnoreTimeScalePromise()
|
||||
sealed class DelayRealtimePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayRealtimePromise>
|
||||
{
|
||||
static TaskPool<DelayRealtimePromise> pool;
|
||||
public DelayRealtimePromise NextNode { get; set; }
|
||||
|
||||
static DelayRealtimePromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
TaskPool.RegisterSizeGetter(typeof(DelayRealtimePromise), () => pool.Size);
|
||||
}
|
||||
|
||||
long delayTimeSpanTicks;
|
||||
ValueStopwatch stopwatch;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
DelayRealtimePromise()
|
||||
{
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new DelayRealtimePromise();
|
||||
}
|
||||
|
||||
result.stopwatch = ValueStopwatch.StartNew();
|
||||
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
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 (stopwatch.ElapsedTicks >= delayTimeSpanTicks)
|
||||
{
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryReturn()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
stopwatch = default;
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
@@ -11,10 +12,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
static readonly UniTask CanceledUniTask = new Func<UniTask>(() =>
|
||||
{
|
||||
var promise = new UniTaskCompletionSource();
|
||||
promise.TrySetCanceled(CancellationToken.None);
|
||||
promise.MarkHandled();
|
||||
return promise.Task;
|
||||
return new UniTask(new CanceledResultSource(CancellationToken.None), 0);
|
||||
})();
|
||||
|
||||
static class CanceledUniTaskCache<T>
|
||||
@@ -23,10 +21,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
static CanceledUniTaskCache()
|
||||
{
|
||||
var promise = new UniTaskCompletionSource<T>();
|
||||
promise.TrySetCanceled(CancellationToken.None);
|
||||
promise.MarkHandled();
|
||||
Task = promise.Task;
|
||||
Task = new UniTask<T>(new CanceledResultSource<T>(CancellationToken.None), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,18 +29,22 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public static UniTask FromException(Exception ex)
|
||||
{
|
||||
var promise = new UniTaskCompletionSource();
|
||||
promise.TrySetException(ex);
|
||||
promise.MarkHandled();
|
||||
return promise.Task;
|
||||
if (ex is OperationCanceledException oce)
|
||||
{
|
||||
return FromCanceled(oce.CancellationToken);
|
||||
}
|
||||
|
||||
return new UniTask(new ExceptionResultSource(ex), 0);
|
||||
}
|
||||
|
||||
public static UniTask<T> FromException<T>(Exception ex)
|
||||
{
|
||||
var promise = new UniTaskCompletionSource<T>();
|
||||
promise.TrySetException(ex);
|
||||
promise.MarkHandled();
|
||||
return promise.Task;
|
||||
if (ex is OperationCanceledException oce)
|
||||
{
|
||||
return FromCanceled<T>(oce.CancellationToken);
|
||||
}
|
||||
|
||||
return new UniTask<T>(new ExceptionResultSource<T>(ex), 0);
|
||||
}
|
||||
|
||||
public static UniTask<T> FromResult<T>(T value)
|
||||
@@ -61,10 +60,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
var promise = new UniTaskCompletionSource();
|
||||
promise.TrySetCanceled(cancellationToken);
|
||||
promise.MarkHandled();
|
||||
return promise.Task;
|
||||
return new UniTask(new CanceledResultSource(cancellationToken), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +72,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
var promise = new UniTaskCompletionSource<T>();
|
||||
promise.TrySetCanceled(cancellationToken);
|
||||
promise.MarkHandled();
|
||||
return promise.Task;
|
||||
return new UniTask<T>(new CanceledResultSource<T>(cancellationToken), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +175,153 @@ namespace Cysharp.Threading.Tasks
|
||||
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Never complete.
|
||||
/// </summary>
|
||||
public static UniTask Never(CancellationToken cancellationToken)
|
||||
{
|
||||
return new UniTask<AsyncUnit>(new NeverPromise<AsyncUnit>(cancellationToken), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Never complete.
|
||||
/// </summary>
|
||||
public static UniTask<T> Never<T>(CancellationToken cancellationToken)
|
||||
{
|
||||
return new UniTask<T>(new NeverPromise<T>(cancellationToken), 0);
|
||||
}
|
||||
|
||||
sealed class ExceptionResultSource : IUniTaskSource
|
||||
{
|
||||
readonly ExceptionDispatchInfo exception;
|
||||
|
||||
public ExceptionResultSource(Exception exception)
|
||||
{
|
||||
this.exception = ExceptionDispatchInfo.Capture(exception);
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
exception.Throw();
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return UniTaskStatus.Faulted;
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return UniTaskStatus.Faulted;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
continuation(state);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ExceptionResultSource<T> : IUniTaskSource<T>
|
||||
{
|
||||
readonly ExceptionDispatchInfo exception;
|
||||
|
||||
public ExceptionResultSource(Exception exception)
|
||||
{
|
||||
this.exception = ExceptionDispatchInfo.Capture(exception);
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
exception.Throw();
|
||||
return default;
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
exception.Throw();
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return UniTaskStatus.Faulted;
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return UniTaskStatus.Faulted;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
continuation(state);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CanceledResultSource : IUniTaskSource
|
||||
{
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public CanceledResultSource(CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
throw new OperationCanceledException(cancellationToken);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return UniTaskStatus.Canceled;
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return UniTaskStatus.Canceled;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
continuation(state);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CanceledResultSource<T> : IUniTaskSource<T>
|
||||
{
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public CanceledResultSource(CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
throw new OperationCanceledException(cancellationToken);
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
throw new OperationCanceledException(cancellationToken);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return UniTaskStatus.Canceled;
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return UniTaskStatus.Canceled;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
continuation(state);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DeferPromise : IUniTaskSource
|
||||
{
|
||||
Func<UniTask> factory;
|
||||
@@ -260,6 +400,54 @@ namespace Cysharp.Threading.Tasks
|
||||
return task.Status;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class NeverPromise<T> : IUniTaskSource<T>
|
||||
{
|
||||
static readonly Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
|
||||
public NeverPromise(CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
if (this.cancellationToken.CanBeCanceled)
|
||||
{
|
||||
this.cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (NeverPromise<T>)state;
|
||||
self.core.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
return 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);
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CompletedTasks
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public partial struct UniTask
|
||||
{
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask Run(Action action, bool configureAwait = true)
|
||||
public static async UniTask Run(Action action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
@@ -26,13 +31,19 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask Run(Action<object> action, object state, bool configureAwait = true)
|
||||
public static async UniTask Run(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
@@ -48,12 +59,75 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
action(state);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> Run<T>(Func<T> func, bool configureAwait = true)
|
||||
public static async UniTask Run(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
await action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await action();
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask Run(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
await action(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await action(state);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> Run<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
@@ -63,6 +137,7 @@ namespace Cysharp.Threading.Tasks
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -72,10 +147,44 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true)
|
||||
public static async UniTask<T> Run<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await func();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
@@ -85,6 +194,7 @@ namespace Cysharp.Threading.Tasks
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -92,6 +202,36 @@ namespace Cysharp.Threading.Tasks
|
||||
return func(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> Run<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await func(state);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,33 +15,41 @@ namespace Cysharp.Threading.Tasks
|
||||
/// <summary>
|
||||
/// If running on mainthread, do nothing. Otherwise, same as UniTask.Yield(PlayerLoopTiming.Update).
|
||||
/// </summary>
|
||||
public static SwitchToMainThreadAwaitable SwitchToMainThread()
|
||||
public static SwitchToMainThreadAwaitable SwitchToMainThread(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new SwitchToMainThreadAwaitable(PlayerLoopTiming.Update);
|
||||
return new SwitchToMainThreadAwaitable(PlayerLoopTiming.Update, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If running on mainthread, do nothing. Otherwise, same as UniTask.Yield(timing).
|
||||
/// </summary>
|
||||
public static SwitchToMainThreadAwaitable SwitchToMainThread(PlayerLoopTiming timing)
|
||||
public static SwitchToMainThreadAwaitable SwitchToMainThread(PlayerLoopTiming timing, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new SwitchToMainThreadAwaitable(timing);
|
||||
return new SwitchToMainThreadAwaitable(timing, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return to mainthread(same as await SwitchToMainThread) after using scope is closed.
|
||||
/// </summary>
|
||||
public static ReturnToMainThread ReturnToMainThread()
|
||||
public static ReturnToMainThread ReturnToMainThread(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new ReturnToMainThread(PlayerLoopTiming.Update);
|
||||
return new ReturnToMainThread(PlayerLoopTiming.Update, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return to mainthread(same as await SwitchToMainThread) after using scope is closed.
|
||||
/// </summary>
|
||||
public static ReturnToMainThread ReturnToMainThread(PlayerLoopTiming timing)
|
||||
public static ReturnToMainThread ReturnToMainThread(PlayerLoopTiming timing, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new ReturnToMainThread(timing);
|
||||
return new ReturnToMainThread(timing, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queue the action to PlayerLoop.
|
||||
/// </summary>
|
||||
public static void Post(Action action, PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
||||
{
|
||||
PlayerLoopHelper.AddContinuation(timing, action);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -59,20 +67,20 @@ namespace Cysharp.Threading.Tasks
|
||||
return new SwitchToTaskPoolAwaitable();
|
||||
}
|
||||
|
||||
public static SwitchToSynchronizationContextAwaitable SwitchToSynchronizationContext(SynchronizationContext synchronizationContext)
|
||||
public static SwitchToSynchronizationContextAwaitable SwitchToSynchronizationContext(SynchronizationContext synchronizationContext, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(synchronizationContext, nameof(synchronizationContext));
|
||||
return new SwitchToSynchronizationContextAwaitable(synchronizationContext);
|
||||
return new SwitchToSynchronizationContextAwaitable(synchronizationContext, cancellationToken);
|
||||
}
|
||||
|
||||
public static ReturnToSynchronizationContext ReturnToSynchronizationContext(SynchronizationContext synchronizationContext)
|
||||
public static ReturnToSynchronizationContext ReturnToSynchronizationContext(SynchronizationContext synchronizationContext, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new ReturnToSynchronizationContext(synchronizationContext, false);
|
||||
return new ReturnToSynchronizationContext(synchronizationContext, false, cancellationToken);
|
||||
}
|
||||
|
||||
public static ReturnToSynchronizationContext ReturnToCurrentSynchronizationContext(bool dontPostWhenSameContext = true)
|
||||
public static ReturnToSynchronizationContext ReturnToCurrentSynchronizationContext(bool dontPostWhenSameContext = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new ReturnToSynchronizationContext(SynchronizationContext.Current, dontPostWhenSameContext);
|
||||
return new ReturnToSynchronizationContext(SynchronizationContext.Current, dontPostWhenSameContext, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,21 +89,25 @@ namespace Cysharp.Threading.Tasks
|
||||
public struct SwitchToMainThreadAwaitable
|
||||
{
|
||||
readonly PlayerLoopTiming playerLoopTiming;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public SwitchToMainThreadAwaitable(PlayerLoopTiming playerLoopTiming)
|
||||
public SwitchToMainThreadAwaitable(PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken)
|
||||
{
|
||||
this.playerLoopTiming = playerLoopTiming;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter GetAwaiter() => new Awaiter(playerLoopTiming);
|
||||
public Awaiter GetAwaiter() => new Awaiter(playerLoopTiming, cancellationToken);
|
||||
|
||||
public struct Awaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
readonly PlayerLoopTiming playerLoopTiming;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public Awaiter(PlayerLoopTiming playerLoopTiming)
|
||||
public Awaiter(PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken)
|
||||
{
|
||||
this.playerLoopTiming = playerLoopTiming;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public bool IsCompleted
|
||||
@@ -114,7 +126,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public void GetResult() { }
|
||||
public void GetResult() { cancellationToken.ThrowIfCancellationRequested(); }
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
@@ -131,31 +143,35 @@ namespace Cysharp.Threading.Tasks
|
||||
public struct ReturnToMainThread
|
||||
{
|
||||
readonly PlayerLoopTiming playerLoopTiming;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public ReturnToMainThread(PlayerLoopTiming playerLoopTiming)
|
||||
public ReturnToMainThread(PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken)
|
||||
{
|
||||
this.playerLoopTiming = playerLoopTiming;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter DisposeAsync()
|
||||
{
|
||||
return new Awaiter(playerLoopTiming); // run immediate.
|
||||
return new Awaiter(playerLoopTiming, cancellationToken); // run immediate.
|
||||
}
|
||||
|
||||
public readonly struct Awaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
readonly PlayerLoopTiming timing;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public Awaiter(PlayerLoopTiming timing)
|
||||
public Awaiter(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
||||
{
|
||||
this.timing = timing;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter GetAwaiter() => this;
|
||||
|
||||
public bool IsCompleted => PlayerLoopHelper.MainThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||
|
||||
public void GetResult() { }
|
||||
public void GetResult() { cancellationToken.ThrowIfCancellationRequested(); }
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
@@ -277,26 +293,30 @@ namespace Cysharp.Threading.Tasks
|
||||
public struct SwitchToSynchronizationContextAwaitable
|
||||
{
|
||||
readonly SynchronizationContext synchronizationContext;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public SwitchToSynchronizationContextAwaitable(SynchronizationContext synchronizationContext)
|
||||
public SwitchToSynchronizationContextAwaitable(SynchronizationContext synchronizationContext, CancellationToken cancellationToken)
|
||||
{
|
||||
this.synchronizationContext = synchronizationContext;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter GetAwaiter() => new Awaiter(synchronizationContext);
|
||||
public Awaiter GetAwaiter() => new Awaiter(synchronizationContext, cancellationToken);
|
||||
|
||||
public struct Awaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
static readonly SendOrPostCallback switchToCallback = Callback;
|
||||
readonly SynchronizationContext synchronizationContext;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public Awaiter(SynchronizationContext synchronizationContext)
|
||||
public Awaiter(SynchronizationContext synchronizationContext, CancellationToken cancellationToken)
|
||||
{
|
||||
this.synchronizationContext = synchronizationContext;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public bool IsCompleted => false;
|
||||
public void GetResult() { }
|
||||
public void GetResult() { cancellationToken.ThrowIfCancellationRequested(); }
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
@@ -320,16 +340,18 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
readonly SynchronizationContext syncContext;
|
||||
readonly bool dontPostWhenSameContext;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public ReturnToSynchronizationContext(SynchronizationContext syncContext, bool dontPostWhenSameContext)
|
||||
public ReturnToSynchronizationContext(SynchronizationContext syncContext, bool dontPostWhenSameContext, CancellationToken cancellationToken)
|
||||
{
|
||||
this.syncContext = syncContext;
|
||||
this.dontPostWhenSameContext = dontPostWhenSameContext;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter DisposeAsync()
|
||||
{
|
||||
return new Awaiter(syncContext, dontPostWhenSameContext);
|
||||
return new Awaiter(syncContext, dontPostWhenSameContext, cancellationToken);
|
||||
}
|
||||
|
||||
public struct Awaiter : ICriticalNotifyCompletion
|
||||
@@ -338,11 +360,13 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
readonly SynchronizationContext synchronizationContext;
|
||||
readonly bool dontPostWhenSameContext;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
public Awaiter(SynchronizationContext synchronizationContext, bool dontPostWhenSameContext)
|
||||
public Awaiter(SynchronizationContext synchronizationContext, bool dontPostWhenSameContext, CancellationToken cancellationToken)
|
||||
{
|
||||
this.synchronizationContext = synchronizationContext;
|
||||
this.dontPostWhenSameContext = dontPostWhenSameContext;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public Awaiter GetAwaiter() => this;
|
||||
@@ -365,7 +389,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public void GetResult() { }
|
||||
public void GetResult() { cancellationToken.ThrowIfCancellationRequested(); }
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
|
||||
@@ -137,14 +137,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitUntilPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
||||
@@ -249,14 +241,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitWhilePromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
||||
@@ -344,14 +328,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitUntilCanceledPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// where T : UnityEngine.Object, can not add constraint
|
||||
@@ -475,14 +451,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitUntilValueChangedUnityObjectPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WaitUntilValueChangedStandardObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, ITaskPoolNode<WaitUntilValueChangedStandardObjectPromise<T, U>>
|
||||
@@ -604,14 +572,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~WaitUntilValueChangedStandardObjectPromise()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,11 +131,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3)> WhenAll<T1, T2, T3>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3)
|
||||
@@ -295,11 +290,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4)> WhenAll<T1, T2, T3, T4>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4)
|
||||
@@ -495,11 +485,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5)> WhenAll<T1, T2, T3, T4, T5>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5)
|
||||
@@ -731,11 +716,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6)> WhenAll<T1, T2, T3, T4, T5, T6>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6)
|
||||
@@ -1003,11 +983,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7)> WhenAll<T1, T2, T3, T4, T5, T6, T7>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7)
|
||||
@@ -1311,11 +1286,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8)
|
||||
@@ -1655,11 +1625,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9)
|
||||
@@ -2035,11 +2000,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10)
|
||||
@@ -2451,11 +2411,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11)
|
||||
@@ -2903,11 +2858,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12)
|
||||
@@ -3391,11 +3341,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13)
|
||||
@@ -3915,11 +3860,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13, UniTask<T14> task14)
|
||||
@@ -4475,11 +4415,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> WhenAll<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13, UniTask<T14> task14, UniTask<T15> task15)
|
||||
@@ -5071,11 +5006,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public WhenAllPromise(<#= args #>)
|
||||
{
|
||||
TaskTracker2.TrackActiveTask(this, 3);
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
|
||||
this.completedCount = 0;
|
||||
<# for(var j = 1; j <= i; j++) { #>
|
||||
@@ -92,7 +92,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public (<#= t #>) GetResult(short token)
|
||||
{
|
||||
TaskTracker2.RemoveTracking(this);
|
||||
TaskTracker.RemoveTracking(this);
|
||||
GC.SuppressFinalize(this);
|
||||
return core.GetResult(token);
|
||||
}
|
||||
@@ -116,11 +116,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
<# } #>
|
||||
}
|
||||
|
||||
@@ -142,11 +142,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WhenAllPromise : IUniTaskSource
|
||||
@@ -237,11 +232,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~WhenAllPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,11 +127,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3)> WhenAny<T1, T2, T3>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3)
|
||||
@@ -289,11 +284,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4)> WhenAny<T1, T2, T3, T4>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4)
|
||||
@@ -488,11 +478,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5)> WhenAny<T1, T2, T3, T4, T5>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5)
|
||||
@@ -724,11 +709,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6)> WhenAny<T1, T2, T3, T4, T5, T6>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6)
|
||||
@@ -997,11 +977,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7)> WhenAny<T1, T2, T3, T4, T5, T6, T7>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7)
|
||||
@@ -1307,11 +1282,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8)
|
||||
@@ -1654,11 +1624,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9)
|
||||
@@ -2038,11 +2003,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10)
|
||||
@@ -2459,11 +2419,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10, T11 result11)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11)
|
||||
@@ -2917,11 +2872,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10, T11 result11, T12 result12)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12)
|
||||
@@ -3412,11 +3362,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10, T11 result11, T12 result12, T13 result13)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13)
|
||||
@@ -3944,11 +3889,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10, T11 result11, T12 result12, T13 result13, T14 result14)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13, UniTask<T14> task14)
|
||||
@@ -4513,11 +4453,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3, T4 result4, T5 result5, T6 result6, T7 result7, T8 result8, T9 result9, T10 result10, T11 result11, T12 result12, T13 result13, T14 result14, T15 result15)> WhenAny<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(UniTask<T1> task1, UniTask<T2> task2, UniTask<T3> task3, UniTask<T4> task4, UniTask<T5> task5, UniTask<T6> task6, UniTask<T7> task7, UniTask<T8> task8, UniTask<T9> task9, UniTask<T10> task10, UniTask<T11> task11, UniTask<T12> task12, UniTask<T13> task13, UniTask<T14> task14, UniTask<T15> task15)
|
||||
@@ -5119,11 +5054,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public WhenAnyPromise(<#= args #>)
|
||||
{
|
||||
TaskTracker2.TrackActiveTask(this, 3);
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
|
||||
this.completedCount = 0;
|
||||
<# for(var j = 1; j <= i; j++) { #>
|
||||
@@ -86,7 +86,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public (int, <#= tBool #>) GetResult(short token)
|
||||
{
|
||||
TaskTracker2.RemoveTracking(this);
|
||||
TaskTracker.RemoveTracking(this);
|
||||
GC.SuppressFinalize(this);
|
||||
return core.GetResult(token);
|
||||
}
|
||||
@@ -110,11 +110,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
|
||||
@@ -171,11 +171,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyLRPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,11 +263,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WhenAnyPromise : IUniTaskSource<int>
|
||||
@@ -363,11 +353,6 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
~WhenAnyPromise()
|
||||
{
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"name": "UniTask",
|
||||
"references": [
|
||||
"Unity.ResourceManager",
|
||||
"Unity.TextMeshPro",
|
||||
"DOTween.Modules"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
@@ -14,19 +11,9 @@
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.addressables",
|
||||
"name": "com.unity.modules.assetbundle",
|
||||
"expression": "",
|
||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.textmeshpro",
|
||||
"expression": "",
|
||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
||||
},
|
||||
{
|
||||
"name": "com.demigiant.dotween",
|
||||
"expression": "",
|
||||
"define": "UNITASK_DOTWEEN_SUPPORT"
|
||||
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
@@ -38,13 +39,42 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
}
|
||||
|
||||
internal class ExceptionHolder
|
||||
{
|
||||
ExceptionDispatchInfo exception;
|
||||
bool calledGet = false;
|
||||
|
||||
public ExceptionHolder(ExceptionDispatchInfo exception)
|
||||
{
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public ExceptionDispatchInfo GetException()
|
||||
{
|
||||
if (!calledGet)
|
||||
{
|
||||
calledGet = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
return exception;
|
||||
}
|
||||
|
||||
~ExceptionHolder()
|
||||
{
|
||||
if (!calledGet)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct UniTaskCompletionSourceCore<TResult>
|
||||
{
|
||||
// Struct Size: TResult + (8 + 2 + 1 + 1 + 8 + 8)
|
||||
|
||||
TResult result;
|
||||
object error; // ExceptionDispatchInfo or OperationCanceledException
|
||||
object error; // ExceptionHolder or OperationCanceledException
|
||||
short version;
|
||||
bool hasUnhandledError;
|
||||
int completedCount; // 0: completed == false
|
||||
@@ -78,9 +108,9 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(oc);
|
||||
}
|
||||
else if (error is ExceptionDispatchInfo ei)
|
||||
else if (error is ExceptionHolder e)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ei.SourceException);
|
||||
UniTaskScheduler.PublishUnobservedTaskException(e.GetException().SourceException);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -129,7 +159,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
this.error = ExceptionDispatchInfo.Capture(error);
|
||||
this.error = new ExceptionHolder(ExceptionDispatchInfo.Capture(error));
|
||||
}
|
||||
|
||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||
@@ -199,7 +229,7 @@ namespace Cysharp.Threading.Tasks
|
||||
ValidateToken(token);
|
||||
if (completedCount == 0)
|
||||
{
|
||||
throw new InvalidOperationException("not yet completed.");
|
||||
throw new InvalidOperationException("Not yet completed, UniTask only allow to use await.");
|
||||
}
|
||||
|
||||
if (error != null)
|
||||
@@ -209,9 +239,9 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
throw oce;
|
||||
}
|
||||
else if (error is ExceptionDispatchInfo edi)
|
||||
else if (error is ExceptionHolder eh)
|
||||
{
|
||||
edi.Throw();
|
||||
eh.GetException().Throw();
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Critical: invalid exception type was held.");
|
||||
@@ -258,7 +288,7 @@ namespace Cysharp.Threading.Tasks
|
||||
// It will cause call OnCompleted multiple time, invalid.
|
||||
if (!ReferenceEquals(oldContinuation, UniTaskCompletionSourceCoreShared.s_sentinel))
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new InvalidOperationException("Already continuation registered, can not await twice or get Status after await.");
|
||||
}
|
||||
|
||||
continuation(state);
|
||||
@@ -286,95 +316,6 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public class UniTaskCompletionSource : IUniTaskSource, IPromise
|
||||
{
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
bool handled = false;
|
||||
|
||||
public UniTaskCompletionSource()
|
||||
{
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
internal void MarkHandled()
|
||||
{
|
||||
if (!handled)
|
||||
{
|
||||
handled = true;
|
||||
core.MarkHandled();
|
||||
TaskTracker.RemoveTracking(this);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask Task
|
||||
{
|
||||
[DebuggerHidden]
|
||||
get
|
||||
{
|
||||
return new UniTask(this, core.Version);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void Reset()
|
||||
{
|
||||
// Reset, re-active tracker
|
||||
handled = false;
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
core.Reset();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetResult()
|
||||
{
|
||||
return core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return core.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetException(Exception exception)
|
||||
{
|
||||
return core.TrySetException(exception);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void GetResult(short token)
|
||||
{
|
||||
MarkHandled();
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~UniTaskCompletionSource()
|
||||
{
|
||||
// clear error information.
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode<AutoResetUniTaskCompletionSource>, IPromise
|
||||
{
|
||||
static TaskPool<AutoResetUniTaskCompletionSource> pool;
|
||||
@@ -495,110 +436,6 @@ namespace Cysharp.Threading.Tasks
|
||||
core.Reset();
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AutoResetUniTaskCompletionSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UniTaskCompletionSource<T> : IUniTaskSource<T>, IPromise<T>
|
||||
{
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
bool handled = false;
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskCompletionSource()
|
||||
{
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
internal void MarkHandled()
|
||||
{
|
||||
if (!handled)
|
||||
{
|
||||
handled = true;
|
||||
core.MarkHandled();
|
||||
TaskTracker.RemoveTracking(this);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTask<T> Task
|
||||
{
|
||||
get
|
||||
{
|
||||
return new UniTask<T>(this, core.Version);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void Reset()
|
||||
{
|
||||
handled = false;
|
||||
core.Reset();
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetResult(T result)
|
||||
{
|
||||
return core.TrySetResult(result);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return core.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetException(Exception exception)
|
||||
{
|
||||
return core.TrySetException(exception);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public T GetResult(short token)
|
||||
{
|
||||
MarkHandled();
|
||||
return core.GetResult(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
~UniTaskCompletionSource()
|
||||
{
|
||||
// clear error information.
|
||||
core.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<AutoResetUniTaskCompletionSource<T>>, IPromise<T>
|
||||
@@ -726,15 +563,377 @@ namespace Cysharp.Threading.Tasks
|
||||
core.Reset();
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class UniTaskCompletionSource : IUniTaskSource, IPromise
|
||||
{
|
||||
CancellationToken cancellationToken;
|
||||
ExceptionHolder exception;
|
||||
object gate;
|
||||
Action<object> singleContinuation;
|
||||
object singleState;
|
||||
List<(Action<object>, object)> secondaryContinuationList;
|
||||
|
||||
~AutoResetUniTaskCompletionSource()
|
||||
int intStatus; // UniTaskStatus
|
||||
bool handled = false;
|
||||
|
||||
public UniTaskCompletionSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
internal void MarkHandled()
|
||||
{
|
||||
if (!handled)
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
handled = true;
|
||||
TaskTracker.RemoveTracking(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask Task
|
||||
{
|
||||
[DebuggerHidden]
|
||||
get
|
||||
{
|
||||
return new UniTask(this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetResult()
|
||||
{
|
||||
return TrySignalCompletion(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (UnsafeGetStatus() != UniTaskStatus.Pending) return false;
|
||||
|
||||
this.cancellationToken = cancellationToken;
|
||||
return TrySignalCompletion(UniTaskStatus.Canceled);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetException(Exception exception)
|
||||
{
|
||||
if (exception is OperationCanceledException oce)
|
||||
{
|
||||
return TrySetCanceled(oce.CancellationToken);
|
||||
}
|
||||
|
||||
if (UnsafeGetStatus() != UniTaskStatus.Pending) return false;
|
||||
|
||||
this.exception = new ExceptionHolder(ExceptionDispatchInfo.Capture(exception));
|
||||
return TrySignalCompletion(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void GetResult(short token)
|
||||
{
|
||||
MarkHandled();
|
||||
|
||||
var status = (UniTaskStatus)intStatus;
|
||||
switch (status)
|
||||
{
|
||||
case UniTaskStatus.Succeeded:
|
||||
return;
|
||||
case UniTaskStatus.Faulted:
|
||||
exception.GetException().Throw();
|
||||
return;
|
||||
case UniTaskStatus.Canceled:
|
||||
throw new OperationCanceledException(cancellationToken);
|
||||
default:
|
||||
case UniTaskStatus.Pending:
|
||||
throw new InvalidOperationException("not yet completed.");
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return (UniTaskStatus)intStatus;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return (UniTaskStatus)intStatus;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
if (gate == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref gate, new object(), null);
|
||||
}
|
||||
|
||||
var lockGate = Thread.VolatileRead(ref gate);
|
||||
lock (lockGate) // wait TrySignalCompletion, after status is not pending.
|
||||
{
|
||||
if ((UniTaskStatus)intStatus != UniTaskStatus.Pending)
|
||||
{
|
||||
continuation(state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (singleContinuation == null)
|
||||
{
|
||||
singleContinuation = continuation;
|
||||
singleState = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (secondaryContinuationList == null)
|
||||
{
|
||||
secondaryContinuationList = new List<(Action<object>, object)>();
|
||||
}
|
||||
secondaryContinuationList.Add((continuation, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
bool TrySignalCompletion(UniTaskStatus status)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref intStatus, (int)status, (int)UniTaskStatus.Pending) == (int)UniTaskStatus.Pending)
|
||||
{
|
||||
if (gate == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref gate, new object(), null);
|
||||
}
|
||||
|
||||
var lockGate = Thread.VolatileRead(ref gate);
|
||||
lock (lockGate) // wait OnCompleted.
|
||||
{
|
||||
if (singleContinuation != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
singleContinuation(singleState);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (secondaryContinuationList != null)
|
||||
{
|
||||
foreach (var (c, state) in secondaryContinuationList)
|
||||
{
|
||||
try
|
||||
{
|
||||
c(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
singleContinuation = null;
|
||||
singleState = null;
|
||||
secondaryContinuationList = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class UniTaskCompletionSource<T> : IUniTaskSource<T>, IPromise<T>
|
||||
{
|
||||
CancellationToken cancellationToken;
|
||||
T result;
|
||||
ExceptionHolder exception;
|
||||
object gate;
|
||||
Action<object> singleContinuation;
|
||||
object singleState;
|
||||
List<(Action<object>, object)> secondaryContinuationList;
|
||||
|
||||
int intStatus; // UniTaskStatus
|
||||
bool handled = false;
|
||||
|
||||
public UniTaskCompletionSource()
|
||||
{
|
||||
TaskTracker.TrackActiveTask(this, 2);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
internal void MarkHandled()
|
||||
{
|
||||
if (!handled)
|
||||
{
|
||||
handled = true;
|
||||
TaskTracker.RemoveTracking(this);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask<T> Task
|
||||
{
|
||||
[DebuggerHidden]
|
||||
get
|
||||
{
|
||||
return new UniTask<T>(this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetResult(T result)
|
||||
{
|
||||
if (UnsafeGetStatus() != UniTaskStatus.Pending) return false;
|
||||
|
||||
this.result = result;
|
||||
return TrySignalCompletion(UniTaskStatus.Succeeded);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (UnsafeGetStatus() != UniTaskStatus.Pending) return false;
|
||||
|
||||
this.cancellationToken = cancellationToken;
|
||||
return TrySignalCompletion(UniTaskStatus.Canceled);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public bool TrySetException(Exception exception)
|
||||
{
|
||||
if (exception is OperationCanceledException oce)
|
||||
{
|
||||
return TrySetCanceled(oce.CancellationToken);
|
||||
}
|
||||
|
||||
if (UnsafeGetStatus() != UniTaskStatus.Pending) return false;
|
||||
|
||||
this.exception = new ExceptionHolder(ExceptionDispatchInfo.Capture(exception));
|
||||
return TrySignalCompletion(UniTaskStatus.Faulted);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public T GetResult(short token)
|
||||
{
|
||||
MarkHandled();
|
||||
|
||||
var status = (UniTaskStatus)intStatus;
|
||||
switch (status)
|
||||
{
|
||||
case UniTaskStatus.Succeeded:
|
||||
return result;
|
||||
case UniTaskStatus.Faulted:
|
||||
exception.GetException().Throw();
|
||||
return default;
|
||||
case UniTaskStatus.Canceled:
|
||||
throw new OperationCanceledException(cancellationToken);
|
||||
default:
|
||||
case UniTaskStatus.Pending:
|
||||
throw new InvalidOperationException("not yet completed.");
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
GetResult(token);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return (UniTaskStatus)intStatus;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return (UniTaskStatus)intStatus;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
if (gate == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref gate, new object(), null);
|
||||
}
|
||||
|
||||
var lockGate = Thread.VolatileRead(ref gate);
|
||||
lock (lockGate) // wait TrySignalCompletion, after status is not pending.
|
||||
{
|
||||
if ((UniTaskStatus)intStatus != UniTaskStatus.Pending)
|
||||
{
|
||||
continuation(state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (singleContinuation == null)
|
||||
{
|
||||
singleContinuation = continuation;
|
||||
singleState = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (secondaryContinuationList == null)
|
||||
{
|
||||
secondaryContinuationList = new List<(Action<object>, object)>();
|
||||
}
|
||||
secondaryContinuationList.Add((continuation, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
bool TrySignalCompletion(UniTaskStatus status)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref intStatus, (int)status, (int)UniTaskStatus.Pending) == (int)UniTaskStatus.Pending)
|
||||
{
|
||||
if (gate == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref gate, new object(), null);
|
||||
}
|
||||
|
||||
var lockGate = Thread.VolatileRead(ref gate);
|
||||
lock (lockGate) // wait OnCompleted.
|
||||
{
|
||||
if (singleContinuation != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
singleContinuation(singleState);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (secondaryContinuationList != null)
|
||||
{
|
||||
foreach (var (c, state) in secondaryContinuationList)
|
||||
{
|
||||
try
|
||||
{
|
||||
c(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
singleContinuation = null;
|
||||
singleState = null;
|
||||
secondaryContinuationList = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,12 +181,180 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public static AsyncLazy ToAsyncLazy(this UniTask task)
|
||||
{
|
||||
return new AsyncLazy(task.Preserve()); // require Preserve
|
||||
return new AsyncLazy(task);
|
||||
}
|
||||
|
||||
public static AsyncLazy<T> ToAsyncLazy<T>(this UniTask<T> task)
|
||||
{
|
||||
return new AsyncLazy<T>(task.Preserve()); // require Preserve
|
||||
return new AsyncLazy<T>(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore task result when cancel raised first.
|
||||
/// </summary>
|
||||
public static UniTask WithCancellation(this UniTask task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!cancellationToken.CanBeCanceled)
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
if (task.Status.IsCompleted())
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
return new UniTask(new WithCancellationSource(task, cancellationToken), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore task result when cancel raised first.
|
||||
/// </summary>
|
||||
public static UniTask<T> WithCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!cancellationToken.CanBeCanceled)
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled<T>(cancellationToken);
|
||||
}
|
||||
|
||||
if (task.Status.IsCompleted())
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
return new UniTask<T>(new WithCancellationSource<T>(task, cancellationToken), 0);
|
||||
}
|
||||
|
||||
sealed class WithCancellationSource : IUniTaskSource
|
||||
{
|
||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration tokenRegistration;
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
public WithCancellationSource(UniTask task, CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
core.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tokenRegistration.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (WithCancellationSource)state;
|
||||
self.core.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WithCancellationSource<T> : IUniTaskSource<T>
|
||||
{
|
||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration tokenRegistration;
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
|
||||
public WithCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask<T> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
core.TrySetResult(await task);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
core.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tokenRegistration.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (WithCancellationSource<T>)state;
|
||||
self.core.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
return core.GetResult(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
@@ -201,10 +369,10 @@ namespace Cysharp.Threading.Tasks
|
||||
return new ToCoroutineEnumerator(task, exceptionHandler);
|
||||
}
|
||||
|
||||
public static async UniTask Timeout(this UniTask task, TimeSpan timeout, bool ignoreTimeScale = true, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
public static async UniTask Timeout(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, ignoreTimeScale, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
bool taskResultIsCanceled;
|
||||
@@ -242,10 +410,10 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTask<T> Timeout<T>(this UniTask<T> task, TimeSpan timeout, bool ignoreTimeScale = true, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
public static async UniTask<T> Timeout<T>(this UniTask<T> task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, ignoreTimeScale, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
(bool IsCanceled, T Result) taskResult;
|
||||
@@ -288,10 +456,10 @@ namespace Cysharp.Threading.Tasks
|
||||
/// <summary>
|
||||
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCacneled).
|
||||
/// </summary>
|
||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, bool ignoreTimeScale = true, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, ignoreTimeScale, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
bool taskResultIsCanceled;
|
||||
@@ -315,7 +483,7 @@ namespace Cysharp.Threading.Tasks
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
throw new TimeoutException("Exceed Timeout:" + timeout);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -325,7 +493,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (taskResultIsCanceled)
|
||||
{
|
||||
Error.ThrowOperationCanceledException();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -334,10 +502,10 @@ namespace Cysharp.Threading.Tasks
|
||||
/// <summary>
|
||||
/// Timeout with suppress OperationCanceledException. Returns (bool IsTimeout, T Result).
|
||||
/// </summary>
|
||||
public static async UniTask<(bool IsTimeout, T Result)> TimeoutWithoutException<T>(this UniTask<T> task, TimeSpan timeout, bool ignoreTimeScale = true, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
public static async UniTask<(bool IsTimeout, T Result)> TimeoutWithoutException<T>(this UniTask<T> task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, ignoreTimeScale, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
(bool IsCanceled, T Result) taskResult;
|
||||
@@ -361,7 +529,7 @@ namespace Cysharp.Threading.Tasks
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
throw new TimeoutException("Exceed Timeout:" + timeout);
|
||||
return (true, default);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -371,7 +539,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (taskResult.IsCanceled)
|
||||
{
|
||||
Error.ThrowOperationCanceledException();
|
||||
return (true, default);
|
||||
}
|
||||
|
||||
return (false, taskResult.Result);
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public class UniTaskSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
const int MaxArrayLength = 0X7FEFFFFF;
|
||||
const int InitialSize = 16;
|
||||
|
||||
static SpinLock gate = new SpinLock();
|
||||
static bool dequing = false;
|
||||
|
||||
static int actionListCount = 0;
|
||||
static Callback[] actionList = new Callback[InitialSize];
|
||||
|
||||
static int waitingListCount = 0;
|
||||
static Callback[] waitingList = new Callback[InitialSize];
|
||||
|
||||
static int opCount;
|
||||
|
||||
public override void Send(SendOrPostCallback d, object state)
|
||||
{
|
||||
d(state);
|
||||
}
|
||||
|
||||
public override void Post(SendOrPostCallback d, object state)
|
||||
{
|
||||
bool lockTaken = false;
|
||||
try
|
||||
{
|
||||
gate.Enter(ref lockTaken);
|
||||
|
||||
if (dequing)
|
||||
{
|
||||
// Ensure Capacity
|
||||
if (waitingList.Length == waitingListCount)
|
||||
{
|
||||
var newLength = waitingListCount * 2;
|
||||
if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
|
||||
|
||||
var newArray = new Callback[newLength];
|
||||
Array.Copy(waitingList, newArray, waitingListCount);
|
||||
waitingList = newArray;
|
||||
}
|
||||
waitingList[waitingListCount] = new Callback(d, state);
|
||||
waitingListCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure Capacity
|
||||
if (actionList.Length == actionListCount)
|
||||
{
|
||||
var newLength = actionListCount * 2;
|
||||
if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
|
||||
|
||||
var newArray = new Callback[newLength];
|
||||
Array.Copy(actionList, newArray, actionListCount);
|
||||
actionList = newArray;
|
||||
}
|
||||
actionList[actionListCount] = new Callback(d, state);
|
||||
actionListCount++;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (lockTaken) gate.Exit(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OperationStarted()
|
||||
{
|
||||
Interlocked.Increment(ref opCount);
|
||||
}
|
||||
|
||||
public override void OperationCompleted()
|
||||
{
|
||||
Interlocked.Decrement(ref opCount);
|
||||
}
|
||||
|
||||
public override SynchronizationContext CreateCopy()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// delegate entrypoint.
|
||||
internal static void Run()
|
||||
{
|
||||
{
|
||||
bool lockTaken = false;
|
||||
try
|
||||
{
|
||||
gate.Enter(ref lockTaken);
|
||||
if (actionListCount == 0) return;
|
||||
dequing = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (lockTaken) gate.Exit(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < actionListCount; i++)
|
||||
{
|
||||
var action = actionList[i];
|
||||
actionList[i] = default;
|
||||
action.Invoke();
|
||||
}
|
||||
|
||||
{
|
||||
bool lockTaken = false;
|
||||
try
|
||||
{
|
||||
gate.Enter(ref lockTaken);
|
||||
dequing = false;
|
||||
|
||||
var swapTempActionList = actionList;
|
||||
|
||||
actionListCount = waitingListCount;
|
||||
actionList = waitingList;
|
||||
|
||||
waitingListCount = 0;
|
||||
waitingList = swapTempActionList;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (lockTaken) gate.Exit(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
readonly struct Callback
|
||||
{
|
||||
readonly SendOrPostCallback callback;
|
||||
readonly object state;
|
||||
|
||||
public Callback(SendOrPostCallback callback, object state)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
callback(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abf3aae9813db2849bce518f8596e920
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,317 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
#if UNITY_2018_4 || UNITY_2019_4_OR_NEWER
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class UnityAsyncExtensions
|
||||
{
|
||||
public static AssetBundleRequestAllAssetsAwaiter AwaitForAllAssets(this AssetBundleRequest asyncOperation)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
return new AssetBundleRequestAllAssetsAwaiter(asyncOperation);
|
||||
}
|
||||
|
||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult<UnityEngine.Object[]>(asyncOperation.allAssets);
|
||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
AssetBundleRequest asyncOperation;
|
||||
Action<AsyncOperation> continuationAction;
|
||||
|
||||
public AssetBundleRequestAllAssetsAwaiter(AssetBundleRequest asyncOperation)
|
||||
{
|
||||
this.asyncOperation = asyncOperation;
|
||||
this.continuationAction = null;
|
||||
}
|
||||
|
||||
public bool IsCompleted => asyncOperation.isDone;
|
||||
|
||||
public UnityEngine.Object[] GetResult()
|
||||
{
|
||||
if (continuationAction != null)
|
||||
{
|
||||
asyncOperation.completed -= continuationAction;
|
||||
continuationAction = null;
|
||||
var result = asyncOperation.allAssets;
|
||||
asyncOperation = null;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = asyncOperation.allAssets;
|
||||
asyncOperation = null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
UnsafeOnCompleted(continuation);
|
||||
}
|
||||
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||
continuationAction = PooledDelegate<AsyncOperation>.Create(continuation);
|
||||
asyncOperation.completed += continuationAction;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AssetBundleRequestAllAssetsWithCancellationSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsWithCancellationSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestAllAssetsWithCancellationSource> pool;
|
||||
public AssetBundleRequestAllAssetsWithCancellationSource NextNode { get; set; }
|
||||
|
||||
static AssetBundleRequestAllAssetsWithCancellationSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestAllAssetsWithCancellationSource), () => pool.Size);
|
||||
}
|
||||
|
||||
readonly Action<AsyncOperation> continuationAction;
|
||||
AssetBundleRequest asyncOperation;
|
||||
CancellationToken cancellationToken;
|
||||
bool completed;
|
||||
|
||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||
|
||||
AssetBundleRequestAllAssetsWithCancellationSource()
|
||||
{
|
||||
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 AssetBundleRequestAllAssetsWithCancellationSource();
|
||||
}
|
||||
|
||||
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;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
core.TrySetResult(asyncOperation.allAssets);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
||||
public AssetBundleRequestAllAssetsConfiguredSource NextNode { get; set; }
|
||||
|
||||
static AssetBundleRequestAllAssetsConfiguredSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestAllAssetsConfiguredSource), () => pool.Size);
|
||||
}
|
||||
|
||||
AssetBundleRequest asyncOperation;
|
||||
IProgress<float> progress;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||
|
||||
AssetBundleRequestAllAssetsConfiguredSource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AssetBundleRequestAllAssetsConfiguredSource();
|
||||
}
|
||||
|
||||
result.asyncOperation = asyncOperation;
|
||||
result.progress = progress;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnityEngine.Object[] GetResult(short token)
|
||||
{
|
||||
try
|
||||
{
|
||||
return core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryReturn();
|
||||
}
|
||||
}
|
||||
|
||||
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 (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (progress != null)
|
||||
{
|
||||
progress.Report(asyncOperation.progress);
|
||||
}
|
||||
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
core.TrySetResult(asyncOperation.allAssets);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryReturn()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
asyncOperation = default;
|
||||
progress = default;
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9147caba40da434da95b39709c13784
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,139 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class UnityAsyncExtensions
|
||||
{
|
||||
#region AsyncGPUReadbackRequest
|
||||
|
||||
public static UniTask<AsyncGPUReadbackRequest>.Awaiter GetAwaiter(this AsyncGPUReadbackRequest asyncOperation)
|
||||
{
|
||||
return ToUniTask(asyncOperation).GetAwaiter();
|
||||
}
|
||||
|
||||
public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
||||
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
||||
{
|
||||
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
||||
public AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode { get; set; }
|
||||
|
||||
static AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncGPUReadbackRequestAwaiterConfiguredSource), () => pool.Size);
|
||||
}
|
||||
|
||||
AsyncGPUReadbackRequest asyncOperation;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
||||
|
||||
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource<AsyncGPUReadbackRequest>.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new AsyncGPUReadbackRequestAwaiterConfiguredSource();
|
||||
}
|
||||
|
||||
result.asyncOperation = asyncOperation;
|
||||
result.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
return result;
|
||||
}
|
||||
|
||||
public AsyncGPUReadbackRequest GetResult(short token)
|
||||
{
|
||||
try
|
||||
{
|
||||
return core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryReturn();
|
||||
}
|
||||
}
|
||||
|
||||
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 (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (asyncOperation.hasError)
|
||||
{
|
||||
core.TrySetException(new Exception("AsyncGPUReadbackRequest.hasError = true"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (asyncOperation.done)
|
||||
{
|
||||
core.TrySetResult(asyncOperation);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryReturn()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
asyncOperation = default;
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98f5fedb44749ab4688674d79126b46a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -24,6 +24,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||
return new UniTask(AsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -31,6 +32,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -134,6 +136,12 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +168,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
TryReturn();
|
||||
@@ -185,14 +193,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AsyncOperationWithCancellationSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
||||
@@ -299,14 +299,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AsyncOperationConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -322,6 +314,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||
return new UniTask<UnityEngine.Object>(ResourceRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -329,6 +322,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -436,6 +430,12 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
core.TrySetResult(asyncOperation.asset);
|
||||
}
|
||||
}
|
||||
@@ -466,7 +466,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
TryReturn();
|
||||
@@ -491,14 +491,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~ResourceRequestWithCancellationSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
||||
@@ -609,18 +601,11 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~ResourceRequestConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
#region AssetBundleRequest
|
||||
|
||||
public static AssetBundleRequestAwaiter GetAwaiter(this AssetBundleRequest asyncOperation)
|
||||
@@ -632,6 +617,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -639,6 +625,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -746,6 +733,12 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
core.TrySetResult(asyncOperation.asset);
|
||||
}
|
||||
}
|
||||
@@ -776,7 +769,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
TryReturn();
|
||||
@@ -801,14 +794,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AssetBundleRequestWithCancellationSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
||||
@@ -919,18 +904,12 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AssetBundleRequestConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
#region AssetBundleCreateRequest
|
||||
|
||||
public static AssetBundleCreateRequestAwaiter GetAwaiter(this AssetBundleCreateRequest asyncOperation)
|
||||
@@ -942,6 +921,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -949,6 +929,7 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
@@ -1056,6 +1037,12 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
core.TrySetResult(asyncOperation.assetBundle);
|
||||
}
|
||||
}
|
||||
@@ -1086,7 +1073,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
TryReturn();
|
||||
@@ -1111,14 +1098,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AssetBundleCreateRequestWithCancellationSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
||||
@@ -1229,17 +1208,10 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~AssetBundleCreateRequestConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#if ENABLE_UNITYWEBREQUEST
|
||||
#region UnityWebRequestAsyncOperation
|
||||
@@ -1253,14 +1225,30 @@ namespace Cysharp.Threading.Tasks
|
||||
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
return UniTask.FromResult(asyncOperation.webRequest);
|
||||
}
|
||||
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))
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
return UniTask.FromResult(asyncOperation.webRequest);
|
||||
}
|
||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
@@ -1285,12 +1273,20 @@ namespace Cysharp.Threading.Tasks
|
||||
continuationAction = null;
|
||||
var result = asyncOperation.webRequest;
|
||||
asyncOperation = null;
|
||||
if (result.IsError())
|
||||
{
|
||||
throw new UnityWebRequestException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = asyncOperation.webRequest;
|
||||
asyncOperation = null;
|
||||
if (result.IsError())
|
||||
{
|
||||
throw new UnityWebRequestException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1367,7 +1363,21 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
core.TrySetResult(asyncOperation.webRequest);
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
var result = asyncOperation.webRequest;
|
||||
if (result.IsError())
|
||||
{
|
||||
core.TrySetException(new UnityWebRequestException(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1397,7 +1407,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
TryReturn();
|
||||
@@ -1423,14 +1433,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~UnityWebRequestAsyncOperationWithCancellationSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
||||
@@ -1526,7 +1528,14 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
core.TrySetResult(asyncOperation.webRequest);
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(asyncOperation.webRequest);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1542,14 +1551,6 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~UnityWebRequestAsyncOperationConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
||||
#>
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
@@ -34,8 +36,10 @@ namespace Cysharp.Threading.Tasks
|
||||
public static partial class UnityAsyncExtensions
|
||||
{
|
||||
<# foreach(var t in types) { #>
|
||||
<# if(t.returnType == "UnityWebRequest") { #>
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
#if ENABLE_UNITYWEBREQUEST
|
||||
<# } else if(IsAssetBundleModule(t)) { #>
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
<# } #>
|
||||
#region <#= t.typeName #>
|
||||
|
||||
@@ -48,14 +52,38 @@ namespace Cysharp.Threading.Tasks
|
||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
return UniTask.FromResult(asyncOperation.webRequest);
|
||||
}
|
||||
<# } else { #>
|
||||
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||
<# } #>
|
||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>WithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
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));
|
||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
return UniTask.FromResult(asyncOperation.webRequest);
|
||||
}
|
||||
<# } else { #>
|
||||
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, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
@@ -81,6 +109,12 @@ namespace Cysharp.Threading.Tasks
|
||||
<# if (!IsVoid(t)) { #>
|
||||
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
||||
asyncOperation = null;
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
if (result.IsError())
|
||||
{
|
||||
throw new UnityWebRequestException(result);
|
||||
}
|
||||
<# } #>
|
||||
return result;
|
||||
<# } else { #>
|
||||
asyncOperation = null;
|
||||
@@ -91,6 +125,12 @@ namespace Cysharp.Threading.Tasks
|
||||
<# if (!IsVoid(t)) { #>
|
||||
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
||||
asyncOperation = null;
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
if (result.IsError())
|
||||
{
|
||||
throw new UnityWebRequestException(result);
|
||||
}
|
||||
<# } #>
|
||||
return result;
|
||||
<# } else { #>
|
||||
asyncOperation = null;
|
||||
@@ -170,7 +210,25 @@ namespace Cysharp.Threading.Tasks
|
||||
else
|
||||
{
|
||||
completed = true;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
var result = asyncOperation.webRequest;
|
||||
if (result.IsError())
|
||||
{
|
||||
core.TrySetException(new UnityWebRequestException(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(result);
|
||||
}
|
||||
<# } else { #>
|
||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +274,7 @@ namespace Cysharp.Threading.Tasks
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
completed = true;
|
||||
<# if(t.returnType == "UnityWebRequest") { #>
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
asyncOperation.webRequest.Abort();
|
||||
<# } #>
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
@@ -234,14 +292,6 @@ namespace Cysharp.Threading.Tasks
|
||||
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>
|
||||
@@ -331,7 +381,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
<# if(t.returnType == "UnityWebRequest") { #>
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
asyncOperation.webRequest.Abort();
|
||||
<# } #>
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
@@ -345,7 +395,18 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
if (asyncOperation.webRequest.IsError())
|
||||
{
|
||||
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||
}
|
||||
else
|
||||
{
|
||||
core.TrySetResult(asyncOperation.webRequest);
|
||||
}
|
||||
<# } else { #>
|
||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||
<# } #>
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -361,18 +422,10 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
|
||||
~<#= t.typeName #>ConfiguredSource()
|
||||
{
|
||||
if (TryReturn())
|
||||
{
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
<# if(t.returnType == "UnityWebRequest") { #>
|
||||
<# if(IsUnityWebRequest(t) || IsAssetBundleModule(t)) { #>
|
||||
#endif
|
||||
<# } #>
|
||||
|
||||
|
||||
@@ -296,6 +296,58 @@ namespace Cysharp.Threading.Tasks
|
||||
UniTask<T> OnEndEditAsync();
|
||||
}
|
||||
|
||||
// for TMP_PRO
|
||||
|
||||
public interface IAsyncEndTextSelectionEventHandler<T> : IDisposable
|
||||
{
|
||||
UniTask<T> OnEndTextSelectionAsync();
|
||||
}
|
||||
|
||||
public interface IAsyncTextSelectionEventHandler<T> : IDisposable
|
||||
{
|
||||
UniTask<T> OnTextSelectionAsync();
|
||||
}
|
||||
|
||||
public interface IAsyncDeselectEventHandler<T> : IDisposable
|
||||
{
|
||||
UniTask<T> OnDeselectAsync();
|
||||
}
|
||||
|
||||
public interface IAsyncSelectEventHandler<T> : IDisposable
|
||||
{
|
||||
UniTask<T> OnSelectAsync();
|
||||
}
|
||||
|
||||
public interface IAsyncSubmitEventHandler<T> : IDisposable
|
||||
{
|
||||
UniTask<T> OnSubmitAsync();
|
||||
}
|
||||
|
||||
internal class TextSelectionEventConverter : UnityEvent<(string, int, int)>, IDisposable
|
||||
{
|
||||
readonly UnityEvent<string, int, int> innerEvent;
|
||||
readonly UnityAction<string, int, int> invokeDelegate;
|
||||
|
||||
|
||||
public TextSelectionEventConverter(UnityEvent<string, int, int> unityEvent)
|
||||
{
|
||||
this.innerEvent = unityEvent;
|
||||
this.invokeDelegate = InvokeCore;
|
||||
|
||||
innerEvent.AddListener(invokeDelegate);
|
||||
}
|
||||
|
||||
void InvokeCore(string item1, int item2, int item3)
|
||||
{
|
||||
innerEvent.Invoke(item1, item2, item3);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
innerEvent.RemoveListener(invokeDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncUnityEventHandler : IUniTaskSource, IDisposable, IAsyncClickEventHandler
|
||||
{
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
@@ -402,6 +454,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
public class AsyncUnityEventHandler<T> : IUniTaskSource<T>, IDisposable, IAsyncValueChangedEventHandler<T>, IAsyncEndEditEventHandler<T>
|
||||
, IAsyncEndTextSelectionEventHandler<T>, IAsyncTextSelectionEventHandler<T>, IAsyncDeselectEventHandler<T>, IAsyncSelectEventHandler<T>, IAsyncSubmitEventHandler<T>
|
||||
{
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
@@ -464,6 +517,12 @@ namespace Cysharp.Threading.Tasks
|
||||
registration.Dispose();
|
||||
if (unityEvent != null)
|
||||
{
|
||||
// Dispose inner delegate for TextSelectionEventConverter
|
||||
if (unityEvent is IDisposable disp)
|
||||
{
|
||||
disp.Dispose();
|
||||
}
|
||||
|
||||
unityEvent.RemoveListener(action);
|
||||
}
|
||||
|
||||
@@ -481,6 +540,31 @@ namespace Cysharp.Threading.Tasks
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
UniTask<T> IAsyncEndTextSelectionEventHandler<T>.OnEndTextSelectionAsync()
|
||||
{
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
UniTask<T> IAsyncTextSelectionEventHandler<T>.OnTextSelectionAsync()
|
||||
{
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
UniTask<T> IAsyncDeselectEventHandler<T>.OnDeselectAsync()
|
||||
{
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
UniTask<T> IAsyncSelectEventHandler<T>.OnSelectAsync()
|
||||
{
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
UniTask<T> IAsyncSubmitEventHandler<T>.OnSubmitAsync()
|
||||
{
|
||||
return OnInvokeAsync();
|
||||
}
|
||||
|
||||
T IUniTaskSource<T>.GetResult(short token)
|
||||
{
|
||||
try
|
||||
@@ -718,6 +802,10 @@ namespace Cysharp.Threading.Tasks
|
||||
TaskTracker.RemoveTracking(this);
|
||||
registration1.Dispose();
|
||||
registration2.Dispose();
|
||||
if (unityEvent is IDisposable disp)
|
||||
{
|
||||
disp.Dispose();
|
||||
}
|
||||
unityEvent.RemoveListener(unityAction);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,65 +237,5 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TMP
|
||||
|
||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
||||
|
||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMPro.TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMPro.TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||
}
|
||||
|
||||
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, TMPro.TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||
{
|
||||
var repeat = false;
|
||||
BIND_AGAIN:
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
bool moveNext;
|
||||
try
|
||||
{
|
||||
moveNext = await e.MoveNextAsync();
|
||||
repeat = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
if (rebindOnError && !repeat)
|
||||
{
|
||||
repeat = true;
|
||||
goto BIND_AGAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (!moveNext) return;
|
||||
|
||||
text.text = e.Current;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#if ENABLE_UNITYWEBREQUEST
|
||||
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public class UnityWebRequestException : Exception
|
||||
{
|
||||
public UnityWebRequest UnityWebRequest { get; }
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
public UnityWebRequest.Result Result { get; }
|
||||
#else
|
||||
public bool IsNetworkError { get; }
|
||||
public bool IsHttpError { get; }
|
||||
#endif
|
||||
public string Error { get; }
|
||||
public string Text { get; }
|
||||
public long ResponseCode { get; }
|
||||
|
||||
string msg;
|
||||
|
||||
public UnityWebRequestException(UnityWebRequest unityWebRequest)
|
||||
{
|
||||
this.UnityWebRequest = unityWebRequest;
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
this.Result = unityWebRequest.result;
|
||||
#else
|
||||
this.IsNetworkError = unityWebRequest.isNetworkError;
|
||||
this.IsHttpError = unityWebRequest.isHttpError;
|
||||
#endif
|
||||
this.Error = unityWebRequest.error;
|
||||
this.ResponseCode = unityWebRequest.responseCode;
|
||||
if (UnityWebRequest.downloadHandler != null)
|
||||
{
|
||||
if (unityWebRequest.downloadHandler is DownloadHandlerBuffer dhb)
|
||||
{
|
||||
this.Text = dhb.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
if (msg == null)
|
||||
{
|
||||
if (Text != null)
|
||||
{
|
||||
msg = Error + Environment.NewLine + Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = Error;
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 013a499e522703a42962a779b4d9850c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,3 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("UniTask.Linq")]
|
||||
[assembly: InternalsVisibleTo("UniTask.Linq")]
|
||||
[assembly: InternalsVisibleTo("UniTask.Addressables")]
|
||||
[assembly: InternalsVisibleTo("UniTask.DOTween")]
|
||||
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "com.cysharp.unitask",
|
||||
"displayName": "UniTask",
|
||||
"version": "2.0.17",
|
||||
"version": "2.0.31",
|
||||
"unity": "2018.4",
|
||||
"description": "Provides an efficient async/await integration to Unity.",
|
||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||
|
||||
@@ -1,77 +1,52 @@
|
||||
// Provided from: https://github.com/Cysharp/UniTask/issues/40
|
||||
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Example script for comparing how exceptions in unobserved tasks are handled between
|
||||
/// UniTask and normal tasks. This helps in verifying that unobserved exceptions are
|
||||
/// logged in a way that it useful to developers.
|
||||
/// </summary>
|
||||
/*UNniTastWhenAnyTester*/
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class ExceptionExamples : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private LogType _unobservedExceptionLogType = LogType.Exception;
|
||||
public bool apply = false;
|
||||
|
||||
private void Awake()
|
||||
private async UniTaskVoid Update()
|
||||
{
|
||||
UniTaskScheduler.UnobservedExceptionWriteLogType = _unobservedExceptionLogType;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UnityEngine.Debug.Log("ExceptionScene, LoopType:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||
|
||||
//TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||
|
||||
//ThrowFromAsyncVoid();
|
||||
//_ = ThrowFromTask();
|
||||
//_ = ThrowFromUniTask();
|
||||
|
||||
//ThrowFromNonAsync();
|
||||
}
|
||||
|
||||
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
||||
{
|
||||
UnityEngine.Debug.LogException(e.Exception);
|
||||
}
|
||||
|
||||
private void ThrowFromNonAsync()
|
||||
{
|
||||
throw new Exception("Thrown from non-async function");
|
||||
}
|
||||
|
||||
private async void ThrowFromAsyncVoid()
|
||||
{
|
||||
await ThrowInner();
|
||||
|
||||
async Task ThrowInner()
|
||||
if (apply)
|
||||
{
|
||||
await UniTask.Yield();
|
||||
throw new Exception("Thrown from `async void` function");
|
||||
apply = false;
|
||||
await LaunchTasksAndDetectWhenAnyDone(5);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ThrowFromTask()
|
||||
private async UniTask LaunchTasksAndDetectWhenAnyDone(int nbTasks)
|
||||
{
|
||||
await ThrowInner();
|
||||
|
||||
async Task ThrowInner()
|
||||
List<UniTask<int>> sleeptasks = new List<UniTask<int>>();
|
||||
for (int i = 0; i < nbTasks; i++)
|
||||
{
|
||||
await UniTask.Yield();
|
||||
throw new Exception("Thrown from `async Task` function");
|
||||
sleeptasks.Add(SleepAndReturnTrue(i).ToAsyncLazy().Task);
|
||||
}
|
||||
while (sleeptasks.Count > 0)
|
||||
{
|
||||
Debug.Log(DateTime.Now.ToString() + " waiting for " + sleeptasks.Count + " tasks...");
|
||||
try
|
||||
{
|
||||
(int index, int taskID) = await UniTask.WhenAny(sleeptasks);
|
||||
Debug.Log(DateTime.Now.ToString() + " Sleep task " + taskID + " done");
|
||||
sleeptasks.RemoveAt(index);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
//Debug.Log("Error: " + e.Message);
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask ThrowFromUniTask()
|
||||
private async UniTask<int> SleepAndReturnTrue(int taskIndex)
|
||||
{
|
||||
await ThrowInner();
|
||||
|
||||
async UniTask ThrowInner()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
throw new Exception("Thrown from `async UniTask` function");
|
||||
}
|
||||
await UniTask.Delay(100);
|
||||
return taskIndex;
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,149 @@ NavMeshSettings:
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &542336983
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 542336986}
|
||||
- component: {fileID: 542336985}
|
||||
- component: {fileID: 542336984}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &542336984
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 542336983}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_HorizontalAxis: Horizontal
|
||||
m_VerticalAxis: Vertical
|
||||
m_SubmitButton: Submit
|
||||
m_CancelButton: Cancel
|
||||
m_InputActionsPerSecond: 10
|
||||
m_RepeatDelay: 0.5
|
||||
m_ForceModuleActive: 0
|
||||
--- !u!114 &542336985
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 542336983}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 10
|
||||
--- !u!4 &542336986
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 542336983}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &730559310
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 730559311}
|
||||
- component: {fileID: 730559313}
|
||||
- component: {fileID: 730559312}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &730559311
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 730559310}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1587363385}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &730559312
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 730559310}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Button
|
||||
--- !u!222 &730559313
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 730559310}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &735985614
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -152,7 +295,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 329ff620b32b4ef4abdc99884242ee67, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_unobservedExceptionLogType: 0
|
||||
ButtonTest: {fileID: 1587363386}
|
||||
--- !u!81 &735985616
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -214,7 +357,225 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Children:
|
||||
- {fileID: 1323586517}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1323586516
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1323586517}
|
||||
- component: {fileID: 1323586520}
|
||||
- component: {fileID: 1323586519}
|
||||
- component: {fileID: 1323586518}
|
||||
m_Layer: 5
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1323586517
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1323586516}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_Children:
|
||||
- {fileID: 1587363385}
|
||||
m_Father: {fileID: 735985618}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!114 &1323586518
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1323586516}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &1323586519
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1323586516}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 0
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
--- !u!223 &1323586520
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1323586516}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!1 &1587363384
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1587363385}
|
||||
- component: {fileID: 1587363388}
|
||||
- component: {fileID: 1587363387}
|
||||
- component: {fileID: 1587363386}
|
||||
m_Layer: 5
|
||||
m_Name: Button
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1587363385
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1587363384}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 730559311}
|
||||
m_Father: {fileID: 1323586517}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 160, y: 30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1587363386
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1587363384}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 1587363387}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!114 &1587363387
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1587363384}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!222 &1587363388
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1587363384}
|
||||
m_CullTransparentMesh: 0
|
||||
|
||||
471
src/UniTask/Assets/Scenes/MiddlewareSample.cs
Normal file
471
src/UniTask/Assets/Scenes/MiddlewareSample.cs
Normal file
@@ -0,0 +1,471 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Sample
|
||||
{
|
||||
//public class Sample2
|
||||
//{
|
||||
// public Sample2()
|
||||
// {
|
||||
// // デコレーターの詰まったClientを生成(これは一度作ったらフィールドに保存可)
|
||||
// var client = new NetworkClient("http://localhost", TimeSpan.FromSeconds(10),
|
||||
// new QueueRequestDecorator(),
|
||||
// new LoggingDecorator(),
|
||||
// new AppendTokenDecorator(),
|
||||
// new SetupHeaderDecorator());
|
||||
|
||||
|
||||
// await client.PostAsync("/User/Register", new { Id = 100 });
|
||||
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
public class ReturnToTitleDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException)
|
||||
{
|
||||
// キャンセルはきっと想定されている処理なのでそのまんまスルー(呼び出し側でOperationCanceledExceptionとして飛んでいく)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (ex is UnityWebRequestException uwe)
|
||||
{
|
||||
// ステータスコードを使って、タイトルに戻す例外です、とかリトライさせる例外です、とかハンドリングさせると便利
|
||||
// if (uwe.ResponseCode) { }...
|
||||
}
|
||||
|
||||
// サーバー例外のMessageを直接出すなんて乱暴なことはデバッグ時だけですよ勿論。
|
||||
var result = await MessageDialog.ShowAsync(ex.Message);
|
||||
|
||||
// OK か Cancelかで分岐するなら。今回はボタン一個、OKのみの想定なので無視
|
||||
// if (result == DialogResult.Ok) { }...
|
||||
|
||||
// シーン呼び出しはawaitしないこと!awaitして正常終了しちゃうと、この通信の呼び出し元に処理が戻って続行してしまいます
|
||||
// のでForget。
|
||||
SceneManager.LoadSceneAsync("TitleScene").ToUniTask().Forget();
|
||||
|
||||
|
||||
// そしてOperationCanceledExceptionを投げて、この通信の呼び出し元の処理はキャンセル扱いにして終了させる
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DialogResult
|
||||
{
|
||||
Ok,
|
||||
Cancel
|
||||
}
|
||||
|
||||
public static class MessageDialog
|
||||
{
|
||||
public static async UniTask<DialogResult> ShowAsync(string message)
|
||||
{
|
||||
// (例えば)Prefabで作っておいたダイアログを生成する
|
||||
var view = await Resources.LoadAsync("Prefabs/Dialog");
|
||||
|
||||
// Ok, Cancelボタンのどちらかが押されるのを待機
|
||||
return await (view as GameObject).GetComponent<MessageDialogView>().ClickResult;
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageDialogView : MonoBehaviour
|
||||
{
|
||||
[SerializeField] Button okButton = default;
|
||||
[SerializeField] Button closeButton = default;
|
||||
|
||||
UniTaskCompletionSource<DialogResult> taskCompletion;
|
||||
|
||||
// これでどちらかが押されるまで無限に待つを表現
|
||||
public UniTask<DialogResult> ClickResult => taskCompletion.Task;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
taskCompletion = new UniTaskCompletionSource<DialogResult>();
|
||||
|
||||
okButton.onClick.AddListener(() =>
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Ok);
|
||||
});
|
||||
|
||||
closeButton.onClick.AddListener(() =>
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||
});
|
||||
}
|
||||
|
||||
// もしボタンが押されずに消滅した場合にネンノタメ。
|
||||
private void OnDestroy()
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public class MockDecorator : IAsyncDecorator
|
||||
{
|
||||
Dictionary<string, object> mock;
|
||||
|
||||
// Pathと型を1:1にして事前定義したオブジェクトを返す辞書を渡す
|
||||
public MockDecorator(Dictionary<string, object> mock)
|
||||
{
|
||||
this.mock = mock;
|
||||
}
|
||||
|
||||
public UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
if (mock.TryGetValue(context.Path, out var value))
|
||||
{
|
||||
// 一致したものがあればそれを返す(実際の通信は行わない)
|
||||
return new UniTask<ResponseContext>(new ResponseContext(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
return next(context, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LoggingDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
UnityEngine.Debug.Log("Start Network Request:" + context.Path);
|
||||
|
||||
var response = await next(context, cancellationToken);
|
||||
|
||||
UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}");
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException)
|
||||
{
|
||||
UnityEngine.Debug.Log("Request Canceled:" + context.Path);
|
||||
}
|
||||
else if (ex is TimeoutException)
|
||||
{
|
||||
UnityEngine.Debug.Log("Request Timeout:" + context.Path);
|
||||
}
|
||||
else if (ex is UnityWebRequestException webex)
|
||||
{
|
||||
if (webex.IsHttpError)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||
}
|
||||
else if (webex.IsNetworkError)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
/* log other */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SetupHeaderDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
context.RequestHeaders["x-app-timestamp"] = context.Timestamp.ToString();
|
||||
context.RequestHeaders["x-user-id"] = "132141411"; // どこかから持ってくる
|
||||
context.RequestHeaders["x-access-token"] = "fafafawfafewaea"; // どこかから持ってくる2
|
||||
|
||||
var respsonse = await next(context, cancellationToken);
|
||||
|
||||
var nextToken = respsonse.ResponseHeaders["token"];
|
||||
// UserProfile.Token = nextToken; // どこかにセットするということにする
|
||||
|
||||
return respsonse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AppendTokenDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
string token = "token"; // どっかから取ってくるということにする
|
||||
RETRY:
|
||||
try
|
||||
{
|
||||
context.RequestHeaders["x-accesss-token"] = token;
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
catch (UnityWebRequestException ex)
|
||||
{
|
||||
// 例えば700はTokenを再取得してください的な意味だったとする
|
||||
if (ex.ResponseCode == 700)
|
||||
{
|
||||
// 別口でTokenを取得します的な処理
|
||||
var newToken = await new NetworkClient(context.BasePath, context.Timeout).PostAsync<string>("/Auth/GetToken", "access_token", cancellationToken);
|
||||
context.Reset(this);
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
goto RETRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class QueueRequestDecorator : IAsyncDecorator
|
||||
{
|
||||
readonly Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)> q = new Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)>();
|
||||
bool running;
|
||||
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
if (q.Count == 0)
|
||||
{
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var completionSource = new UniTaskCompletionSource<ResponseContext>();
|
||||
q.Enqueue((completionSource, context, cancellationToken, next));
|
||||
if (!running)
|
||||
{
|
||||
Run().Forget();
|
||||
}
|
||||
return await completionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
async UniTaskVoid Run()
|
||||
{
|
||||
running = true;
|
||||
try
|
||||
{
|
||||
while (q.Count != 0)
|
||||
{
|
||||
var (tcs, context, cancellationToken, next) = q.Dequeue();
|
||||
try
|
||||
{
|
||||
var response = await next(context, cancellationToken);
|
||||
tcs.TrySetResult(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class RequestContext
|
||||
{
|
||||
int decoratorIndex;
|
||||
readonly IAsyncDecorator[] decorators;
|
||||
Dictionary<string, string> headers;
|
||||
|
||||
public string BasePath { get; }
|
||||
public string Path { get; }
|
||||
public object Value { get; }
|
||||
public TimeSpan Timeout { get; }
|
||||
public DateTimeOffset Timestamp { get; private set; }
|
||||
|
||||
public IDictionary<string, string> RequestHeaders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (headers == null)
|
||||
{
|
||||
headers = new Dictionary<string, string>();
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
public RequestContext(string basePath, string path, object value, TimeSpan timeout, IAsyncDecorator[] filters)
|
||||
{
|
||||
this.decoratorIndex = -1;
|
||||
this.decorators = filters;
|
||||
this.BasePath = basePath;
|
||||
this.Path = path;
|
||||
this.Value = value;
|
||||
this.Timeout = timeout;
|
||||
this.Timestamp = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
internal Dictionary<string, string> GetRawHeaders() => headers;
|
||||
internal IAsyncDecorator GetNextDecorator() => decorators[++decoratorIndex];
|
||||
|
||||
public void Reset(IAsyncDecorator currentFilter)
|
||||
{
|
||||
decoratorIndex = Array.IndexOf(decorators, currentFilter);
|
||||
if (headers != null)
|
||||
{
|
||||
headers.Clear();
|
||||
}
|
||||
Timestamp = DateTimeOffset.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
public class ResponseContext
|
||||
{
|
||||
bool hasValue;
|
||||
object value;
|
||||
readonly byte[] bytes;
|
||||
|
||||
public long StatusCode { get; }
|
||||
public Dictionary<string, string> ResponseHeaders { get; }
|
||||
|
||||
public ResponseContext(object value, Dictionary<string, string> header = null)
|
||||
{
|
||||
this.hasValue = true;
|
||||
this.value = value;
|
||||
this.StatusCode = 200;
|
||||
this.ResponseHeaders = (header ?? new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
public ResponseContext(byte[] bytes, long statusCode, Dictionary<string, string> responseHeaders)
|
||||
{
|
||||
this.hasValue = false;
|
||||
this.bytes = bytes;
|
||||
this.StatusCode = statusCode;
|
||||
this.ResponseHeaders = responseHeaders;
|
||||
}
|
||||
|
||||
public byte[] GetRawData() => bytes;
|
||||
|
||||
public T GetResponseAs<T>()
|
||||
{
|
||||
if (hasValue)
|
||||
{
|
||||
return (T)value;
|
||||
}
|
||||
|
||||
value = JsonUtility.FromJson<T>(Encoding.UTF8.GetString(bytes));
|
||||
hasValue = true;
|
||||
return (T)value;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAsyncDecorator
|
||||
{
|
||||
UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next);
|
||||
}
|
||||
|
||||
|
||||
public class NetworkClient : IAsyncDecorator
|
||||
{
|
||||
readonly Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next;
|
||||
readonly IAsyncDecorator[] decorators;
|
||||
readonly TimeSpan timeout;
|
||||
readonly IProgress<float> progress;
|
||||
readonly string basePath;
|
||||
|
||||
public NetworkClient(string basePath, TimeSpan timeout, params IAsyncDecorator[] decorators)
|
||||
: this(basePath, timeout, null, decorators)
|
||||
{
|
||||
}
|
||||
|
||||
public NetworkClient(string basePath, TimeSpan timeout, IProgress<float> progress, params IAsyncDecorator[] decorators)
|
||||
{
|
||||
this.next = InvokeRecursive; // setup delegate
|
||||
|
||||
this.basePath = basePath;
|
||||
this.timeout = timeout;
|
||||
this.progress = progress;
|
||||
this.decorators = new IAsyncDecorator[decorators.Length + 1];
|
||||
Array.Copy(decorators, this.decorators, decorators.Length);
|
||||
this.decorators[this.decorators.Length - 1] = this;
|
||||
}
|
||||
|
||||
public async UniTask<T> PostAsync<T>(string path, T value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var request = new RequestContext(basePath, path, value, timeout, decorators);
|
||||
var response = await InvokeRecursive(request, cancellationToken);
|
||||
return response.GetResponseAs<T>();
|
||||
}
|
||||
|
||||
|
||||
UniTask<ResponseContext> InvokeRecursive(RequestContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
return context.GetNextDecorator().SendAsync(context, cancellationToken, next); // マジカル再帰処理
|
||||
}
|
||||
|
||||
async UniTask<ResponseContext> IAsyncDecorator.SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> _)
|
||||
{
|
||||
// Postしか興味ないからPostにしかしないよ!
|
||||
// パフォーマンスを最大限にしたい場合はuploadHandler, downloadHandlerをカスタマイズすること
|
||||
|
||||
// JSONでbodyに送るというパラメータで送るという雑設定。
|
||||
var data = JsonUtility.ToJson(context.Value);
|
||||
var formData = new Dictionary<string, string> { { "body", data } };
|
||||
|
||||
using (var req = UnityWebRequest.Post(basePath + context.Path, formData))
|
||||
{
|
||||
var header = context.GetRawHeaders();
|
||||
if (header != null)
|
||||
{
|
||||
foreach (var item in header)
|
||||
{
|
||||
req.SetRequestHeader(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Timeout処理はCancellationTokenSourceのCancelAfterSlim(UniTask拡張)を使ってサクッと処理
|
||||
var linkToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
linkToken.CancelAfterSlim(timeout);
|
||||
try
|
||||
{
|
||||
// 完了待ちや終了処理はUniTaskの拡張自体に丸投げ
|
||||
await req.SendWebRequest().ToUniTask(progress: progress, cancellationToken: linkToken.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 元キャンセレーションソースがキャンセルしてなければTimeoutによるものと判定
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Timeoutに引っかからなかった場合にてるのでCancelAfterSlimの裏で回ってるループをこれで終わらせとく
|
||||
if (!linkToken.IsCancellationRequested)
|
||||
{
|
||||
linkToken.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// UnityWebRequestを先にDisposeしちゃうので先に必要なものを取得しておく(性能的には無駄なのでパフォーマンスを最大限にしたい場合は更に一工夫を)
|
||||
return new ResponseContext(req.downloadHandler.data, req.responseCode, req.GetResponseHeaders());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/UniTask/Assets/Scenes/MiddlewareSample.cs.meta
Normal file
11
src/UniTask/Assets/Scenes/MiddlewareSample.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fc39a4b35a8db44592cddc0b365942f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -15,6 +15,10 @@ using UnityEngine.LowLevel;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.Rendering;
|
||||
using System.IO;
|
||||
using System.Linq.Expressions;
|
||||
using Cysharp.Threading.Tasks.Sample;
|
||||
|
||||
|
||||
// using DG.Tweening;
|
||||
@@ -117,6 +121,8 @@ public class AsyncMessageBroker<T> : IDisposable
|
||||
|
||||
public class SandboxMain : MonoBehaviour
|
||||
{
|
||||
public Camera mycamera;
|
||||
|
||||
public Button okButton;
|
||||
public Button cancelButton;
|
||||
|
||||
@@ -129,6 +135,7 @@ public class SandboxMain : MonoBehaviour
|
||||
UniTaskCompletionSource ucs;
|
||||
async UniTask<int> FooAsync()
|
||||
{
|
||||
|
||||
// use F10, will crash.
|
||||
var loop = int.Parse("9");
|
||||
await UniTask.DelayFrame(loop);
|
||||
@@ -161,6 +168,9 @@ public class SandboxMain : MonoBehaviour
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//setHp = Hp.GetSetter();
|
||||
}
|
||||
|
||||
@@ -178,14 +188,14 @@ public class SandboxMain : MonoBehaviour
|
||||
public Button button;
|
||||
|
||||
|
||||
void Start2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
async UniTask RunStandardDelayAsync()
|
||||
{
|
||||
|
||||
|
||||
|
||||
UnityEngine.Debug.Log("DEB");
|
||||
|
||||
await UniTask.DelayFrame(30);
|
||||
@@ -216,6 +226,11 @@ public class SandboxMain : MonoBehaviour
|
||||
async UniTaskVoid Update2()
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UnityEngine.Debug.Log("async linq!");
|
||||
|
||||
await UniTaskAsyncEnumerable.Range(1, 10)
|
||||
@@ -415,21 +430,80 @@ public class SandboxMain : MonoBehaviour
|
||||
|
||||
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");
|
||||
}
|
||||
var req = UnityWebRequest.Get("https://google.com/");
|
||||
|
||||
var v = await req.SendWebRequest().ToUniTask();
|
||||
// req.Dispose();
|
||||
Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}");
|
||||
Debug.Log(v.downloadHandler.text);
|
||||
}
|
||||
private async void Go()
|
||||
{
|
||||
await UniTask.DelayFrame(0);
|
||||
}
|
||||
|
||||
async UniTask Foo()
|
||||
{
|
||||
await UniTask.DelayFrame(10);
|
||||
throw new Exception("yeah");
|
||||
}
|
||||
|
||||
|
||||
void Start()
|
||||
|
||||
|
||||
async void Nanika()
|
||||
{
|
||||
UnityEngine.Debug.Log("Start:" + PlayerLoopInfo.CurrentLoopType);
|
||||
await UniTask.Yield();
|
||||
Debug.Log("Here");
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// PlayerLoopInfo.Inject();
|
||||
PrepareCamera();
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerable<int> MyEveryUpdate()
|
||||
{
|
||||
return UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||
{
|
||||
var frameCount = 0;
|
||||
await UniTask.Yield();
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
await writer.YieldAsync(frameCount++); // instead of `yield return`
|
||||
await UniTask.Yield();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async void RunStandardTaskAsync()
|
||||
{
|
||||
Debug.Log("Wait 3 seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
|
||||
Debug.Log("Current SyncContext:" + SynchronizationContext.Current.GetType().FullName);
|
||||
}
|
||||
|
||||
|
||||
async UniTaskVoid Start()
|
||||
{
|
||||
//Expression.Lambda<Func<int>>(null).Compile(true);
|
||||
|
||||
//RunStandardTaskAsync();
|
||||
|
||||
//UnityEngine.Debug.Log("UniTaskPlayerLoop ready? " + PlayerLoopHelper.IsInjectedUniTaskPlayerLoop());
|
||||
|
||||
//var url = "http://google.com/404";
|
||||
//var webRequestAsyncOperation = UnityWebRequest.Get(url).SendWebRequest();
|
||||
//await webRequestAsyncOperation.ToUniTask();
|
||||
|
||||
//PlayerLoopInfo.Inject();
|
||||
|
||||
@@ -444,76 +518,95 @@ public class SandboxMain : MonoBehaviour
|
||||
|
||||
|
||||
// rp.AddTo(this.GetCancellationTokenOnDestroy());
|
||||
var cts = new CancellationTokenSource();
|
||||
//var cts = new CancellationTokenSource();
|
||||
|
||||
|
||||
// UniTask.Post(
|
||||
|
||||
// CancellationToken.
|
||||
|
||||
//UniTask.Delay(TimeSpan.FromSeconds(3)).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
var client = new NetworkClient("http://localhost:5000", TimeSpan.FromSeconds(2),
|
||||
new QueueRequestDecorator(),
|
||||
new LoggingDecorator());
|
||||
//new AppendTokenDecorator(),
|
||||
//new SetupHeaderDecorator());
|
||||
|
||||
|
||||
//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);
|
||||
await client.PostAsync("", new { Id = 100 });
|
||||
|
||||
//StartCoroutine(CoroutineRun2());
|
||||
////StartCoroutine(CoroutineRun());
|
||||
//UnityEngine.Debug.Log("FOO?");
|
||||
|
||||
//_ = DelayFrame3_Pre();
|
||||
//await UniTask.Yield();
|
||||
|
||||
}));
|
||||
|
||||
cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||
{
|
||||
_ = DelayFrame3_Post();
|
||||
await UniTask.Yield();
|
||||
// _ = ExecuteAsync();
|
||||
|
||||
//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);
|
||||
// await UniTask.Yield();
|
||||
|
||||
//StartCoroutine(CoroutineRun());
|
||||
// //await DelayCheck();
|
||||
// /*
|
||||
// UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||
// StartCoroutine(CoroutineRun());
|
||||
// StartCoroutine(CoroutineRun2());
|
||||
// _ = AsyncRun();
|
||||
// _ = AsyncLastUpdate();
|
||||
// _ = AsyncLastLast();
|
||||
// */
|
||||
// //await UniTask.Yield();
|
||||
// //_ = Test2();
|
||||
// // EarlyUpdate.ExecuteMainThreadJobs
|
||||
// // _ = Test2();
|
||||
|
||||
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||
//_ = Yieldding();
|
||||
// //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);
|
||||
|
||||
//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);
|
||||
}));
|
||||
// //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;
|
||||
//await UniTask.SwitchToMainThread();
|
||||
@@ -632,7 +725,9 @@ public class SandboxMain : MonoBehaviour
|
||||
|
||||
//StartCoroutine(Coroutine());
|
||||
|
||||
//await UniTask.Delay(TimeSpan.FromSeconds(1));
|
||||
// PlayerLoopInfo.Inject();
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(1));
|
||||
PlayerLoopInfo.DumpPlayerLoop("current", PlayerLoop.GetCurrentPlayerLoop());
|
||||
|
||||
|
||||
// _ = ReturnToMainThreadTest();
|
||||
@@ -939,9 +1034,76 @@ public class SandboxMain : MonoBehaviour
|
||||
// e.SetObserved();
|
||||
// or other custom write code.
|
||||
UnityEngine.Debug.LogError("Unobserved:" + e.Exception.ToString());
|
||||
}
|
||||
|
||||
|
||||
// GPU Screenshot Sample
|
||||
|
||||
void PrepareCamera()
|
||||
{
|
||||
//Debug.Log("Support AsyncGPUReadback:" + SystemInfo.supportsAsyncGPUReadback);
|
||||
|
||||
//var width = 480;
|
||||
//var height = 240;
|
||||
//var depth = 24;
|
||||
|
||||
//mycamera.targetTexture = new RenderTexture(width, height, depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
|
||||
//{
|
||||
// antiAliasing = 8
|
||||
//};
|
||||
//mycamera.enabled = true;
|
||||
|
||||
//myRenderTexture = new RenderTexture(width, height, depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
|
||||
//{
|
||||
// antiAliasing = 8
|
||||
//};
|
||||
}
|
||||
|
||||
RenderTexture myRenderTexture;
|
||||
|
||||
async UniTask ShootAsync()
|
||||
{
|
||||
var rt = mycamera.targetTexture;
|
||||
|
||||
|
||||
|
||||
var req = await AsyncGPUReadback.Request(rt, 0);
|
||||
|
||||
Debug.Log("GPU Readback done?:" + req.done);
|
||||
|
||||
var rawByteArray = req.GetData<byte>().ToArray();
|
||||
var graphicsFormat = rt.graphicsFormat;
|
||||
var width = (uint)rt.width;
|
||||
var height = (uint)rt.height;
|
||||
|
||||
Debug.Log("BytesSize:" + rawByteArray.Length);
|
||||
|
||||
|
||||
var imageBytes = ImageConversion.EncodeArrayToPNG(rawByteArray, graphicsFormat, width, height);
|
||||
|
||||
|
||||
File.WriteAllBytes("my_screenshot.png", imageBytes); // test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SyncContextInjecter
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void Inject()
|
||||
{
|
||||
SynchronizationContext.SetSynchronizationContext(new UniTaskSynchronizationContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class PlayerLoopInfo
|
||||
{
|
||||
// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
@@ -976,7 +1138,7 @@ public class PlayerLoopInfo
|
||||
|
||||
public static Type CurrentLoopType { get; private set; }
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void Inject()
|
||||
{
|
||||
var system = PlayerLoop.GetCurrentPlayerLoop();
|
||||
|
||||
@@ -239,6 +239,80 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 16537670}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &518730348
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 518730350}
|
||||
- component: {fileID: 518730349}
|
||||
m_Layer: 0
|
||||
m_Name: Camera
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!20 &518730349
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 518730348}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &518730350
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 518730348}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 488, y: 418, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &519420028
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -278,9 +352,11 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: f0bc6c75abb2e0b47a25aa49bfd488ed, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
camera: {fileID: 518730349}
|
||||
okButton: {fileID: 16537672}
|
||||
cancelButton: {fileID: 628393011}
|
||||
text: {fileID: 2101290655}
|
||||
button: {fileID: 0}
|
||||
--- !u!20 &519420031
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -597,7 +673,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1556045504
|
||||
GameObject:
|
||||
@@ -693,7 +769,7 @@ RectTransform:
|
||||
- {fileID: 628393010}
|
||||
- {fileID: 2101290654}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
|
||||
8
src/UniTask/Assets/TempAsm.meta
Normal file
8
src/UniTask/Assets/TempAsm.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56fb2352cb532934f82d1590ce377e5c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
src/UniTask/Assets/TempAsm/FooMonoBehaviour.cs
Normal file
27
src/UniTask/Assets/TempAsm/FooMonoBehaviour.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
public class FooMonoBehaviour : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async UniTask Download(UnityWebRequest req, string filePath)
|
||||
{
|
||||
var foo = req.SendWebRequest();
|
||||
|
||||
|
||||
|
||||
|
||||
var aaa = await foo;
|
||||
Debug.Log(aaa);
|
||||
|
||||
//File.WriteAllText(filePath, req.downloadHandler.text ?? string.Empty);
|
||||
}
|
||||
}
|
||||
11
src/UniTask/Assets/TempAsm/FooMonoBehaviour.cs.meta
Normal file
11
src/UniTask/Assets/TempAsm/FooMonoBehaviour.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de703bd72a8720b47b7c3d993786aaae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
src/UniTask/Assets/TempAsm/TempAsm.asmdef
Normal file
16
src/UniTask/Assets/TempAsm/TempAsm.asmdef
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "TempAsm",
|
||||
"references": [
|
||||
"UniTask",
|
||||
""
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
src/UniTask/Assets/TempAsm/TempAsm.asmdef.meta
Normal file
7
src/UniTask/Assets/TempAsm/TempAsm.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d076e9cb44bf59e41ab73add08e510cf
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
153
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs
Normal file
153
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Scripting;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Collections;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.TestTools;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Cysharp.Threading.TasksTests
|
||||
{
|
||||
public class CoroutineToUniTaskTest
|
||||
{
|
||||
[UnityTest]
|
||||
public IEnumerator EarlyUpdate() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.EarlyUpdate);
|
||||
|
||||
var l = new List<(int, int)>();
|
||||
var currentFrame = Time.frameCount;
|
||||
var t = Worker(l).ToUniTask();
|
||||
|
||||
l.Count.Should().Be(1);
|
||||
l[0].Should().Be((0, currentFrame));
|
||||
|
||||
await t;
|
||||
|
||||
l[1].Should().Be((1, Time.frameCount));
|
||||
l[1].Item2.Should().NotBe(currentFrame);
|
||||
});
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator LateUpdate() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||
|
||||
var l = new List<(int, int)>();
|
||||
var currentFrame = Time.frameCount;
|
||||
var t = Worker(l).ToUniTask();
|
||||
|
||||
l.Count.Should().Be(1);
|
||||
l[0].Should().Be((0, currentFrame));
|
||||
|
||||
await t;
|
||||
|
||||
l[1].Should().Be((1, Time.frameCount));
|
||||
l[1].Item2.Should().NotBe(currentFrame);
|
||||
});
|
||||
|
||||
//[UnityTest]
|
||||
//public IEnumerator TestCoroutine()
|
||||
//{
|
||||
// yield return UniTask.Yield(PlayerLoopTiming.EarlyUpdate).ToUniTask().ToCoroutine();
|
||||
|
||||
// var nanika = (UnityEngine.MonoBehaviour)GameObject.FindObjectOfType(typeof(UnityEngine.MonoBehaviour));
|
||||
|
||||
// var l = new List<(int, int)>();
|
||||
// var currentFrame = Time.frameCount;
|
||||
// var t = nanika.StartCoroutine(Worker(l));
|
||||
|
||||
// l.Count.Should().Be(1);
|
||||
// l[0].Should().Be((0, currentFrame));
|
||||
|
||||
// yield return t;
|
||||
|
||||
// l[1].Should().Be((1, Time.frameCount));
|
||||
// l[1].Item2.Should().NotBe(currentFrame);
|
||||
//}
|
||||
|
||||
//[UnityTest]
|
||||
//public IEnumerator TestCoroutine2()
|
||||
//{
|
||||
// yield return UniTask.Yield(PlayerLoopTiming.PostLateUpdate).ToUniTask().ToCoroutine();
|
||||
|
||||
// var nanika = (UnityEngine.MonoBehaviour)GameObject.FindObjectOfType(typeof(UnityEngine.MonoBehaviour));
|
||||
|
||||
// var l = new List<(int, int)>();
|
||||
// var currentFrame = Time.frameCount;
|
||||
// var t = nanika.StartCoroutine(Worker(l));
|
||||
|
||||
// l.Count.Should().Be(1);
|
||||
// l[0].Should().Be((0, currentFrame));
|
||||
|
||||
// yield return t;
|
||||
|
||||
// l[1].Should().Be((1, Time.frameCount));
|
||||
// l[1].Item2.Should().NotBe(currentFrame);
|
||||
//}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||
|
||||
Time.timeScale = 0.5f;
|
||||
try
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
await WaitFor();
|
||||
|
||||
var elapsed = DateTimeOffset.UtcNow - now;
|
||||
|
||||
(5.8f <= elapsed.TotalSeconds && elapsed.TotalSeconds <= 6.2f).Should().BeTrue();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Time.timeScale = 1.0f;
|
||||
}
|
||||
});
|
||||
|
||||
IEnumerator WaitFor()
|
||||
{
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
}
|
||||
|
||||
IEnumerator Worker(List<(int, int)> l)
|
||||
{
|
||||
l.Add((0, Time.frameCount));
|
||||
yield return null;
|
||||
l.Add((1, Time.frameCount));
|
||||
}
|
||||
|
||||
public async UniTask Foo()
|
||||
{
|
||||
var tasks = new List<UniTask>();
|
||||
var t = Bar<int>();
|
||||
tasks.Add(t);
|
||||
|
||||
t = Bar<int>();
|
||||
tasks.Add(t);
|
||||
|
||||
await UniTask.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public async UniTask<T> Bar<T>()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43ffb719370515746932af3732ce073e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -176,10 +176,29 @@ namespace Cysharp.Threading.TasksTests
|
||||
});
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator DelayInThreadPool() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Run(async () =>
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(2));
|
||||
});
|
||||
});
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator DelayRealtime() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(2), DelayType.Realtime);
|
||||
|
||||
var elapsed = DateTimeOffset.UtcNow - now;
|
||||
|
||||
var okay1 = TimeSpan.FromSeconds(1.80) <= elapsed;
|
||||
var okay2 = elapsed <= TimeSpan.FromSeconds(2.20);
|
||||
|
||||
okay1.Should().Be(true);
|
||||
okay2.Should().Be(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user