mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-15 19:40:09 +00:00
Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b49b7332bb | ||
|
|
08184af737 | ||
|
|
0ef6c59385 | ||
|
|
4b0bd3b509 | ||
|
|
9a4720d180 | ||
|
|
b99646558c | ||
|
|
ee12dd9ae7 | ||
|
|
006e0f2c81 | ||
|
|
7d31299b5c | ||
|
|
fe8bf834e6 | ||
|
|
5843258e8c | ||
|
|
6cd002645e | ||
|
|
4fe0861714 | ||
|
|
fbbba061dd | ||
|
|
81f2e37ea5 | ||
|
|
66de0d3a58 | ||
|
|
beb10abbf7 | ||
|
|
d60f64761b | ||
|
|
36ac0863ad | ||
|
|
104f8e09ca | ||
|
|
cfbff008c4 | ||
|
|
5cc97c7f00 | ||
|
|
5666292496 | ||
|
|
1288cbc128 | ||
|
|
5f3aa18f38 | ||
|
|
0970ae8c31 | ||
|
|
ad23f7fb29 | ||
|
|
a4be8f316e | ||
|
|
370425578f | ||
|
|
1b76f77608 | ||
|
|
0579984355 | ||
|
|
39cf81d2ab | ||
|
|
0a203c8db9 | ||
|
|
55be4dba82 | ||
|
|
f0adf36633 | ||
|
|
24afc4f3eb | ||
|
|
2cf06af433 | ||
|
|
94be2e748b | ||
|
|
7f582e5e29 | ||
|
|
3f042c8886 | ||
|
|
6f5d818544 | ||
|
|
2ccb37cb02 | ||
|
|
cfe509a556 | ||
|
|
a46a4cac01 | ||
|
|
3ed28e534a | ||
|
|
be8dbe8804 | ||
|
|
64f7eec4e9 | ||
|
|
3a93f4a49f | ||
|
|
71958adc3d | ||
|
|
acc71550c9 | ||
|
|
3ba64412f8 | ||
|
|
90c5e5a6ad | ||
|
|
8a022ee02d | ||
|
|
6a89ea8139 | ||
|
|
90c81613ac | ||
|
|
7c62904a74 | ||
|
|
4f6344a12f | ||
|
|
937d3adf66 | ||
|
|
3bac16229f | ||
|
|
ea57847c97 | ||
|
|
730d68132d | ||
|
|
6db872236e | ||
|
|
ba7e676c6f | ||
|
|
6e99accf99 | ||
|
|
b195df9773 | ||
|
|
f303d9d7e8 | ||
|
|
62a2a2e8f9 | ||
|
|
ffbadbcc4c | ||
|
|
50ad2ee9d6 | ||
|
|
c170af5642 | ||
|
|
242bceecd3 | ||
|
|
06346b8a2a | ||
|
|
b071eeadfb | ||
|
|
e7f23d8328 | ||
|
|
47a3f09abf | ||
|
|
a7a6af0a68 | ||
|
|
f203b6c051 | ||
|
|
07211f1fc3 | ||
|
|
bc27f6c0d8 | ||
|
|
c65f9c3497 | ||
|
|
afe5f57adc | ||
|
|
9135c7ce56 | ||
|
|
7fae415689 | ||
|
|
e5cc8667ac | ||
|
|
0ea18d0e16 | ||
|
|
2d674999f0 | ||
|
|
3121903fa3 | ||
|
|
af2e49aa29 | ||
|
|
22940635fe | ||
|
|
c1042b32b7 | ||
|
|
29a144694d | ||
|
|
548d56e654 | ||
|
|
6fb4f2d6d2 | ||
|
|
8eac07ad24 | ||
|
|
716402a180 | ||
|
|
4c3d6938ed | ||
|
|
b4486802f2 | ||
|
|
d210e3d76a | ||
|
|
f2773f585e | ||
|
|
305695ad5d | ||
|
|
418ab36a72 | ||
|
|
563b4fbbd5 | ||
|
|
878d33115f | ||
|
|
356a4ee62e | ||
|
|
eb32ae25e0 | ||
|
|
3ca4062536 | ||
|
|
019f8aaf30 | ||
|
|
663fa737f3 | ||
|
|
73d86259ce | ||
|
|
c7eedf85c7 | ||
|
|
8dc3ffd552 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
github: [neuecc]
|
||||||
27
.github/workflows/build-debug.yml
vendored
27
.github/workflows/build-debug.yml
vendored
@@ -15,10 +15,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
3.1.x
|
|
||||||
6.0.x
|
|
||||||
- run: dotnet build -c Debug
|
- run: dotnet build -c Debug
|
||||||
- run: dotnet test -c Debug
|
- run: dotnet test -c Debug
|
||||||
|
|
||||||
@@ -27,13 +23,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
|
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
|
||||||
include:
|
|
||||||
- unity: 2019.3.9f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
- unity: 2019.4.13f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
- unity: 2020.1.12f1
|
|
||||||
license: UNITY_LICENSE_2020
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
@@ -41,31 +30,33 @@ jobs:
|
|||||||
# Execute scripts: RuntimeUnitTestToolkit
|
# Execute scripts: RuntimeUnitTestToolkit
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
||||||
- name: Build UnitTest(Linux64, mono)
|
- name: Build UnitTest(Linux64, mono)
|
||||||
uses: game-ci/unity-builder@v2
|
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
projectPath: src/UniTask
|
projectPath: src/UniTask
|
||||||
unityVersion: ${{ matrix.unity }}
|
unityVersion: ${{ matrix.unity }}
|
||||||
targetPlatform: StandaloneLinux64
|
targetPlatform: StandaloneLinux64
|
||||||
buildMethod: UnitTestBuilder.BuildUnitTest
|
buildMethod: UnitTestBuilder.BuildUnitTest
|
||||||
customParameters: /headless /ScriptBackend mono
|
customParameters: /headless /ScriptBackend mono
|
||||||
versioning: None
|
|
||||||
- name: Execute UnitTest
|
- name: Execute UnitTest
|
||||||
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
||||||
|
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
- name: Export unitypackage
|
- name: Build Unity (.unitypacakge)
|
||||||
uses: game-ci/unity-builder@v2
|
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
projectPath: src/UniTask
|
projectPath: src/UniTask
|
||||||
unityVersion: ${{ matrix.unity }}
|
unityVersion: ${{ matrix.unity }}
|
||||||
targetPlatform: StandaloneLinux64
|
targetPlatform: StandaloneLinux64
|
||||||
buildMethod: PackageExporter.Export
|
buildMethod: PackageExporter.Export
|
||||||
versioning: None
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
||||||
with:
|
with:
|
||||||
|
|||||||
16
.github/workflows/build-release.yml
vendored
16
.github/workflows/build-release.yml
vendored
@@ -34,10 +34,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
3.1.x
|
|
||||||
6.0.x
|
|
||||||
# build and pack
|
# build and pack
|
||||||
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
|
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
|
||||||
- run: dotnet test -c Release --no-build
|
- run: dotnet test -c Release --no-build
|
||||||
@@ -53,9 +49,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2019.3.9f1"]
|
unity: ["2019.3.9f1"]
|
||||||
include:
|
|
||||||
- unity: 2019.3.9f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
@@ -65,16 +58,17 @@ jobs:
|
|||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
- name: Export unitypackage
|
- name: Build Unity (.unitypacakge)
|
||||||
uses: game-ci/unity-builder@v2
|
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||||
|
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||||
|
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
|
||||||
with:
|
with:
|
||||||
projectPath: src/UniTask
|
projectPath: src/UniTask
|
||||||
unityVersion: ${{ matrix.unity }}
|
unityVersion: ${{ matrix.unity }}
|
||||||
targetPlatform: StandaloneLinux64
|
targetPlatform: StandaloneLinux64
|
||||||
buildMethod: PackageExporter.Export
|
buildMethod: PackageExporter.Export
|
||||||
versioning: None
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
||||||
with:
|
with:
|
||||||
|
|||||||
10
.github/workflows/prevent-github-change.yml
vendored
Normal file
10
.github/workflows/prevent-github-change.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
name: Prevent github change
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- ".github/**/*.yaml"
|
||||||
|
- ".github/**/*.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
detect:
|
||||||
|
uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main
|
||||||
48
README.md
48
README.md
@@ -44,7 +44,6 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
|||||||
- [API References](#api-references)
|
- [API References](#api-references)
|
||||||
- [UPM Package](#upm-package)
|
- [UPM Package](#upm-package)
|
||||||
- [Install via git URL](#install-via-git-url)
|
- [Install via git URL](#install-via-git-url)
|
||||||
- [Install via OpenUPM](#install-via-openupm)
|
|
||||||
- [.NET Core](#net-core)
|
- [.NET Core](#net-core)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
|||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
---
|
---
|
||||||
Install via [UPM package](#upm-package) or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases) page.
|
Install via [UPM package](#upm-package) with git reference or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// extension awaiter/methods can be used by this namespace
|
// extension awaiter/methods can be used by this namespace
|
||||||
@@ -86,8 +85,13 @@ async UniTask<string> DemoAsync()
|
|||||||
await UniTask.Yield();
|
await UniTask.Yield();
|
||||||
await UniTask.NextFrame();
|
await UniTask.NextFrame();
|
||||||
|
|
||||||
// replacement of WaitForEndOfFrame(requires MonoBehaviour(CoroutineRunner))
|
// replacement of WaitForEndOfFrame
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
await UniTask.WaitForEndOfFrame();
|
||||||
|
#else
|
||||||
|
// requires MonoBehaviour(CoroutineRunner))
|
||||||
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
|
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
|
||||||
|
#endif
|
||||||
|
|
||||||
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
||||||
await UniTask.WaitForFixedUpdate();
|
await UniTask.WaitForFixedUpdate();
|
||||||
@@ -291,7 +295,7 @@ public class MyBehaviour : MonoBehaviour
|
|||||||
|
|
||||||
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. When exception(not limited to `OperationCanceledException`) is not handled in async method, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`. The default behaviour of received unhandled exception is to write log as exception. Log level can be changed using `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to use custom behaviour, set an action to `UniTaskScheduler.UnobservedTaskException.`
|
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. When exception(not limited to `OperationCanceledException`) is not handled in async method, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`. The default behaviour of received unhandled exception is to write log as exception. Log level can be changed using `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to use custom behaviour, set an action to `UniTaskScheduler.UnobservedTaskException.`
|
||||||
|
|
||||||
Andalso `OperationCanceledException` is a special exception, this is silently ignored at `UnobservedTaskException`.
|
And also `OperationCanceledException` is a special exception, this is silently ignored at `UnobservedTaskException`.
|
||||||
|
|
||||||
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
||||||
|
|
||||||
@@ -332,6 +336,18 @@ if (isCanceled)
|
|||||||
|
|
||||||
Note: Only suppress throws if you call directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not suppress throws.
|
Note: Only suppress throws if you call directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not suppress throws.
|
||||||
|
|
||||||
|
Some features that use Unity's player loop, such as `UniTask.Yield` and `UniTask.Delay` etc, determines CancellationToken state on the player loop.
|
||||||
|
This means it does not cancel immediately upon `CancellationToken` fired.
|
||||||
|
|
||||||
|
If you want to change this behaviour, the cancellation to be immediate, set the `cancelImmediately` flag as an argument.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await UniTask.Yield(cancellationToken, cancelImmediately: true);
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Setting `cancelImmediately` to true and detecting an immediate cancellation is more costly than the default behavior.
|
||||||
|
This is because it uses `CancellationToken.Register`; it is heavier than checking CancellationToken on the player loop.
|
||||||
|
|
||||||
Timeout handling
|
Timeout handling
|
||||||
---
|
---
|
||||||
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
||||||
@@ -359,7 +375,7 @@ If you want to use timeout with other source of cancellation, use `CancellationT
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var cancelToken = new CancellationTokenSource();
|
var cancelToken = new CancellationTokenSource();
|
||||||
cancelButton.onClick.AddListener(()=>
|
cancelButton.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
cancelToken.Cancel(); // cancel from button click.
|
cancelToken.Cancel(); // cancel from button click.
|
||||||
});
|
});
|
||||||
@@ -499,6 +515,8 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
|
|||||||
`PlayerLoopTiming.Update` is similar to `yield return null` in a coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar to `WaitForFixedUpdate`.
|
`PlayerLoopTiming.Update` is similar to `yield return null` in a coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar to `WaitForFixedUpdate`.
|
||||||
|
|
||||||
> `PlayerLoopTiming.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
|
> `PlayerLoopTiming.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
|
||||||
|
>
|
||||||
|
> Note: In Unity 2023.1 or newer, `await UniTask.WaitForEndOfFrame();` no longer requires MonoBehaviour. It uses `UnityEngine.Awaitable.EndOfFrameAsync`.
|
||||||
|
|
||||||
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
|
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
|
||||||
|
|
||||||
@@ -658,7 +676,8 @@ By default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField`
|
|||||||
|
|
||||||
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
||||||
|
|
||||||
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager. However for DOTween support, it is required to import `com.demigiant.dotween` from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or to define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager.
|
||||||
|
However for DOTween support, after importing from the [DOTWeen assets](https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676r) and define the scripting define symbol `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// sequential
|
// sequential
|
||||||
@@ -681,7 +700,7 @@ Unity 2020.2 supports C# 8.0 so you can use `await foreach`. This is the new Upd
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Unity 2020.2, C# 8.0
|
// Unity 2020.2, C# 8.0
|
||||||
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate().WithCancellation(token))
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
}
|
}
|
||||||
@@ -691,10 +710,10 @@ In a C# 7.3 environment, you can use the `ForEachAsync` method to work in almost
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// C# 7.3(Unity 2018.3~)
|
// C# 7.3(Unity 2018.3~)
|
||||||
await UniTaskAsyncEnumerable.EveryUpdate(token).ForEachAsync(_ =>
|
await UniTaskAsyncEnumerable.EveryUpdate().ForEachAsync(_ =>
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
});
|
}, token);
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
||||||
@@ -717,7 +736,7 @@ Async LINQ is enabled when `using Cysharp.Threading.Tasks.Linq;`, and `UniTaskAs
|
|||||||
|
|
||||||
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.
|
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 `Enumerable`. 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`.
|
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. 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`,`Merge` `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`.
|
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
||||||
|
|
||||||
@@ -1072,13 +1091,6 @@ or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/
|
|||||||
|
|
||||||
If you want to set a target version, UniTask uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
|
If you want to set a target version, UniTask uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
|
||||||
|
|
||||||
### Install via OpenUPM
|
|
||||||
|
|
||||||
The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
|
||||||
|
|
||||||
```
|
|
||||||
openupm add com.cysharp.unitask
|
|
||||||
```
|
|
||||||
|
|
||||||
.NET Core
|
.NET Core
|
||||||
---
|
---
|
||||||
@@ -1088,7 +1100,7 @@ For .NET Core, use NuGet.
|
|||||||
|
|
||||||
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
|
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
|
||||||
|
|
||||||
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AysncLocal` also does not work because it ignores ExecutionContext.
|
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AsyncLocal` also does not work because it ignores ExecutionContext.
|
||||||
|
|
||||||
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
||||||
|
|
||||||
|
|||||||
11
README_CN.md
11
README_CN.md
@@ -661,7 +661,8 @@ UniTaskTracker 仅用于调试用途,因为启用跟踪和捕获堆栈跟踪
|
|||||||
|
|
||||||
在单独的 asmdef 中定义,如`UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
在单独的 asmdef 中定义,如`UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
||||||
|
|
||||||
从包管理器导入包时,会自动启用 TextMeshPro 和 Addressables 支持。但是对于 DOTween 支持,需要`com.demigiant.dotween`从[OpenUPM](https://openupm.com/packages/com.demigiant.dotween/)导入或定义`UNITASK_DOTWEEN_SUPPORT`以启用它。
|
从 Package manager 中导入软件包时,会自动启用对 TextMeshPro 和 Addressables 的支持。
|
||||||
|
但对于 DOTween 支持,则需要从 [DOTWeen assets](https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676r) 中导入并定义脚本定义符号 `UNITASK_DOTWEEN_SUPPORT` 后才能启用。
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// 动画序列
|
// 动画序列
|
||||||
@@ -684,7 +685,7 @@ Unity 2020.2 支持 C# 8.0,因此您可以使用`await foreach`. 这是异步
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Unity 2020.2, C# 8.0
|
// Unity 2020.2, C# 8.0
|
||||||
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate().WithCancellation(token))
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
}
|
}
|
||||||
@@ -694,10 +695,10 @@ await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// C# 7.3(Unity 2018.3~)
|
// C# 7.3(Unity 2018.3~)
|
||||||
await UniTaskAsyncEnumerable.EveryUpdate(token).ForEachAsync(_ =>
|
await UniTaskAsyncEnumerable.EveryUpdate().ForEachAsync(_ =>
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
});
|
}, token);
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTaskAsyncEnumerable 实现异步 LINQ,类似于 LINQ 的`IEnumerable<T>`或 Rx 的 `IObservable<T>`。所有标准 LINQ 查询运算符都可以应用于异步流。例如,以下代码表示如何将 Where 过滤器应用于每两次单击运行一次的按钮单击异步流。
|
UniTaskAsyncEnumerable 实现异步 LINQ,类似于 LINQ 的`IEnumerable<T>`或 Rx 的 `IObservable<T>`。所有标准 LINQ 查询运算符都可以应用于异步流。例如,以下代码表示如何将 Where 过滤器应用于每两次单击运行一次的按钮单击异步流。
|
||||||
@@ -1091,7 +1092,7 @@ openupm add com.cysharp.unitask
|
|||||||
|
|
||||||
.NET Core 版本的 UniTask 是 Unity UniTask 的子集,移除了 PlayerLoop 依赖的方法。
|
.NET Core 版本的 UniTask 是 Unity UniTask 的子集,移除了 PlayerLoop 依赖的方法。
|
||||||
|
|
||||||
它以比标准 Task/ValueTask 更高的性能运行,但在使用时应注意忽略 ExecutionContext/SynchronizationContext。`AysncLocal`也不起作用,因为它忽略了 ExecutionContext。
|
它以比标准 Task/ValueTask 更高的性能运行,但在使用时应注意忽略 ExecutionContext/SynchronizationContext。`AsyncLocal`也不起作用,因为它忽略了 ExecutionContext。
|
||||||
|
|
||||||
如果您在内部使用 UniTask,但将 ValueTask 作为外部 API 提供,您可以编写如下(受[PooledAwait](https://github.com/mgravell/PooledAwait)启发)代码。
|
如果您在内部使用 UniTask,但将 ValueTask 作为外部 API 提供,您可以编写如下(受[PooledAwait](https://github.com/mgravell/PooledAwait)启发)代码。
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,43 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.1;netstandard2.1;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0;netstandard2.1;netstandard2.0</TargetFrameworks>
|
||||||
<AssemblyName>UniTask</AssemblyName>
|
<AssemblyName>UniTask</AssemblyName>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<DefineConstants>UNITASK_NETCORE</DefineConstants>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
|
||||||
<!-- NuGet Packaging -->
|
<!-- NuGet Packaging -->
|
||||||
<Id>UniTask</Id>
|
<Id>UniTask</Id>
|
||||||
<PackageVersion>$(Version)</PackageVersion>
|
<PackageVersion>$(Version)</PackageVersion>
|
||||||
<Company>Cysharp</Company>
|
<Company>Cysharp</Company>
|
||||||
<Authors>Cysharp</Authors>
|
<Authors>Cysharp</Authors>
|
||||||
<Copyright>© Cysharp, Inc.</Copyright>
|
<Copyright>© Cysharp, Inc.</Copyright>
|
||||||
<PackageTags>task;async</PackageTags>
|
<PackageTags>task;async</PackageTags>
|
||||||
<Description>Provides an efficient async/await integration to Unity and .NET Core.</Description>
|
<Description>Provides an efficient async/await integration to Unity and .NET Core.</Description>
|
||||||
<PackageProjectUrl>https://github.com/Cysharp/UniTask</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Cysharp/UniTask</PackageProjectUrl>
|
||||||
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
|
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Icon.png</PackageIcon>
|
<PackageIcon>Icon.png</PackageIcon>
|
||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>opensource.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>opensource.snk</AssemblyOriginatorKeyFile>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Icon.png" Pack="true" PackagePath="/" />
|
<None Include="Icon.png" Pack="true" PackagePath="/" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs" Exclude="
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Triggers\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Linq\UnityExtensions\*.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityEqualityComparer.cs;
..\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\TimeoutController.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopTimer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
..\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.*;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
" />
|
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs" Exclude="
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Triggers\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Linq\UnityExtensions\*.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityEqualityComparer.cs;
..\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\TimeoutController.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopTimer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
..\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.*;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
" />
|
||||||
<Compile Remove="..\UniTask\Assets\Plugins\UniTask\Runtime\_InternalVisibleTo.cs" />
|
<Compile Remove="..\UniTask\Assets\Plugins\UniTask\Runtime\_InternalVisibleTo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<RootNamespace>NetCoreSandbox</RootNamespace>
|
<RootNamespace>NetCoreSandbox</RootNamespace>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -159,6 +159,30 @@ namespace NetCoreTests.Linq
|
|||||||
list.Should().Equal(100, 200, 300, 400);
|
list.Should().Equal(100, 200, 300, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AwaitForeachBreak()
|
||||||
|
{
|
||||||
|
var finallyCalled = false;
|
||||||
|
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await writer.YieldAsync(1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
finallyCalled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await foreach (var x in enumerable)
|
||||||
|
{
|
||||||
|
x.Should().Be(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
finallyCalled.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
async IAsyncEnumerable<int> Range(int from, int count)
|
async IAsyncEnumerable<int> Range(int from, int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
|
|||||||
139
src/UniTask.NetCoreTests/Linq/Merge.cs
Normal file
139
src/UniTask.NetCoreTests/Linq/Merge.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#pragma warning disable CS1998
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests.Linq
|
||||||
|
{
|
||||||
|
public class MergeTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task TwoSource()
|
||||||
|
{
|
||||||
|
var semaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A2");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
await writer.YieldAsync("B2");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B3");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await a.Merge(b).ToArrayAsync();
|
||||||
|
result.Should().Equal("A1", "B1", "B2", "A2", "B3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ThreeSource()
|
||||||
|
{
|
||||||
|
var semaphore = new SemaphoreSlim(0, 1);
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A2");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
await writer.YieldAsync("B2");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B3");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var c = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await writer.YieldAsync("C1");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await a.Merge(b, c).ToArrayAsync();
|
||||||
|
result.Should().Equal("C1", "A1", "B1", "B2", "A2", "B3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Throw()
|
||||||
|
{
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
throw new UniTaskTestException();
|
||||||
|
});
|
||||||
|
|
||||||
|
var enumerator = a.Merge(b).GetAsyncEnumerator();
|
||||||
|
(await enumerator.MoveNextAsync()).Should().Be(true);
|
||||||
|
enumerator.Current.Should().Be("A1");
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<UniTaskTestException>(async () => await enumerator.MoveNextAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Cancel()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
});
|
||||||
|
|
||||||
|
var enumerator = a.Merge(b).GetAsyncEnumerator(cts.Token);
|
||||||
|
(await enumerator.MoveNextAsync()).Should().Be(true);
|
||||||
|
enumerator.Current.Should().Be("A1");
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
await Assert.ThrowsAsync<OperationCanceledException>(async () => await enumerator.MoveNextAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/UniTask.NetCoreTests/TaskExtensionsTest.cs
Normal file
45
src/UniTask.NetCoreTests/TaskExtensionsTest.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma warning disable CS1998
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class TaskExtensionsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task PropagateException()
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await ThrowAsync().AsUniTask();
|
||||||
|
});
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await ThrowOrValueAsync().AsUniTask();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PropagateExceptionWhenAll()
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await Task.WhenAll(ThrowAsync(), ThrowAsync()).AsUniTask();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task ThrowAsync()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<int> ThrowOrValueAsync()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
|||||||
80
src/UniTask.NetCoreTests/UniTaskCompletionSourceTest.cs
Normal file
80
src/UniTask.NetCoreTests/UniTaskCompletionSourceTest.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NetCoreTests.Linq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class AutoResetUniTaskCompletionSourceTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task SetResultAfterReturn()
|
||||||
|
{
|
||||||
|
var source1 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source1.TrySetResult();
|
||||||
|
await source1.Task;
|
||||||
|
|
||||||
|
source1.TrySetResult().Should().BeFalse();
|
||||||
|
|
||||||
|
var source2 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source2.TrySetResult();
|
||||||
|
await source2.Task;
|
||||||
|
|
||||||
|
source2.TrySetResult().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetCancelAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source.TrySetResult();
|
||||||
|
await source.Task;
|
||||||
|
|
||||||
|
source.TrySetCanceled().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetExceptionAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source.TrySetResult();
|
||||||
|
await source.Task;
|
||||||
|
|
||||||
|
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetResultWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source1 = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source1.TrySetResult(100);
|
||||||
|
(await source1.Task).Should().Be(100);
|
||||||
|
|
||||||
|
source1.TrySetResult(100).Should().BeFalse();
|
||||||
|
|
||||||
|
var source2 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source2.TrySetResult();
|
||||||
|
await source2.Task;
|
||||||
|
source2.TrySetResult().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetCancelWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source.TrySetResult(100);
|
||||||
|
(await source.Task).Should().Be(100);
|
||||||
|
source.TrySetCanceled().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetExceptionWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source.TrySetResult(100);
|
||||||
|
(await source.Task).Should().Be(100);
|
||||||
|
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using UnityEngine.AddressableAssets;
|
||||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
@@ -20,12 +21,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCancelled = false)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCancelled: autoReleaseWhenCancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCancelled = false)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCancelled, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -103,20 +104,22 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle> continuationAction;
|
readonly Action<AsyncOperationHandle> completedCallback;
|
||||||
AsyncOperationHandle handle;
|
AsyncOperationHandle handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
|
bool autoReleaseWhenCancelled;
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
completedCallback = HandleCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCancelled, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -132,20 +135,37 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
|
result.autoReleaseWhenCancelled = autoReleaseWhenCancelled;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncOperationHandleConfiguredSource)state;
|
||||||
|
if (promise.autoReleaseWhenCancelled && promise.handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(promise.handle);
|
||||||
|
}
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.continuationAction;
|
handle.Completed += result.completedCallback;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperationHandle _)
|
void HandleCompleted(AsyncOperationHandle _)
|
||||||
{
|
{
|
||||||
handle.Completed -= continuationAction;
|
if (handle.IsValid())
|
||||||
|
{
|
||||||
|
handle.Completed -= completedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
@@ -156,6 +176,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
if (autoReleaseWhenCancelled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (handle.Status == AsyncOperationStatus.Failed)
|
else if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
@@ -200,6 +224,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
|
if (autoReleaseWhenCancelled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -219,6 +247,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,12 +261,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCancelled = false)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCancelled: autoReleaseWhenCancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCancelled = false)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
||||||
|
|
||||||
@@ -255,7 +284,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return UniTask.FromResult(handle.Result);
|
return UniTask.FromResult(handle.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCancelled, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||||
@@ -269,20 +298,22 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
readonly Action<AsyncOperationHandle<T>> completedCallback;
|
||||||
AsyncOperationHandle<T> handle;
|
AsyncOperationHandle<T> handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
|
bool autoReleaseWhenCancelled;
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
completedCallback = HandleCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCancelled, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -298,20 +329,37 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
|
result.autoReleaseWhenCancelled = autoReleaseWhenCancelled;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncOperationHandleConfiguredSource<T>)state;
|
||||||
|
if (promise.autoReleaseWhenCancelled && promise.handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(promise.handle);
|
||||||
|
}
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.continuationAction;
|
handle.Completed += result.completedCallback;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperationHandle<T> argHandle)
|
void HandleCompleted(AsyncOperationHandle<T> argHandle)
|
||||||
{
|
{
|
||||||
handle.Completed -= continuationAction;
|
if (handle.IsValid())
|
||||||
|
{
|
||||||
|
handle.Completed -= completedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
@@ -322,6 +370,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
if (autoReleaseWhenCancelled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
||||||
@@ -371,6 +423,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
|
if (autoReleaseWhenCancelled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -390,6 +446,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
"name": "UniTask.Addressables",
|
"name": "UniTask.Addressables",
|
||||||
"references": [
|
"references": [
|
||||||
"UniTask",
|
"UniTask",
|
||||||
"Unity.ResourceManager"
|
"Unity.ResourceManager",
|
||||||
|
"Unity.Addressables"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -144,22 +144,20 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
readonly TweenCallback onCompleteCallbackDelegate;
|
readonly TweenCallback onCompleteCallbackDelegate;
|
||||||
readonly TweenCallback onUpdateDelegate;
|
|
||||||
|
|
||||||
Tween tween;
|
Tween tween;
|
||||||
TweenCancelBehaviour cancelBehaviour;
|
TweenCancelBehaviour cancelBehaviour;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationRegistration;
|
||||||
CallbackType callbackType;
|
CallbackType callbackType;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
|
||||||
TweenCallback originalUpdateAction;
|
|
||||||
TweenCallback originalCompleteAction;
|
TweenCallback originalCompleteAction;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
TweenConfiguredSource()
|
TweenConfiguredSource()
|
||||||
{
|
{
|
||||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
||||||
onUpdateDelegate = OnUpdate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
||||||
@@ -179,17 +177,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.cancelBehaviour = cancelBehaviour;
|
result.cancelBehaviour = cancelBehaviour;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.callbackType = callbackType;
|
result.callbackType = callbackType;
|
||||||
|
|
||||||
result.originalUpdateAction = tween.onUpdate;
|
|
||||||
result.canceled = false;
|
result.canceled = false;
|
||||||
|
|
||||||
if (result.originalUpdateAction == result.onUpdateDelegate)
|
|
||||||
{
|
|
||||||
result.originalUpdateAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
tween.onUpdate = result.onUpdateDelegate;
|
|
||||||
|
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
@@ -225,6 +214,50 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.originalCompleteAction = null;
|
result.originalCompleteAction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
|
||||||
|
{
|
||||||
|
var source = (TweenConfiguredSource)x;
|
||||||
|
switch (source.cancelBehaviour)
|
||||||
|
{
|
||||||
|
case TweenCancelBehaviour.Kill:
|
||||||
|
default:
|
||||||
|
source.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
|
source.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.Complete:
|
||||||
|
source.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
||||||
|
source.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
source.RestoreOriginalCallback();
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
@@ -255,77 +288,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
originalUpdateAction?.Invoke();
|
|
||||||
|
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.cancelBehaviour)
|
|
||||||
{
|
|
||||||
case TweenCancelBehaviour.Kill:
|
|
||||||
default:
|
|
||||||
this.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallback:
|
|
||||||
this.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.Complete:
|
|
||||||
this.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
|
||||||
this.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
|
||||||
// restore to original callback
|
|
||||||
switch (callbackType)
|
|
||||||
{
|
|
||||||
case CallbackType.Kill:
|
|
||||||
tween.onKill = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Complete:
|
|
||||||
tween.onComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Pause:
|
|
||||||
tween.onPause = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Play:
|
|
||||||
tween.onPlay = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Rewind:
|
|
||||||
tween.onRewind = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.StepComplete:
|
|
||||||
tween.onStepComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.core.TrySetCanceled(this.cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -392,8 +354,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
tween.onUpdate = originalUpdateAction;
|
cancellationRegistration.Dispose();
|
||||||
|
|
||||||
|
RestoreOriginalCallback();
|
||||||
|
|
||||||
|
tween = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
originalCompleteAction = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreOriginalCallback()
|
||||||
|
{
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
@@ -417,12 +389,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tween = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
originalUpdateAction = default;
|
|
||||||
originalCompleteAction = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable CS0108
|
||||||
|
|
||||||
|
#if (UNITASK_NETCORE && !NETSTANDARD2_0) || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -19,9 +24,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
// similar as IValueTaskSource
|
// similar as IValueTaskSource
|
||||||
public interface IUniTaskSource
|
public interface IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
: System.Threading.Tasks.Sources.IValueTaskSource
|
: System.Threading.Tasks.Sources.IValueTaskSource
|
||||||
#pragma warning disable CS0108
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UniTaskStatus GetStatus(short token);
|
UniTaskStatus GetStatus(short token);
|
||||||
@@ -30,8 +34,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
#pragma warning restore CS0108
|
|
||||||
|
|
||||||
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
|
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
|
||||||
{
|
{
|
||||||
@@ -53,13 +56,13 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface IUniTaskSource<out T> : IUniTaskSource
|
public interface IUniTaskSource<out T> : IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
, System.Threading.Tasks.Sources.IValueTaskSource<T>
|
, System.Threading.Tasks.Sources.IValueTaskSource<T>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
new T GetResult(short token);
|
new T GetResult(short token);
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
new public UniTaskStatus GetStatus(short token)
|
new public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
public static void ThrowArgumentException<T>(string message)
|
public static void ThrowArgumentException(string message)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(message);
|
throw new ArgumentException(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
|
writer.Dispose();
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
|
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
||||||
{
|
{
|
||||||
readonly _Create enumerator;
|
readonly _Create enumerator;
|
||||||
|
|
||||||
@@ -137,6 +138,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
this.enumerator = enumerator;
|
this.enumerator = enumerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var status = core.GetStatus(core.Version);
|
||||||
|
if (status == UniTaskStatus.Pending)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
{
|
{
|
||||||
|
|||||||
232
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Merge.cs
Normal file
232
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Merge.cs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
{
|
||||||
|
public static partial class UniTaskAsyncEnumerable
|
||||||
|
{
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(first, nameof(first));
|
||||||
|
Error.ThrowArgumentNullException(second, nameof(second));
|
||||||
|
|
||||||
|
return new Merge<T>(new [] { first, second });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second, IUniTaskAsyncEnumerable<T> third)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(first, nameof(first));
|
||||||
|
Error.ThrowArgumentNullException(second, nameof(second));
|
||||||
|
Error.ThrowArgumentNullException(third, nameof(third));
|
||||||
|
|
||||||
|
return new Merge<T>(new[] { first, second, third });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IEnumerable<IUniTaskAsyncEnumerable<T>> sources)
|
||||||
|
{
|
||||||
|
return new Merge<T>(sources.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(params IUniTaskAsyncEnumerable<T>[] sources)
|
||||||
|
{
|
||||||
|
return new Merge<T>(sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class Merge<T> : IUniTaskAsyncEnumerable<T>
|
||||||
|
{
|
||||||
|
readonly IUniTaskAsyncEnumerable<T>[] sources;
|
||||||
|
|
||||||
|
public Merge(IUniTaskAsyncEnumerable<T>[] sources)
|
||||||
|
{
|
||||||
|
if (sources.Length <= 0)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentException("No source async enumerable to merge");
|
||||||
|
}
|
||||||
|
this.sources = sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
=> new _Merge(sources, cancellationToken);
|
||||||
|
|
||||||
|
enum MergeSourceState
|
||||||
|
{
|
||||||
|
Pending,
|
||||||
|
Running,
|
||||||
|
Completed,
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class _Merge : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
||||||
|
{
|
||||||
|
static readonly Action<object> GetResultAtAction = GetResultAt;
|
||||||
|
|
||||||
|
readonly int length;
|
||||||
|
readonly IUniTaskAsyncEnumerator<T>[] enumerators;
|
||||||
|
readonly MergeSourceState[] states;
|
||||||
|
readonly Queue<(T, Exception, bool)> queuedResult = new Queue<(T, Exception, bool)>();
|
||||||
|
readonly CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int moveNextCompleted;
|
||||||
|
|
||||||
|
public T Current { get; private set; }
|
||||||
|
|
||||||
|
public _Merge(IUniTaskAsyncEnumerable<T>[] sources, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
length = sources.Length;
|
||||||
|
states = ArrayPool<MergeSourceState>.Shared.Rent(length);
|
||||||
|
enumerators = ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Rent(length);
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
enumerators[i] = sources[i].GetAsyncEnumerator(cancellationToken);
|
||||||
|
states[i] = (int)MergeSourceState.Pending;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
completionSource.Reset();
|
||||||
|
Interlocked.Exchange(ref moveNextCompleted, 0);
|
||||||
|
|
||||||
|
if (HasQueuedResult() && Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
(T, Exception, bool) value;
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
value = queuedResult.Dequeue();
|
||||||
|
}
|
||||||
|
var resultValue = value.Item1;
|
||||||
|
var exception = value.Item2;
|
||||||
|
var hasNext = value.Item3;
|
||||||
|
if (exception != null)
|
||||||
|
{
|
||||||
|
completionSource.TrySetException(exception);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Current = resultValue;
|
||||||
|
completionSource.TrySetResult(hasNext);
|
||||||
|
}
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
if (states[i] == MergeSourceState.Pending)
|
||||||
|
{
|
||||||
|
states[i] = MergeSourceState.Running;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var awaiter = enumerators[i].MoveNextAsync().GetAwaiter();
|
||||||
|
if (awaiter.IsCompleted)
|
||||||
|
{
|
||||||
|
GetResultAt(i, awaiter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(GetResultAtAction, StateTuple.Create(this, i, awaiter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
await enumerators[i].DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayPool<MergeSourceState>.Shared.Return(states, true);
|
||||||
|
ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Return(enumerators, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetResultAt(object state)
|
||||||
|
{
|
||||||
|
using (var tuple = (StateTuple<_Merge, int, UniTask<bool>.Awaiter>)state)
|
||||||
|
{
|
||||||
|
tuple.Item1.GetResultAt(tuple.Item2, tuple.Item3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetResultAt(int index, UniTask<bool>.Awaiter awaiter)
|
||||||
|
{
|
||||||
|
bool hasNext;
|
||||||
|
bool completedAll;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hasNext = awaiter.GetResult();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
completionSource.TrySetException(ex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
queuedResult.Enqueue((default, ex, default));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
states[index] = hasNext ? MergeSourceState.Pending : MergeSourceState.Completed;
|
||||||
|
completedAll = !hasNext && IsCompletedAll();
|
||||||
|
}
|
||||||
|
if (hasNext || completedAll)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Current = enumerators[index].Current;
|
||||||
|
completionSource.TrySetResult(!completedAll);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
queuedResult.Enqueue((enumerators[index].Current, null, !completedAll));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasQueuedResult()
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
return queuedResult.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompletedAll()
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (states[i] != MergeSourceState.Completed)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ca56812f160c45d0bacb4339819edf1a
|
||||||
|
timeCreated: 1694133666
|
||||||
@@ -4,38 +4,50 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new EveryUpdate(updateTiming);
|
return new EveryUpdate(updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryUpdate(PlayerLoopTiming updateTiming)
|
public EveryUpdate(PlayerLoopTiming updateTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryUpdate(updateTiming, cancellationToken);
|
return new _EveryUpdate(updateTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryUpdate)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
@@ -44,10 +56,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +71,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
@@ -63,7 +80,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null)
|
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null, bool cancelImmediately = false)
|
||||||
where TTarget : class
|
where TTarget : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
@@ -15,11 +15,11 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
if (isUnityObject)
|
if (isUnityObject)
|
||||||
{
|
{
|
||||||
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,18 +30,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
@@ -50,13 +52,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly UnityEngine.Object targetAsUnityObject;
|
readonly UnityEngine.Object targetAsUnityObject;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.targetAsUnityObject = target as UnityEngine.Object;
|
this.targetAsUnityObject = target as UnityEngine.Object;
|
||||||
@@ -64,6 +67,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryValueChanged)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
@@ -72,8 +85,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
|
||||||
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
@@ -86,7 +106,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +113,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
@@ -102,13 +122,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || targetAsUnityObject == null) // destroyed = cancel.
|
if (disposed || targetAsUnityObject == null)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -139,18 +164,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = new WeakReference<TTarget>(target, false);
|
this.target = new WeakReference<TTarget>(target, false);
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
@@ -158,19 +185,30 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly WeakReference<TTarget> target;
|
readonly WeakReference<TTarget> target;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryValueChanged)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
@@ -179,8 +217,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
if (disposed) return CompletedTasks.False;
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
first = false;
|
first = false;
|
||||||
@@ -192,7 +238,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +245,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
@@ -208,13 +254,19 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
|
if (disposed || !target.TryGetTarget(out var t))
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,32 +6,32 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
|
return new Timer(dueTime, null, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
|
return new Timer(dueTime, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(period, period, updateTiming, ignoreTimeScale);
|
return new Timer(period, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, null, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
@@ -42,16 +42,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (intervalFrameCount < 0)
|
if (intervalFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
||||||
}
|
}
|
||||||
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,18 +61,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly TimeSpan dueTime;
|
readonly TimeSpan dueTime;
|
||||||
readonly TimeSpan? period;
|
readonly TimeSpan? period;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
|
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTime = dueTime;
|
this.dueTime = dueTime;
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
|
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
@@ -81,7 +83,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly float? period;
|
readonly float? period;
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
@@ -89,7 +92,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
|
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.dueTime = (float)dueTime.TotalSeconds;
|
this.dueTime = (float)dueTime.TotalSeconds;
|
||||||
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
||||||
@@ -105,6 +108,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_Timer)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
@@ -114,12 +127,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
// return false instead of throw
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
if (disposed || completed) return CompletedTasks.False;
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.elapsed = 0;
|
this.elapsed = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +144,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
@@ -135,11 +153,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
@@ -187,24 +210,27 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
|
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
|
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
int currentFrame;
|
int currentFrame;
|
||||||
@@ -212,7 +238,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
||||||
if (periodFrameCount != null)
|
if (periodFrameCount != null)
|
||||||
@@ -225,6 +251,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_TimerFrame)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
@@ -234,13 +269,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed || completed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.currentFrame = 0;
|
this.currentFrame = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
@@ -249,6 +286,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
@@ -257,7 +295,12 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -285,7 +285,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return dest.ToArray();
|
return dest.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
|
#endif
|
||||||
static void Init()
|
static void Init()
|
||||||
{
|
{
|
||||||
// capture default(unity) sync-context.
|
// capture default(unity) sync-context.
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
ITriggerHandler<T> head; // head.prev is last
|
ITriggerHandler<T> head; // head.prev is last
|
||||||
ITriggerHandler<T> iteratingHead;
|
ITriggerHandler<T> iteratingHead;
|
||||||
|
|
||||||
bool preserveRemoveSelf;
|
|
||||||
ITriggerHandler<T> iteratingNode;
|
ITriggerHandler<T> iteratingNode;
|
||||||
|
|
||||||
void LogError(Exception ex)
|
void LogError(Exception ex)
|
||||||
@@ -55,18 +53,9 @@ namespace Cysharp.Threading.Tasks
|
|||||||
Remove(h);
|
Remove(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preserveRemoveSelf)
|
// If `h` itself is removed by OnNext, h.Next is null.
|
||||||
{
|
// Therefore, instead of looking at h.Next, the `iteratingNode` reference itself is replaced.
|
||||||
preserveRemoveSelf = false;
|
h = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
|
||||||
h = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h = h.Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
@@ -97,9 +86,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
@@ -132,9 +120,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
@@ -167,9 +154,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
@@ -241,71 +227,65 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||||
|
|
||||||
if (iteratingNode != null && iteratingNode == handler)
|
var prev = handler.Prev;
|
||||||
|
var next = handler.Next;
|
||||||
|
|
||||||
|
if (next != null)
|
||||||
{
|
{
|
||||||
// if remove self, reserve remove self after invoke completed.
|
next.Prev = prev;
|
||||||
preserveRemoveSelf = true;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (handler == head)
|
||||||
{
|
{
|
||||||
var prev = handler.Prev;
|
head = next;
|
||||||
var next = handler.Next;
|
|
||||||
|
|
||||||
if (next != null)
|
|
||||||
{
|
|
||||||
next.Prev = prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler == head)
|
|
||||||
{
|
|
||||||
head = next;
|
|
||||||
}
|
|
||||||
else if (handler == iteratingHead)
|
|
||||||
{
|
|
||||||
iteratingHead = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// when handler is head, prev indicate last so don't use it.
|
|
||||||
if (prev != null)
|
|
||||||
{
|
|
||||||
prev.Next = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (head != null)
|
|
||||||
{
|
|
||||||
if (head.Prev == handler)
|
|
||||||
{
|
|
||||||
if (prev != head)
|
|
||||||
{
|
|
||||||
head.Prev = prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
head.Prev = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iteratingHead != null)
|
|
||||||
{
|
|
||||||
if (iteratingHead.Prev == handler)
|
|
||||||
{
|
|
||||||
if (prev != iteratingHead.Prev)
|
|
||||||
{
|
|
||||||
iteratingHead.Prev = prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iteratingHead.Prev = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.Prev = null;
|
|
||||||
handler.Next = null;
|
|
||||||
}
|
}
|
||||||
|
// when handler is head, prev indicate last so don't use it.
|
||||||
|
else if (prev != null)
|
||||||
|
{
|
||||||
|
prev.Next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler == iteratingNode)
|
||||||
|
{
|
||||||
|
iteratingNode = next;
|
||||||
|
}
|
||||||
|
if (handler == iteratingHead)
|
||||||
|
{
|
||||||
|
iteratingHead = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head != null)
|
||||||
|
{
|
||||||
|
if (head.Prev == handler)
|
||||||
|
{
|
||||||
|
if (prev != head)
|
||||||
|
{
|
||||||
|
head.Prev = prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
head.Prev = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iteratingHead != null)
|
||||||
|
{
|
||||||
|
if (iteratingHead.Prev == handler)
|
||||||
|
{
|
||||||
|
if (prev != iteratingHead.Prev)
|
||||||
|
{
|
||||||
|
iteratingHead.Prev = prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iteratingHead.Prev = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.Prev = null;
|
||||||
|
handler.Next = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
if (cancellationTokenSource == null)
|
if (cancellationTokenSource == null)
|
||||||
{
|
{
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
if (!awakeCalled)
|
||||||
|
{
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!awakeCalled)
|
|
||||||
{
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return cancellationTokenSource.Token;
|
return cancellationTokenSource.Token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +81,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (trigger.called) return false;
|
if (trigger.called || trigger.awakeCalled) return false;
|
||||||
if (trigger == null)
|
if (trigger == null)
|
||||||
{
|
{
|
||||||
trigger.OnDestroy();
|
trigger.OnDestroy();
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
|
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Sources;
|
using System.Threading.Tasks.Sources;
|
||||||
@@ -10,7 +16,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public static ValueTask AsValueTask(this in UniTask task)
|
public static ValueTask AsValueTask(this in UniTask task)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
@@ -19,7 +25,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
@@ -36,7 +42,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
await task;
|
await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
|
|
||||||
class UniTaskValueTaskSource : IValueTaskSource
|
class UniTaskValueTaskSource : IValueTaskSource
|
||||||
{
|
{
|
||||||
@@ -95,3 +101,4 @@ namespace Cysharp.Threading.Tasks
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d38f0478933be42d895c37b862540a1c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -33,14 +33,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new YieldAwaitable(timing);
|
return new YieldAwaitable(timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Yield(CancellationToken cancellationToken)
|
public static UniTask Yield(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -48,7 +48,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame()
|
public static UniTask NextFrame()
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, out var token), token);
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, false, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -56,25 +56,31 @@ namespace Cysharp.Threading.Tasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing)
|
public static UniTask NextFrame(PlayerLoopTiming timing)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, false, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(CancellationToken cancellationToken)
|
public static UniTask NextFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
public static async UniTask WaitForEndOfFrame(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
await Awaitable.EndOfFrameAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
#else
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
||||||
public static YieldAwaitable WaitForEndOfFrame()
|
public static YieldAwaitable WaitForEndOfFrame()
|
||||||
{
|
{
|
||||||
@@ -82,14 +88,21 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
||||||
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
|
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner)
|
||||||
|
{
|
||||||
|
var source = WaitForEndOfFramePromise.Create(coroutineRunner, CancellationToken.None, false, out var token);
|
||||||
|
return new UniTask(source, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken = default)
|
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, out var token);
|
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, cancelImmediately, out var token);
|
||||||
return new UniTask(source, token);
|
return new UniTask(source, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,40 +119,50 @@ namespace Cysharp.Threading.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
|
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken);
|
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (delayFrameCount < 0)
|
if (delayFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (delayTimeSpan < TimeSpan.Zero)
|
if (delayTimeSpan < TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
@@ -158,16 +181,16 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
case DelayType.UnscaledDeltaTime:
|
case DelayType.UnscaledDeltaTime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.Realtime:
|
case DelayType.Realtime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.DeltaTime:
|
case DelayType.DeltaTime:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,13 +207,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
YieldPromise()
|
YieldPromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -202,8 +226,16 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result = new YieldPromise();
|
result = new YieldPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (YieldPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -257,6 +289,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,14 +306,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
int frameCount;
|
int frameCount;
|
||||||
CancellationToken cancellationToken;
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
NextFramePromise()
|
NextFramePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -295,6 +329,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (NextFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -352,6 +395,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,14 +411,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
WaitForEndOfFramePromise()
|
WaitForEndOfFramePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -388,6 +433,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitForEndOfFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
coroutineRunner.StartCoroutine(result);
|
coroutineRunner.StartCoroutine(result);
|
||||||
@@ -429,6 +483,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
Reset(); // Reset Enumerator
|
Reset(); // Reset Enumerator
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +532,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
int initialFrame;
|
int initialFrame;
|
||||||
int delayFrameCount;
|
int delayFrameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
int currentFrameCount;
|
int currentFrameCount;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
@@ -485,7 +541,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -501,6 +557,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -587,6 +652,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
currentFrameCount = default;
|
currentFrameCount = default;
|
||||||
delayFrameCount = default;
|
delayFrameCount = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -606,6 +672,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
float delayTimeSpan;
|
float delayTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
@@ -613,7 +680,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -630,6 +697,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -698,6 +774,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
delayTimeSpan = default;
|
delayTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -717,6 +794,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
float elapsed;
|
float elapsed;
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
@@ -724,7 +802,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -741,6 +819,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayIgnoreTimeScalePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -809,6 +896,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
delayFrameTimeSpan = default;
|
delayFrameTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -827,6 +915,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
long delayTimeSpanTicks;
|
long delayTimeSpanTicks;
|
||||||
ValueStopwatch stopwatch;
|
ValueStopwatch stopwatch;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
@@ -834,7 +923,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -850,6 +939,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayRealtimePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -914,6 +1012,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
stopwatch = default;
|
stopwatch = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,30 +9,30 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, out var token), token);
|
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token);
|
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update, bool completeImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, out var token), token);
|
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, completeImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
||||||
|
|
||||||
return new UniTask<U>(isUnityObject
|
return new UniTask<U>(isUnityObject
|
||||||
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out var token)
|
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out var token)
|
||||||
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token);
|
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
||||||
@@ -48,6 +48,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
Func<bool> predicate;
|
Func<bool> predicate;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -70,6 +71,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -136,6 +146,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,6 +164,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
Func<bool> predicate;
|
Func<bool> predicate;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
@@ -160,7 +172,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -174,6 +186,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitWhilePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -241,6 +262,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,6 +279,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
@@ -264,7 +287,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, out short token)
|
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, bool completeImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -278,6 +301,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (completeImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilCanceledPromise)state;
|
||||||
|
promise.core.TrySetResult(null);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
@@ -329,6 +361,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -351,6 +384,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
@@ -358,7 +392,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -376,6 +410,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilValueChangedUnityObjectPromise<T, U>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -453,6 +496,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,6 +518,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
@@ -481,7 +526,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -498,6 +543,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilValueChangedStandardObjectPromise<T, U>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -575,6 +629,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
#pragma warning disable CS0436
|
#pragma warning disable CS0436
|
||||||
|
|
||||||
|
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.CompilerServices;
|
using Cysharp.Threading.Tasks.CompilerServices;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -69,7 +73,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new UniTask<bool>(new IsCanceledSource(source), token);
|
return new UniTask<bool>(new IsCanceledSource(source), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
||||||
{
|
{
|
||||||
@@ -78,7 +82,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
||||||
@@ -118,7 +122,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
this.source.GetResult(this.token);
|
this.source.GetResult(this.token);
|
||||||
return CompletedTasks.AsyncUnit;
|
return CompletedTasks.AsyncUnit;
|
||||||
}
|
}
|
||||||
else if(this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
|
else if (this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
|
||||||
{
|
{
|
||||||
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
|
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
|
||||||
}
|
}
|
||||||
@@ -440,7 +444,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return self.AsUniTask();
|
return self.AsUniTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
||||||
{
|
{
|
||||||
@@ -449,7 +453,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -165,8 +165,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -184,8 +184,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -328,6 +328,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
short version;
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
@@ -340,6 +341,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource();
|
result = new AutoResetUniTaskCompletionSource();
|
||||||
}
|
}
|
||||||
|
result.version = result.core.Version;
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -383,19 +385,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult()
|
public bool TrySetResult()
|
||||||
{
|
{
|
||||||
return core.TrySetResult(AsyncUnit.Default);
|
return version == core.Version && core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return core.TrySetCanceled(cancellationToken);
|
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return core.TrySetException(exception);
|
return version == core.Version && core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
@@ -409,7 +411,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
@@ -451,6 +452,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
short version;
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
@@ -463,6 +465,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource<T>();
|
result = new AutoResetUniTaskCompletionSource<T>();
|
||||||
}
|
}
|
||||||
|
result.version = result.core.Version;
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -506,19 +509,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult(T result)
|
public bool TrySetResult(T result)
|
||||||
{
|
{
|
||||||
return core.TrySetResult(result);
|
return version == core.Version && core.TrySetResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return core.TrySetCanceled(cancellationToken);
|
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return core.TrySetException(exception);
|
return version == core.Version && core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
@@ -937,5 +940,5 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception);
|
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult(x.Result);
|
p.TrySetResult(x.Result);
|
||||||
@@ -58,7 +58,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception);
|
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult();
|
p.TrySetResult();
|
||||||
@@ -454,7 +454,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCacneled).
|
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCanceled).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, 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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,12 +24,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
|
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return AwaitForAllAssets(asyncOperation, progress: null, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
||||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -95,15 +100,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
AssetBundleRequest asyncOperation;
|
AssetBundleRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleRequestAllAssetsConfiguredSource()
|
AssetBundleRequestAllAssetsConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -118,6 +127,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleRequestAllAssetsConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -161,6 +182,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -188,8 +215,29 @@ namespace Cysharp.Threading.Tasks
|
|||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.allAssets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
||||||
|
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
||||||
@@ -39,15 +44,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
AsyncGPUReadbackRequest asyncOperation;
|
AsyncGPUReadbackRequest asyncOperation;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
||||||
|
|
||||||
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -61,6 +66,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncGPUReadbackRequestAwaiterConfiguredSource)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -131,6 +145,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
#if !UNITY_2023_1_OR_NEWER
|
#if !UNITY_2023_1_OR_NEWER
|
||||||
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
||||||
|
|
||||||
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
|
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
@@ -30,12 +29,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AsyncOperationAwaiter : ICriticalNotifyCompletion
|
public struct AsyncOperationAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -92,15 +96,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
AsyncOperation asyncOperation;
|
AsyncOperation asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AsyncOperationConfiguredSource()
|
AsyncOperationConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -115,6 +123,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AsyncOperationConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -154,6 +174,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -178,11 +204,33 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -200,12 +248,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ResourceRequestAwaiter : ICriticalNotifyCompletion
|
public struct ResourceRequestAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -266,15 +319,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
ResourceRequest asyncOperation;
|
ResourceRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
ResourceRequestConfiguredSource()
|
ResourceRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -289,6 +346,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (ResourceRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -332,6 +401,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -356,11 +431,33 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -379,12 +476,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleRequestAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleRequestAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -445,15 +547,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
AssetBundleRequest asyncOperation;
|
AssetBundleRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleRequestConfiguredSource()
|
AssetBundleRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -468,6 +574,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -511,6 +629,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -535,11 +659,33 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -559,12 +705,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleCreateRequestAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleCreateRequestAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -625,15 +776,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
AssetBundleCreateRequest asyncOperation;
|
AssetBundleCreateRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AssetBundle> core;
|
UniTaskCompletionSourceCore<AssetBundle> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleCreateRequestConfiguredSource()
|
AssetBundleCreateRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -648,6 +803,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleCreateRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -691,6 +858,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -715,11 +888,33 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.assetBundle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -739,7 +934,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
||||||
@@ -751,7 +951,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
return UniTask.FromResult(asyncOperation.webRequest);
|
return UniTask.FromResult(asyncOperation.webRequest);
|
||||||
}
|
}
|
||||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UnityWebRequestAsyncOperationAwaiter : ICriticalNotifyCompletion
|
public struct UnityWebRequestAsyncOperationAwaiter : ICriticalNotifyCompletion
|
||||||
@@ -820,15 +1020,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
UnityWebRequestAsyncOperation asyncOperation;
|
UnityWebRequestAsyncOperation asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
UnityWebRequestAsyncOperationConfiguredSource()
|
UnityWebRequestAsyncOperationConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -843,6 +1047,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (UnityWebRequestAsyncOperationConfiguredSource)state;
|
||||||
|
source.asyncOperation.webRequest.Abort();
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -886,6 +1103,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
asyncOperation.webRequest.Abort();
|
asyncOperation.webRequest.Abort();
|
||||||
@@ -918,11 +1141,37 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else if (asyncOperation.webRequest.IsError())
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||||
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
||||||
|
Func<(string typeName, string returnType, string returnField), bool> IsAsyncOperationBase = x => x.typeName == "AsyncOperation";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
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> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
||||||
@@ -43,18 +44,30 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# } #>
|
<# } #>
|
||||||
#region <#= t.typeName #>
|
#region <#= t.typeName #>
|
||||||
|
|
||||||
|
<# if (IsAsyncOperationBase(t)) { #>
|
||||||
|
#if !UNITY_2023_1_OR_NEWER
|
||||||
|
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
||||||
|
<# } #>
|
||||||
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
return new <#= t.typeName #>Awaiter(asyncOperation);
|
return new <#= t.typeName #>Awaiter(asyncOperation);
|
||||||
}
|
}
|
||||||
|
<# if (IsAsyncOperationBase(t)) { #>
|
||||||
|
#endif
|
||||||
|
<# } #>
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||||
@@ -70,7 +83,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# } else { #>
|
<# } else { #>
|
||||||
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
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);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
||||||
@@ -151,15 +164,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<#= t.typeName #> asyncOperation;
|
<#= t.typeName #> asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
<#= t.typeName #>ConfiguredSource()
|
<#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -174,6 +191,21 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (<#= t.typeName #>ConfiguredSource)state;
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
source.asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -223,6 +255,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
@@ -261,11 +299,44 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
else if (asyncOperation.webRequest.IsError())
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public static class UnityAwaitableExtensions
|
||||||
|
{
|
||||||
|
public static async UniTask AsUniTask(this UnityEngine.Awaitable awaitable)
|
||||||
|
{
|
||||||
|
await awaitable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTask<T> AsUniTask<T>(this UnityEngine.Awaitable<T> awaitable)
|
||||||
|
{
|
||||||
|
return await awaitable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c29533c9e4284dee914b71a6579ea274
|
||||||
|
timeCreated: 1698895807
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
|
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
|
||||||
"version": "2.3.3",
|
"version": "2.5.2",
|
||||||
"unity": "2018.4",
|
"unity": "2018.4",
|
||||||
"description": "Provides an efficient async/await integration to Unity.",
|
"description": "Provides an efficient async/await integration to Unity.",
|
||||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||||
|
|||||||
90
src/UniTask/Assets/Tests/AsyncOperationTest.cs
Normal file
90
src/UniTask/Assets/Tests/AsyncOperationTest.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class AsyncOperationTest
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ResourcesLoad_Completed() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var asyncOperation = Resources.LoadAsync<Texture2D>("sample_texture");
|
||||||
|
await asyncOperation.ToUniTask();
|
||||||
|
asyncOperation.isDone.Should().BeTrue();
|
||||||
|
asyncOperation.asset.GetType().Should().Be(typeof(Texture2D));
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ResourcesLoad_CancelOnPlayerLoop() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var task = Resources.LoadAsync<Texture>("sample_texture").ToUniTask(cancellationToken: cts.Token, cancelImmediately: false);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Pending);
|
||||||
|
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ResourcesLoad_CancelImmediately()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var task = Resources.LoadAsync<Texture>("sample_texture").ToUniTask(cancellationToken: cts.Token, cancelImmediately: true);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator UnityWebRequest_Completed() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var asyncOperation = UnityWebRequest.Get($"file://{filePath}").SendWebRequest();
|
||||||
|
await asyncOperation.ToUniTask();
|
||||||
|
|
||||||
|
asyncOperation.isDone.Should().BeTrue();
|
||||||
|
asyncOperation.webRequest.result.Should().Be(UnityWebRequest.Result.Success);
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator UnityWebRequest_CancelOnPlayerLoop() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var task = UnityWebRequest.Get($"file://{filePath}").SendWebRequest().ToUniTask(cancellationToken: cts.Token);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Pending);
|
||||||
|
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UnityWebRequest_CancelImmediately()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
cts.Cancel();
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var task = UnityWebRequest.Get($"file://{filePath}").SendWebRequest().ToUniTask(cancellationToken: cts.Token, cancelImmediately: true);
|
||||||
|
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
3
src/UniTask/Assets/Tests/AsyncOperationTest.cs.meta
Normal file
3
src/UniTask/Assets/Tests/AsyncOperationTest.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 295d574a16494d6aa4d02fcb32179e39
|
||||||
|
timeCreated: 1698887128
|
||||||
8
src/UniTask/Assets/Tests/Resources.meta
Normal file
8
src/UniTask/Assets/Tests/Resources.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8d82913edf6ac48aca30f66ae9ba42d6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
src/UniTask/Assets/Tests/Resources/sample_texture.png
Normal file
BIN
src/UniTask/Assets/Tests/Resources/sample_texture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
208
src/UniTask/Assets/Tests/Resources/sample_texture.png.meta
Normal file
208
src/UniTask/Assets/Tests/Resources/sample_texture.png.meta
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 535006a83baed4ebda99d24a909a2efe
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable:
|
||||||
|
- first:
|
||||||
|
213: -2664112245596591751
|
||||||
|
second: sample_texture_0
|
||||||
|
- first:
|
||||||
|
213: -4606777057269188692
|
||||||
|
second: sample_texture_1
|
||||||
|
- first:
|
||||||
|
213: 1950921086533113773
|
||||||
|
second: sample_texture_2
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 12
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 0
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
flipGreenChannel: 0
|
||||||
|
isReadable: 0
|
||||||
|
streamingMipmaps: 0
|
||||||
|
streamingMipmapsPriority: 0
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMipmapLimit: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 1
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 1
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 2
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 8
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
flipbookRows: 1
|
||||||
|
flipbookColumns: 1
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
ignorePngGamma: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
swizzle: 50462976
|
||||||
|
cookieLightType: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: WebGL
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Standalone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: iPhone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites:
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_0
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 76
|
||||||
|
width: 243
|
||||||
|
height: 251
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: 9796277170c270bd0800000000000000
|
||||||
|
internalID: -2664112245596591751
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_1
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 227
|
||||||
|
y: 0
|
||||||
|
width: 190
|
||||||
|
height: 231
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: ca7fc069ca07110c0800000000000000
|
||||||
|
internalID: -4606777057269188692
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_2
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 398
|
||||||
|
y: 87
|
||||||
|
width: 202
|
||||||
|
height: 188
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: da710ab4460131b10800000000000000
|
||||||
|
internalID: 1950921086533113773
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID:
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
nameFileIdTable: {}
|
||||||
|
mipmapLimitGroupName:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user