mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-17 04:30:13 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80704e489d | ||
|
|
3c0aa03643 | ||
|
|
37cd00d347 | ||
|
|
859c4d706f | ||
|
|
7289fe6e25 | ||
|
|
0c33977f5a | ||
|
|
4d4466e801 | ||
|
|
79330d7cdb | ||
|
|
680ce1098b | ||
|
|
2337d705ec | ||
|
|
d2880a818f | ||
|
|
86ea128bf4 | ||
|
|
a66f378622 | ||
|
|
265f88584b | ||
|
|
686394c861 | ||
|
|
8bad158ab4 | ||
|
|
5e59e7ec86 | ||
|
|
8bb0a48720 | ||
|
|
b4468b4eba | ||
|
|
0725bd1b30 | ||
|
|
ebd80243e0 | ||
|
|
f1ac469058 | ||
|
|
2e0b603d25 | ||
|
|
1d90a40f66 | ||
|
|
1bec3f507e | ||
|
|
1d5ecbb3ab | ||
|
|
e1a4aeb9da | ||
|
|
43f1bb4d85 | ||
|
|
8b7a0e9b15 |
31
.github/workflows/build-docs.yml
vendored
Normal file
31
.github/workflows/build-docs.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: build-docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- feature/docs
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-docfx:
|
||||||
|
if: "!(contains(github.event.head_commit.message, '[skip ci]') || contains(github.event.head_commit.message, '[ci skip]'))"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: Cysharp/DocfxTemplate
|
||||||
|
path: docs/_DocfxTemplate
|
||||||
|
- uses: Kirbyrawr/docfx-action@master
|
||||||
|
name: Docfx metadata
|
||||||
|
with:
|
||||||
|
args: metadata docs/docfx.json
|
||||||
|
- uses: Kirbyrawr/docfx-action@master
|
||||||
|
name: Docfx build
|
||||||
|
with:
|
||||||
|
args: build docs/docfx.json
|
||||||
|
- name: Publish to GitHub Pages
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: docs/_site
|
||||||
4
.github/workflows/build-release.yml
vendored
4
.github/workflows/build-release.yml
vendored
@@ -61,8 +61,8 @@ jobs:
|
|||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: UniTask.unitypackage.zip
|
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
path: ./src/UniTask/*.unitypackage
|
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
needs: [build-dotnet, build-unity]
|
needs: [build-dotnet, build-unity]
|
||||||
|
|||||||
46
.gitignore
vendored
46
.gitignore
vendored
@@ -159,3 +159,49 @@ src/UniTask/UniTask.Tests.Editor.csproj
|
|||||||
src/UniTask/UniTask.*.unitypackage
|
src/UniTask/UniTask.*.unitypackage
|
||||||
|
|
||||||
src/UniTask/UniTask.Linq.csproj
|
src/UniTask/UniTask.Linq.csproj
|
||||||
|
|
||||||
|
src/UniTask/DOTween.Modules.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Addressables.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Addressables.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Analytics.DataPrivacy.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Recorder.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Recorder.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.ResourceManager.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Rider.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.ScriptableBuildPipeline.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.ScriptableBuildPipeline.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.TextMeshPro.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.TextMeshPro.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Timeline.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Timeline.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.VisualStudio.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.VSCode.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEditor.CacheServer.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEditor.TestRunner.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEditor.UI.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.Advertisements.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.Monetization.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.TestRunner.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.UI.csproj
|
||||||
|
|||||||
73
README.md
73
README.md
@@ -6,7 +6,7 @@ Provides an efficient async/await integration to Unity.
|
|||||||
|
|
||||||
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
||||||
* All Unity AsyncOperations and Coroutine to awaitable
|
* All Unity AsyncOperations and Coroutine to awaitable
|
||||||
* PlayerLoop based task(`UniTask.Yield`, `UniTask.Delay`, `UniTask.DelayFrame`, etc...) that enable to replace all coroutine operation
|
* PlayerLoop based task(`UniTask.Yield`, `UniTask.Delay`, `UniTask.DelayFrame`, etc..) that enable to replace all coroutine operation
|
||||||
* MonoBehaviour Message Events and uGUI Events as awaitable/async-enumerable
|
* MonoBehaviour Message Events and uGUI Events as awaitable/async-enumerable
|
||||||
* Completely run on Unity's PlayerLoop so don't use thread and run on WebGL, wasm, etc.
|
* Completely run on Unity's PlayerLoop so don't use thread and run on WebGL, wasm, etc.
|
||||||
* Asynchronous LINQ, with Channel and AsyncReactiveProperty
|
* Asynchronous LINQ, with Channel and AsyncReactiveProperty
|
||||||
@@ -29,6 +29,7 @@ Provides an efficient async/await integration to Unity.
|
|||||||
- [Awaitable Events](#awaitable-events)
|
- [Awaitable Events](#awaitable-events)
|
||||||
- [Channel](#channel)
|
- [Channel](#channel)
|
||||||
- [For Unit Testing](#for-unit-testing)
|
- [For Unit Testing](#for-unit-testing)
|
||||||
|
- [Pooling Configuration](#pooling-configuration)
|
||||||
- [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)
|
||||||
@@ -52,21 +53,33 @@ async UniTask<string> DemoAsync()
|
|||||||
{
|
{
|
||||||
// You can await Unity's AsyncObject
|
// You can await Unity's AsyncObject
|
||||||
var asset = await Resources.LoadAsync<TextAsset>("foo");
|
var asset = await Resources.LoadAsync<TextAsset>("foo");
|
||||||
|
var txt = (await UnityWebRequest.Get("https://...").SendWebRequest()).downloadHandler.text;
|
||||||
|
await SceneManager.LoadSceneAsync("scene2");
|
||||||
|
|
||||||
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
||||||
var asset2 = await Resources.LoadAsync<TextAsset>("foo").WithCancellation(this.GetCancellationTokenOnDestroy());
|
var asset2 = await Resources.LoadAsync<TextAsset>("bar").WithCancellation(this.GetCancellationTokenOnDestroy());
|
||||||
|
|
||||||
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
||||||
await SceneManager.LoadSceneAsync("scene2").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
var asset3 = await Resources.LoadAsync<TextAsset>("baz").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
||||||
|
|
||||||
// await frame-based operation like coroutine
|
// await frame-based operation like coroutine
|
||||||
await UniTask.DelayFrame(100);
|
await UniTask.DelayFrame(100);
|
||||||
|
|
||||||
// replacement of WaitForSeconds/WaitForSecondsRealtime
|
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(10), ignoreTimeScale: false);
|
await UniTask.Delay(TimeSpan.FromSeconds(10), ignoreTimeScale: false);
|
||||||
|
|
||||||
// replacement of WaitForEndOfFrame(or other timing like yield return null, yield return WaitForFixedUpdate)
|
// yield any playerloop timing(PreUpdate, Update, LateUpdate, etc...)
|
||||||
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
await UniTask.Yield(PlayerLoopTiming.PreLateUpdate);
|
||||||
|
|
||||||
|
// replacement of yield return null
|
||||||
|
await UniTask.Yield();
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
|
||||||
|
// replacement of WaitForEndOfFrame(same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate))
|
||||||
|
await UniTask.WaitForEndOfFrame();
|
||||||
|
|
||||||
|
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
||||||
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
|
||||||
// replacement of yield return WaitUntil
|
// replacement of yield return WaitUntil
|
||||||
await UniTask.WaitUntil(() => isActive == false);
|
await UniTask.WaitUntil(() => isActive == false);
|
||||||
@@ -80,9 +93,14 @@ async UniTask<string> DemoAsync()
|
|||||||
// You can await standard task
|
// You can await standard task
|
||||||
await Task.Run(() => 100);
|
await Task.Run(() => 100);
|
||||||
|
|
||||||
// Multithreading, run on ThreadPool under this code(use SwitchToMainThread, same as `ObserveOnMainThreadDispatcher`)
|
// Multithreading, run on ThreadPool under this code
|
||||||
await UniTask.SwitchToThreadPool();
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
/* work on ThreadPool */
|
||||||
|
|
||||||
|
// return to MainThread(same as `ObserveOnMainThread` in UniRx)
|
||||||
|
await UniTask.SwitchToMainThread();
|
||||||
|
|
||||||
// get async webrequest
|
// get async webrequest
|
||||||
async UniTask<string> GetTextAsync(UnityWebRequest req)
|
async UniTask<string> GetTextAsync(UnityWebRequest req)
|
||||||
{
|
{
|
||||||
@@ -126,6 +144,8 @@ UniTask provides three pattern of extension methods.
|
|||||||
|
|
||||||
`WithCancellation` is a simple version of `ToUniTask`, both returns `UniTask`. Details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
`WithCancellation` is a simple version of `ToUniTask`, both returns `UniTask`. Details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
||||||
|
|
||||||
|
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
||||||
|
|
||||||
The type of `UniTask` can use utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
The type of `UniTask` can use utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
@@ -320,9 +340,19 @@ public enum PlayerLoopTiming
|
|||||||
|
|
||||||
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
||||||
|
|
||||||
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update is called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). If change timing to `PlayerLoopTiming.LastUpdate`, called after these Unity's update methods.
|
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
||||||
|
|
||||||
`PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
`yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`.
|
||||||
|
|
||||||
|
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
|
||||||
|
|
||||||
|
AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
|
||||||
|
|
||||||
|
In UniTask, await directly and `WithCancellation` use native timing, `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, causes different order of Start and continuation after await. so recommend not to use `LoadSceneAsync.ToUniTask`.
|
||||||
|
|
||||||
|
In stacktrace, you can check where is running in playerloop.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
In default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
In default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
||||||
|
|
||||||
@@ -413,7 +443,7 @@ For debug use, enable tracking and capture stacktrace is useful but it it declin
|
|||||||
|
|
||||||
External Assets
|
External Assets
|
||||||
---
|
---
|
||||||
In default, UniTask supports DOTween and Addressable(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
In default, UniTask supports DOTween and Addressables(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
||||||
|
|
||||||
For DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
For DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||||
|
|
||||||
@@ -649,6 +679,19 @@ public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
|||||||
|
|
||||||
UniTask itself's unit test is written by Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to check on CI and IL2CPP working.
|
UniTask itself's unit test is written by Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to check on CI and IL2CPP working.
|
||||||
|
|
||||||
|
Pooling Configuration
|
||||||
|
---
|
||||||
|
UniTask is aggressively caching async promise object to achive zero allocation. In default, cache all promises but you can configure `TaskPool.SetMaxPoolSize` to your value, the value indicates cache size per type. `TaskPool.GetCacheSizeInfo` returns current cached object in pool.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||||
|
{
|
||||||
|
Debug.Log(type + ":" + size);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build. And also currently due to IL2CPP limitation, in IL2CPP build, UniTask do boxing AsyncStateMachine when needed so sometimes exists `one` allocation.
|
||||||
|
|
||||||
API References
|
API References
|
||||||
---
|
---
|
||||||
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
||||||
@@ -706,6 +749,16 @@ public class ZeroAllocAsyncAwaitInDotNetCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UniTask does not return to original SynchronizationContext but you can use helper `ReturnToCurrentSynchronizationContext`.
|
||||||
|
public ValueTask TestAsync()
|
||||||
|
{
|
||||||
|
await using (UniTask.ReturnToCurrentSynchronizationContext())
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
// do anything..
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
||||||
|
|||||||
10
docs/.gitignore
vendored
Normal file
10
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
###############
|
||||||
|
# folder #
|
||||||
|
###############
|
||||||
|
/**/DROP/
|
||||||
|
/**/TEMP/
|
||||||
|
/**/packages/
|
||||||
|
/**/bin/
|
||||||
|
/**/obj/
|
||||||
|
_site
|
||||||
|
_DocfxTemplate
|
||||||
5
docs/api/.gitignore
vendored
Normal file
5
docs/api/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
###############
|
||||||
|
# temp file #
|
||||||
|
###############
|
||||||
|
*.yml
|
||||||
|
.manifest
|
||||||
70
docs/docfx.json
Normal file
70
docs/docfx.json
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"metadata": [
|
||||||
|
{
|
||||||
|
"src": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"UniTask/Assets/Plugins/UniTask/Runtime/**/*.cs"
|
||||||
|
],
|
||||||
|
"src": "../src"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dest": "api",
|
||||||
|
"disableGitFeatures": false,
|
||||||
|
"disableDefaultFilter": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"build": {
|
||||||
|
"globalMetadata": {
|
||||||
|
"_disableContribution": true,
|
||||||
|
"_appTitle": "UniTask"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"api/**.yml",
|
||||||
|
"api/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"articles/**.md",
|
||||||
|
"articles/**/toc.yml",
|
||||||
|
"toc.yml",
|
||||||
|
"*.md"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resource": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"images/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"overwrite": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"apidoc/**.md"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"obj/**",
|
||||||
|
"_site/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dest": "_site",
|
||||||
|
|
||||||
|
"globalMetadataFiles": [],
|
||||||
|
"fileMetadataFiles": [],
|
||||||
|
"template": [
|
||||||
|
"_DocfxTemplate/templates/default-v2.5.2",
|
||||||
|
"_DocfxTemplate/templates/cysharp"
|
||||||
|
],
|
||||||
|
"postProcessors": [],
|
||||||
|
"markdownEngineName": "markdig",
|
||||||
|
"noLangKeyword": false,
|
||||||
|
"keepFileLink": false,
|
||||||
|
"cleanupCacheHistory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
8
docs/index.md
Normal file
8
docs/index.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Home
|
||||||
|
---
|
||||||
|
# UniTask
|
||||||
|
|
||||||
|
Provides an efficient async/await integration to Unity.
|
||||||
|
|
||||||
|
https://github.com/Cysharp/UniTask
|
||||||
11
docs/toc.yml
Normal file
11
docs/toc.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
- name: API Documentation
|
||||||
|
href: api/
|
||||||
|
homepage: api/Cysharp.Threading.Tasks.html
|
||||||
|
|
||||||
|
- name: Repository
|
||||||
|
href: https://github.com/Cysharp/UniTask
|
||||||
|
homepage: https://github.com/Cysharp/UniTask
|
||||||
|
|
||||||
|
- name: Releases
|
||||||
|
href: https://github.com/Cysharp/UniTask/releases
|
||||||
|
homepage: https://github.com/Cysharp/UniTask/releases
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading.Tasks.Sources;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
@@ -8,12 +10,20 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public static ValueTask AsValueTask(this in UniTask task)
|
public static ValueTask AsValueTask(this in UniTask task)
|
||||||
{
|
{
|
||||||
|
#if NETSTANDARD2_0
|
||||||
|
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
||||||
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
||||||
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> AsUniTask<T>(this ValueTask<T> task, bool useCurrentSynchronizationContext = true)
|
public static UniTask<T> AsUniTask<T>(this ValueTask<T> task, bool useCurrentSynchronizationContext = true)
|
||||||
@@ -26,5 +36,63 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NETSTANDARD2_0
|
||||||
|
|
||||||
|
class UniTaskValueTaskSource : IValueTaskSource
|
||||||
|
{
|
||||||
|
readonly UniTask task;
|
||||||
|
readonly UniTask.Awaiter awaiter;
|
||||||
|
|
||||||
|
public UniTaskValueTaskSource(UniTask task)
|
||||||
|
{
|
||||||
|
this.task = task;
|
||||||
|
this.awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTaskSourceStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return (ValueTaskSourceStatus)task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UniTaskValueTaskSource<T> : IValueTaskSource<T>
|
||||||
|
{
|
||||||
|
readonly UniTask<T> task;
|
||||||
|
readonly UniTask<T>.Awaiter awaiter;
|
||||||
|
|
||||||
|
public UniTaskValueTaskSource(UniTask<T> task)
|
||||||
|
{
|
||||||
|
this.task = task;
|
||||||
|
this.awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
return awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTaskSourceStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return (ValueTaskSourceStatus)task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.1;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>netcoreapp3.1;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>
|
||||||
|
|||||||
@@ -277,7 +277,11 @@ namespace NetCoreSandbox
|
|||||||
#endif
|
#endif
|
||||||
// await new AllocationCheck().ViaUniTaskVoid();
|
// await new AllocationCheck().ViaUniTaskVoid();
|
||||||
|
|
||||||
// AsyncTest().Forget();
|
// AsyncTest().Forge
|
||||||
|
|
||||||
|
Console.WriteLine("A?");
|
||||||
|
var a = await new ZeroAllocAsyncAwaitInDotNetCore().NanikaAsync(1, 2);
|
||||||
|
Console.WriteLine("RET:" + a);
|
||||||
await WhereSelect();
|
await WhereSelect();
|
||||||
|
|
||||||
SynchronizationContext.SetSynchronizationContext(new MySyncContext());
|
SynchronizationContext.SetSynchronizationContext(new MySyncContext());
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskMethodBuilder
|
public struct AsyncUniTaskMethodBuilder
|
||||||
{
|
{
|
||||||
internal IStateMachineRunnerPromise runnerPromise;
|
IStateMachineRunnerPromise runnerPromise;
|
||||||
Exception ex;
|
Exception ex;
|
||||||
|
|
||||||
// 1. Static Create method.
|
// 1. Static Create method.
|
||||||
@@ -80,7 +80,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -96,7 +96,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -138,7 +138,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskMethodBuilder<T>
|
public struct AsyncUniTaskMethodBuilder<T>
|
||||||
{
|
{
|
||||||
internal IStateMachineRunnerPromise<T> runnerPromise;
|
IStateMachineRunnerPromise<T> runnerPromise;
|
||||||
Exception ex;
|
Exception ex;
|
||||||
T result;
|
T result;
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
@@ -227,7 +227,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runnerPromise == null)
|
if (runnerPromise == null)
|
||||||
{
|
{
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[StructLayout(LayoutKind.Auto)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct AsyncUniTaskVoidMethodBuilder
|
public struct AsyncUniTaskVoidMethodBuilder
|
||||||
{
|
{
|
||||||
internal IStateMachineRunner runner;
|
IStateMachineRunner runner;
|
||||||
|
|
||||||
// 1. Static Create method.
|
// 1. Static Create method.
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
@@ -70,7 +70,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runner == null)
|
if (runner == null)
|
||||||
{
|
{
|
||||||
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.OnCompleted(runner.MoveNext);
|
awaiter.OnCompleted(runner.MoveNext);
|
||||||
@@ -86,7 +86,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
if (runner == null)
|
if (runner == null)
|
||||||
{
|
{
|
||||||
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
|
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaiter.UnsafeOnCompleted(runner.MoveNext);
|
awaiter.UnsafeOnCompleted(runner.MoveNext);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -29,12 +30,26 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
void SetException(Exception exception);
|
void SetException(Exception exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static class StateMachineUtility
|
||||||
|
{
|
||||||
|
public static int GetState(IAsyncStateMachine stateMachine)
|
||||||
|
{
|
||||||
|
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
||||||
|
.First(x => x.Name.EndsWith("__state"));
|
||||||
|
return (int)info.GetValue(stateMachine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
|
internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
|
||||||
where TStateMachine : IAsyncStateMachine
|
where TStateMachine : IAsyncStateMachine
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -43,7 +58,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskVoidMethodBuilder builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -51,7 +66,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runner = result; // set runner before copied.
|
runnerFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +117,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -113,7 +132,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -121,7 +140,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runnerPromise = result; // set runner before copied.
|
runnerPromiseFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +232,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
{
|
{
|
||||||
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
||||||
|
|
||||||
|
#if ENABLE_IL2CPP
|
||||||
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
@@ -224,7 +247,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref AsyncUniTaskMethodBuilder<T> builder, ref TStateMachine stateMachine)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
|
||||||
{
|
{
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
@@ -232,10 +255,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
}
|
}
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
builder.runnerPromise = result; // set runner before copied.
|
runnerPromiseFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
|
|
||||||
|
// UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
||||||
|
|
||||||
static AsyncUniTask()
|
static AsyncUniTask()
|
||||||
@@ -255,6 +281,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void Run()
|
void Run()
|
||||||
{
|
{
|
||||||
|
// UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
|
||||||
stateMachine.MoveNext();
|
stateMachine.MoveNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public static class EnumeratorAsyncExtensions
|
public static class EnumeratorAsyncExtensions
|
||||||
{
|
{
|
||||||
public static UniTask.Awaiter GetAwaiter(this IEnumerator enumerator)
|
public static UniTask.Awaiter GetAwaiter<T>(this T enumerator)
|
||||||
|
where T : IEnumerator
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(enumerator, nameof(enumerator));
|
var e = (IEnumerator)enumerator;
|
||||||
return new UniTask(EnumeratorPromise.Create(enumerator, PlayerLoopTiming.Update, CancellationToken.None, out var token), token).GetAwaiter();
|
Error.ThrowArgumentNullException(e, nameof(enumerator));
|
||||||
|
return new UniTask(EnumeratorPromise.Create(e, PlayerLoopTiming.Update, CancellationToken.None, out var token), token).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WithCancellation(this IEnumerator enumerator, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this IEnumerator enumerator, CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (handle.IsDone) return UniTask.CompletedTask;
|
if (handle.IsDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationHandleWithCancellationSource.Create(handle, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -77,6 +77,132 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle> continuationAction;
|
||||||
|
AsyncOperationHandle handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperationHandle handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||||
@@ -210,7 +336,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<T>(AsyncOperationHandleWithCancellationSource<T>.Create(handle, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -265,6 +391,137 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource<T>>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource<T>> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource<T> NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource<T>), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
||||||
|
AsyncOperationHandle<T> handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle<T> _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(handle.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||||
|
|||||||
@@ -93,28 +93,30 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly Action<object> CancellationCallbackDelegate = CancellationCallback;
|
|
||||||
static readonly TweenCallback EmptyTweenCallback = () => { };
|
static readonly TweenCallback EmptyTweenCallback = () => { };
|
||||||
|
|
||||||
readonly TweenCallback onKillDelegate;
|
readonly TweenCallback onKillDelegate;
|
||||||
|
readonly TweenCallback onUpdateDelegate;
|
||||||
|
|
||||||
Tween tween;
|
Tween tween;
|
||||||
TweenCancelBehaviour cancelBehaviour;
|
TweenCancelBehaviour cancelBehaviour;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
TweenCallback originalUpdateAction;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
TweenConfiguredSource()
|
TweenConfiguredSource()
|
||||||
{
|
{
|
||||||
onKillDelegate = OnKill;
|
onKillDelegate = OnKill;
|
||||||
|
onUpdateDelegate = OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
DoCancelBeforeCreate(tween, cancelBehaviour);
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,27 +129,25 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.cancelBehaviour = cancelBehaviour;
|
result.cancelBehaviour = cancelBehaviour;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
result.originalUpdateAction = tween.onUpdate;
|
||||||
|
result.canceled = false;
|
||||||
|
|
||||||
result.RegisterEvent();
|
if (result.originalUpdateAction == result.onUpdateDelegate)
|
||||||
|
{
|
||||||
|
result.originalUpdateAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
tween.onUpdate = result.onUpdateDelegate;
|
||||||
|
tween.onKill = result.onKillDelegate;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterEvent()
|
|
||||||
{
|
|
||||||
if (cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
tween.OnKill(onKillDelegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnKill()
|
void OnKill()
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
if (canceled)
|
if (canceled)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
@@ -158,44 +158,84 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
void OnUpdate()
|
||||||
{
|
{
|
||||||
var self = (TweenConfiguredSource)state;
|
originalUpdateAction?.Invoke();
|
||||||
|
|
||||||
switch (self.cancelBehaviour)
|
if (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this.cancelBehaviour)
|
||||||
{
|
{
|
||||||
case TweenCancelBehaviour.Kill:
|
case TweenCancelBehaviour.Kill:
|
||||||
default:
|
default:
|
||||||
self.tween.Kill(false);
|
this.tween.Kill(false);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.KillAndCancelAwait:
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
self.canceled = true;
|
this.canceled = true;
|
||||||
self.tween.Kill(false);
|
this.tween.Kill(false);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallback:
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
self.tween.Kill(true);
|
this.tween.Kill(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
self.canceled = true;
|
this.canceled = true;
|
||||||
self.tween.Kill(true);
|
this.tween.Kill(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.Complete:
|
case TweenCancelBehaviour.Complete:
|
||||||
self.tween.Complete(false);
|
this.tween.Complete(false);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
self.canceled = true;
|
this.canceled = true;
|
||||||
self.tween.Complete(false);
|
this.tween.Complete(false);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
||||||
self.tween.Complete(true);
|
this.tween.Complete(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
||||||
self.canceled = true;
|
this.canceled = true;
|
||||||
self.tween.Complete(true);
|
this.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
this.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||||
|
this.core.TrySetCanceled(this.cancellationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (tweenCancelBehaviour)
|
||||||
|
{
|
||||||
|
case TweenCancelBehaviour.Kill:
|
||||||
|
default:
|
||||||
|
tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
|
tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
|
tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
|
tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.Complete:
|
||||||
|
tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
|
tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
||||||
|
tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
||||||
|
tween.Complete(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
self.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Caceled(instance is returned to pool.)
|
|
||||||
self.core.TrySetCanceled(self.cancellationToken);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +252,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
return core.GetStatus(token);
|
return core.GetStatus(token);
|
||||||
@@ -232,8 +271,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
tween.onUpdate = originalUpdateAction;
|
||||||
|
tween.onKill = null;
|
||||||
tween = default;
|
tween = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
originalUpdateAction = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
// similar as IValueTaskSource
|
// similar as IValueTaskSource
|
||||||
public interface IUniTaskSource
|
public interface IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
: System.Threading.Tasks.Sources.IValueTaskSource
|
: System.Threading.Tasks.Sources.IValueTaskSource
|
||||||
#pragma warning disable CS0108
|
#pragma warning disable CS0108
|
||||||
#endif
|
#endif
|
||||||
@@ -30,7 +30,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
#pragma warning restore CS0108
|
#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 +53,13 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface IUniTaskSource<out T> : IUniTaskSource
|
public interface IUniTaskSource<out T> : IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
, 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
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
|
|
||||||
new public UniTaskStatus GetStatus(short token)
|
new public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(Application.dataPath, "");
|
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(PlayerLoopHelper.ApplicationDataPath, "");
|
||||||
var withAssetsPath = "Assets/" + fname;
|
var withAssetsPath = "Assets/" + fname;
|
||||||
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
|
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
{
|
{
|
||||||
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// UnityEngine.Debug.Log("Called ToArray");
|
||||||
|
|
||||||
var pool = ArrayPool<TSource>.Shared;
|
var pool = ArrayPool<TSource>.Shared;
|
||||||
var array = pool.Rent(16);
|
var array = pool.Rent(16);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
@@ -22,16 +23,34 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (dueTimeFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (dueTimeFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
if (periodFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
||||||
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
|
if (intervalFrameCount < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
||||||
|
}
|
||||||
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +83,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
bool dueTimePhase;
|
bool dueTimePhase;
|
||||||
bool completed;
|
bool completed;
|
||||||
@@ -80,6 +100,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
if (this.period <= 0) this.period = 1;
|
if (this.period <= 0) this.period = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.initialFrame = Time.frameCount;
|
||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
@@ -119,9 +140,19 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
|
if (elapsed == 0)
|
||||||
|
{
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
||||||
|
|
||||||
if (elapsed >= dueTime)
|
if (elapsed >= dueTime)
|
||||||
{
|
{
|
||||||
dueTimePhase = false;
|
dueTimePhase = false;
|
||||||
@@ -137,6 +168,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
|
||||||
|
|
||||||
if (elapsed >= period)
|
if (elapsed >= period)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(true);
|
completionSource.TrySetResult(true);
|
||||||
@@ -172,6 +205,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
int currentFrame;
|
int currentFrame;
|
||||||
bool dueTimePhase;
|
bool dueTimePhase;
|
||||||
bool completed;
|
bool completed;
|
||||||
@@ -185,6 +219,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
if (periodFrameCount <= 0) periodFrameCount = 1;
|
if (periodFrameCount <= 0) periodFrameCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.initialFrame = Time.frameCount;
|
||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
@@ -228,11 +263,30 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
if (currentFrame++ >= dueTimeFrameCount)
|
if (currentFrame == 0)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount == 0)
|
||||||
|
{
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrame >= dueTimeFrameCount)
|
||||||
{
|
{
|
||||||
dueTimePhase = false;
|
dueTimePhase = false;
|
||||||
completionSource.TrySetResult(true);
|
completionSource.TrySetResult(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,8 +92,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
||||||
public static int MainThreadId => mainThreadId;
|
public static int MainThreadId => mainThreadId;
|
||||||
|
internal static string ApplicationDataPath => applicationDataPath;
|
||||||
|
|
||||||
static int mainThreadId;
|
static int mainThreadId;
|
||||||
|
static string applicationDataPath;
|
||||||
static SynchronizationContext unitySynchronizationContetext;
|
static SynchronizationContext unitySynchronizationContetext;
|
||||||
static ContinuationQueue[] yielders;
|
static ContinuationQueue[] yielders;
|
||||||
static PlayerLoopRunner[] runners;
|
static PlayerLoopRunner[] runners;
|
||||||
@@ -177,6 +179,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
// capture default(unity) sync-context.
|
// capture default(unity) sync-context.
|
||||||
unitySynchronizationContetext = SynchronizationContext.Current;
|
unitySynchronizationContetext = SynchronizationContext.Current;
|
||||||
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
applicationDataPath = Application.dataPath;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
|
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
|
||||||
// When domain reload is disabled, re-initialization is required when entering play mode;
|
// When domain reload is disabled, re-initialization is required when entering play mode;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
@@ -21,6 +20,46 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask NextFrame(PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate).
|
||||||
|
/// </summary>
|
||||||
|
public static YieldAwaitable WaitForEndOfFrame()
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken).
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate).
|
||||||
|
/// </summary>
|
||||||
|
public static YieldAwaitable WaitForFixedUpdate()
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken).
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (delayFrameCount < 0)
|
if (delayFrameCount < 0)
|
||||||
@@ -152,27 +191,25 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayFramePromise> pool;
|
static TaskPool<NextFramePromise> pool;
|
||||||
public DelayFramePromise NextNode { get; set; }
|
public NextFramePromise NextNode { get; set; }
|
||||||
|
|
||||||
static DelayFramePromise()
|
static NextFramePromise()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(NextFramePromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int delayFrameCount;
|
int frameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
int currentFrameCount;
|
NextFramePromise()
|
||||||
UniTaskCompletionSourceCore<object> core;
|
|
||||||
|
|
||||||
DelayFramePromise()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -181,10 +218,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
result = new DelayFramePromise();
|
result = new NextFramePromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.delayFrameCount = delayFrameCount;
|
result.frameCount = Time.frameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
@@ -230,13 +267,133 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentFrameCount == delayFrameCount)
|
if (frameCount == Time.frameCount)
|
||||||
{
|
{
|
||||||
core.TrySetResult(null);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~NextFramePromise()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
||||||
|
{
|
||||||
|
static TaskPool<DelayFramePromise> pool;
|
||||||
|
public DelayFramePromise NextNode { get; set; }
|
||||||
|
|
||||||
|
static DelayFramePromise()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
|
int delayFrameCount;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int currentFrameCount;
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
DelayFramePromise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new DelayFramePromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.delayFrameCount = delayFrameCount;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFrameCount == 0)
|
||||||
|
{
|
||||||
|
if (delayFrameCount == 0) // same as Yield
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrameCount >= delayFrameCount)
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrameCount++;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +426,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
float delayFrameTimeSpan;
|
float delayFrameTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
@@ -294,6 +452,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.elapsed = 0.0f;
|
result.elapsed = 0.0f;
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
@@ -338,6 +497,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elapsed == 0.0f)
|
||||||
|
{
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elapsed += Time.deltaTime;
|
elapsed += Time.deltaTime;
|
||||||
if (elapsed >= delayFrameTimeSpan)
|
if (elapsed >= delayFrameTimeSpan)
|
||||||
{
|
{
|
||||||
@@ -379,6 +546,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
float delayFrameTimeSpan;
|
float delayFrameTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
|
int initialFrame;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
@@ -401,6 +569,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
result.elapsed = 0.0f;
|
result.elapsed = 0.0f;
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
|
result.initialFrame = Time.frameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
@@ -446,6 +615,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elapsed == 0.0f)
|
||||||
|
{
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elapsed += Time.unscaledDeltaTime;
|
elapsed += Time.unscaledDeltaTime;
|
||||||
if (elapsed >= delayFrameTimeSpan)
|
if (elapsed >= delayFrameTimeSpan)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
|
|
||||||
task = f();
|
task = f();
|
||||||
awaiter = f().GetAwaiter();
|
awaiter = task.GetAwaiter();
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
|
|
||||||
task = f();
|
task = f();
|
||||||
awaiter = f().GetAwaiter();
|
awaiter = task.GetAwaiter();
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (!dontPostWhenSameContext) return false;
|
||||||
|
|
||||||
var current = SynchronizationContext.Current;
|
var current = SynchronizationContext.Current;
|
||||||
if (current == synchronizationContext)
|
if (current == synchronizationContext)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,7 +78,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NETSTANDARD2_0
|
||||||
|
return self.AsValueTask();
|
||||||
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -439,7 +443,11 @@ 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
|
||||||
|
return self.AsValueTask();
|
||||||
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -621,9 +621,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
{
|
{
|
||||||
// throw exception on iterator (main)thread.
|
exception.Throw();
|
||||||
// unfortunately unity test-runner can not handle throw exception on hand-write IEnumerator.MoveNext.
|
return false;
|
||||||
UnityEngine.Debug.LogException(exception.SourceException);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !completed;
|
return !completed;
|
||||||
@@ -692,9 +691,8 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
{
|
{
|
||||||
// throw exception on iterator (main)thread.
|
exception.Throw();
|
||||||
// unfortunately unity test-runner can not handle throw exception on hand-write IEnumerator.MoveNext.
|
return false;
|
||||||
UnityEngine.Debug.LogException(exception.SourceException);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !completed;
|
return !completed;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -75,7 +75,127 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
sealed class AsyncOperationWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationWithCancellationSource> pool;
|
||||||
|
public AsyncOperationWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AsyncOperation asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationConfiguredSource> pool;
|
static TaskPool<AsyncOperationConfiguredSource> pool;
|
||||||
public AsyncOperationConfiguredSource NextNode { get; set; }
|
public AsyncOperationConfiguredSource NextNode { get; set; }
|
||||||
@@ -124,7 +244,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -133,6 +252,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
return core.GetStatus(token);
|
return core.GetStatus(token);
|
||||||
@@ -203,7 +323,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(ResourceRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -257,7 +377,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
sealed class ResourceRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<ResourceRequestWithCancellationSource> pool;
|
||||||
|
public ResourceRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(ResourceRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
ResourceRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new ResourceRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResourceRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<ResourceRequestConfiguredSource> pool;
|
static TaskPool<ResourceRequestConfiguredSource> pool;
|
||||||
public ResourceRequestConfiguredSource NextNode { get; set; }
|
public ResourceRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -306,7 +550,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -390,7 +633,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(AssetBundleRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -444,7 +687,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
sealed class AssetBundleRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AssetBundleRequestWithCancellationSource> pool;
|
||||||
|
public AssetBundleRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AssetBundleRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AssetBundleRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AssetBundleRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
||||||
public AssetBundleRequestConfiguredSource NextNode { get; set; }
|
public AssetBundleRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -545,11 +912,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +943,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<AssetBundle>(AssetBundleCreateRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -630,7 +997,131 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
sealed class AssetBundleCreateRequestWithCancellationSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AssetBundleCreateRequestWithCancellationSource> pool;
|
||||||
|
public AssetBundleCreateRequestWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AssetBundleCreateRequestWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AssetBundleCreateRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AssetBundle> core;
|
||||||
|
|
||||||
|
AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<AssetBundle>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AssetBundleCreateRequestWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.assetBundle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBundle GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AssetBundleCreateRequestWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
||||||
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
|
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
|
||||||
@@ -731,11 +1222,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,7 +1254,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.webRequest);
|
||||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, cancellationToken, out var token), token);
|
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -817,7 +1308,132 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
sealed class UnityWebRequestAsyncOperationWithCancellationSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<UnityWebRequestAsyncOperationWithCancellationSource> pool;
|
||||||
|
public UnityWebRequestAsyncOperationWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(UnityWebRequestAsyncOperationWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
UnityWebRequestAsyncOperation asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
||||||
|
|
||||||
|
UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityWebRequest>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new UnityWebRequestAsyncOperationWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityWebRequest GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~UnityWebRequestAsyncOperationWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
||||||
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
|
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
|
||||||
@@ -866,7 +1482,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -920,11 +1535,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# if(t.returnType == "UnityWebRequest") { #>
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST
|
||||||
<# } #>
|
<# } #>
|
||||||
#region <#= t.typeName #>
|
#region <#= t.typeName #>
|
||||||
|
|
||||||
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
||||||
{
|
{
|
||||||
@@ -45,18 +45,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new <#= t.typeName #>Awaiter(asyncOperation);
|
return new <#= t.typeName #>Awaiter(asyncOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, PlayerLoopTiming.Update, null, CancellationToken.None, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>WithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ConfigureAwait(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellation = default(CancellationToken))
|
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellation, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
||||||
@@ -106,14 +106,153 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public void UnsafeOnCompleted(Action continuation)
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
{
|
{
|
||||||
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||||
continuationAction = continuation.AsFuncOfT<AsyncOperation>(); // allocate delegate.
|
continuationAction = PooledDelegate<AsyncOperation>.Create(continuation);
|
||||||
asyncOperation.completed += continuationAction;
|
asyncOperation.completed += continuationAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, IPromisePoolItem
|
sealed class <#= t.typeName #>WithCancellationSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>WithCancellationSource>
|
||||||
{
|
{
|
||||||
static readonly PromisePool<<#= t.typeName #>ConfiguredSource> pool = new PromisePool<<#= t.typeName #>ConfiguredSource>();
|
static TaskPool<<#= t.typeName #>WithCancellationSource> pool;
|
||||||
|
public <#= t.typeName #>WithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static <#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>WithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
<#= t.typeName #> asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
||||||
|
|
||||||
|
<#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new <#= t.typeName #>WithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <#= t.returnType #> GetResult(short token)
|
||||||
|
{
|
||||||
|
<# if (!IsVoid(t)) { #>
|
||||||
|
return core.GetResult(token);
|
||||||
|
<# } else { #>
|
||||||
|
core.GetResult(token);
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
|
|
||||||
|
<# if (!IsVoid(t)) { #>
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~<#= t.typeName #>WithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
||||||
|
{
|
||||||
|
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
||||||
|
public <#= t.typeName #>ConfiguredSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static <#= t.typeName #>ConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>ConfiguredSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
<#= t.typeName #> asyncOperation;
|
<#= t.typeName #> asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
@@ -133,7 +272,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = pool.TryRent() ?? new <#= t.typeName #>ConfiguredSource();
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new <#= t.typeName #>ConfiguredSource();
|
||||||
|
}
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
@@ -151,8 +293,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
|
|
||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
@@ -161,7 +301,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
pool.TryReturn(this);
|
TryReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +331,9 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -209,24 +352,26 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
~<#= t.typeName #>ConfiguredSource()
|
~<#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
if (pool.TryReturn(this))
|
if (TryReturn())
|
||||||
{
|
{
|
||||||
GC.ReRegisterForFinalize(this);
|
GC.ReRegisterForFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# endregion
|
#endregion
|
||||||
<# if(t.returnType == "UnityWebRequest") { #>
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
#endif
|
#endif
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"version": "2.0.13",
|
"version": "2.0.15",
|
||||||
"unity": "2018.4",
|
"unity": "2018.4",
|
||||||
"description": "Provides an efficient async/await integration to Unity.",
|
"description": "Provides an efficient async/await integration to Unity.",
|
||||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||||
|
|||||||
@@ -21,13 +21,15 @@ public class ExceptionExamples : MonoBehaviour
|
|||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
UnityEngine.Debug.Log("ExceptionScene, LoopType:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
|
||||||
ThrowFromAsyncVoid();
|
//TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||||
_ = ThrowFromTask();
|
|
||||||
_ = ThrowFromUniTask();
|
|
||||||
|
|
||||||
ThrowFromNonAsync();
|
//ThrowFromAsyncVoid();
|
||||||
|
//_ = ThrowFromTask();
|
||||||
|
//_ = ThrowFromUniTask();
|
||||||
|
|
||||||
|
//ThrowFromNonAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ using UnityEngine;
|
|||||||
using UnityEngine.LowLevel;
|
using UnityEngine.LowLevel;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
|
||||||
// using DG.Tweening;
|
// using DG.Tweening;
|
||||||
|
|
||||||
@@ -264,11 +266,14 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//var r = UniAsync("https://bing.com/", cts.Token);
|
//var r = UniAsync("https://bing.com/", cts.Token);
|
||||||
//cts.Cancel();
|
//cts.Cancel();
|
||||||
//await r;
|
//await r;
|
||||||
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
Debug.Log("UNIASYNC1 ");
|
|
||||||
|
|
||||||
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
|
||||||
Debug.Log("UNIASYNC2");
|
// var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
||||||
|
// foo.downloadHandler.text;
|
||||||
|
//
|
||||||
|
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None);
|
||||||
|
Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -301,10 +306,210 @@ public class SandboxMain : MonoBehaviour
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async UniTask<int> Ex()
|
||||||
async UniTaskVoid Start()
|
|
||||||
{
|
{
|
||||||
await UniTask.SwitchToMainThread();
|
await UniTask.Yield();
|
||||||
|
//throw new Exception();
|
||||||
|
await UniTask.Delay(TimeSpan.FromSeconds(15));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineRun()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before Coroutine yield return null," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
yield return null;
|
||||||
|
UnityEngine.Debug.Log("After Coroutine yield return null," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineRun2()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before Coroutine yield return WaitForEndOfFrame," + Time.frameCount);
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
UnityEngine.Debug.Log("After Coroutine yield return WaitForEndOfFrame," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
UnityEngine.Debug.Log("Onemore After Coroutine yield return WaitForEndOfFrame," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncRun()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(default)," + Time.frameCount);
|
||||||
|
await UniTask.Yield();
|
||||||
|
UnityEngine.Debug.Log("After async Yield(default)," + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncLastUpdate()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(LastUpdate)," + Time.frameCount);
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
UnityEngine.Debug.Log("After async Yield(LastUpdate)," + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncLastLast()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Before async Yield(LastPostLateUpdate)," + Time.frameCount);
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
|
UnityEngine.Debug.Log("After async Yield(LastPostLateUpdate)," + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid Yieldding()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
StartCoroutine(CoroutineRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid AsyncFixedUpdate()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
Debug.Log("Async:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator CoroutineFixedUpdate()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
yield return new WaitForFixedUpdate();
|
||||||
|
Debug.Log("Coroutine:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
// Debug.Log("FixedUpdate:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid DelayFrame3_Pre()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
Debug.Log("Before framecount:" + Time.frameCount);
|
||||||
|
await UniTask.DelayFrame(3);
|
||||||
|
Debug.Log("After framecount:" + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid DelayFrame3_Post()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
Debug.Log("Before framecount:" + Time.frameCount);
|
||||||
|
await UniTask.DelayFrame(3);
|
||||||
|
Debug.Log("After framecount:" + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask TestCoroutine()
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
throw new Exception("foobarbaz");
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask DelayCheck()
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
Debug.Log("before");
|
||||||
|
var t = UniTask.Delay(TimeSpan.FromSeconds(1), ignoreTimeScale: false);
|
||||||
|
|
||||||
|
await t;
|
||||||
|
Debug.Log("after");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async UniTaskVoid ExecuteAsync()
|
||||||
|
{
|
||||||
|
Debug.Log("1");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
Debug.Log("------------------");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
Debug.Log("2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
PlayerLoopInfo.Inject();
|
||||||
|
|
||||||
|
//_ = AsyncFixedUpdate();
|
||||||
|
//StartCoroutine(CoroutineFixedUpdate());
|
||||||
|
|
||||||
|
//StartCoroutine(TestCoroutine().ToCoroutine());
|
||||||
|
|
||||||
|
// Application.logMessageReceived += Application_logMessageReceived;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
{
|
||||||
|
_ = ExecuteAsync();
|
||||||
|
|
||||||
|
await UniTask.Yield();
|
||||||
|
|
||||||
|
//await DelayCheck();
|
||||||
|
/*
|
||||||
|
UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
StartCoroutine(CoroutineRun());
|
||||||
|
StartCoroutine(CoroutineRun2());
|
||||||
|
_ = AsyncRun();
|
||||||
|
_ = AsyncLastUpdate();
|
||||||
|
_ = AsyncLastLast();
|
||||||
|
*/
|
||||||
|
//await UniTask.Yield();
|
||||||
|
//_ = Test2();
|
||||||
|
// EarlyUpdate.ExecuteMainThreadJobs
|
||||||
|
// _ = Test2();
|
||||||
|
|
||||||
|
//var t = await Resources.LoadAsync<TextAsset>(Application.streamingAssetsPath + "test.txt");
|
||||||
|
//Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + (t != null));
|
||||||
|
//Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + ((TextAsset)t).text);
|
||||||
|
|
||||||
|
|
||||||
|
//await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
//UnityEngine.Debug.Log("after update:" + Time.frameCount);
|
||||||
|
////await UniTask.NextFrame();
|
||||||
|
////await UniTask.Yield();
|
||||||
|
////UnityEngine.Debug.Log("after update nextframe:" + Time.frameCount);
|
||||||
|
|
||||||
|
//StartCoroutine(CoroutineRun2());
|
||||||
|
////StartCoroutine(CoroutineRun());
|
||||||
|
//UnityEngine.Debug.Log("FOO?");
|
||||||
|
|
||||||
|
//_ = DelayFrame3_Pre();
|
||||||
|
//await UniTask.Yield();
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
{
|
||||||
|
_ = DelayFrame3_Post();
|
||||||
|
await UniTask.Yield();
|
||||||
|
|
||||||
|
//await UniTask.Yield(PlayerLoopTiming.LastPreUpdate);
|
||||||
|
//UnityEngine.Debug.Log("before update:" + Time.frameCount);
|
||||||
|
//await UniTask.NextFrame();
|
||||||
|
//await UniTask.Yield();
|
||||||
|
//UnityEngine.Debug.Log("before update nextframe:" + Time.frameCount);
|
||||||
|
|
||||||
|
//StartCoroutine(CoroutineRun());
|
||||||
|
|
||||||
|
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
//_ = Yieldding();
|
||||||
|
|
||||||
|
//var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
//var la = SceneManager.LoadSceneAsync("Scenes/ExceptionExamples").WithCancellation(cts.Token);
|
||||||
|
////cts.Cancel();
|
||||||
|
//await la;
|
||||||
|
//UnityEngine.Debug.Log("End LoadSceneAsync" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
||||||
|
}));
|
||||||
|
|
||||||
|
//return;
|
||||||
|
//await UniTask.SwitchToMainThread();
|
||||||
|
|
||||||
//UniTaskAsyncEnumerable.EveryValueChanged(mcc, x => x.MyProperty)
|
//UniTaskAsyncEnumerable.EveryValueChanged(mcc, x => x.MyProperty)
|
||||||
// .Do(_ => { }, () => Debug.Log("COMPLETED"))
|
// .Do(_ => { }, () => Debug.Log("COMPLETED"))
|
||||||
@@ -315,10 +520,29 @@ public class SandboxMain : MonoBehaviour
|
|||||||
// .Forget();
|
// .Forget();
|
||||||
|
|
||||||
//_ = Test1();
|
//_ = Test1();
|
||||||
Test2().Forget();
|
//Test2().Forget();
|
||||||
//StartCoroutine(Test3("https://bing.com/"));
|
//StartCoroutine(Test3("https://bing.com/"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//bool flip = false;
|
||||||
|
//var rect = cancelButton.GetComponent<RectTransform>();
|
||||||
|
//var cts = new CancellationTokenSource();
|
||||||
|
//var ct = cts.Token;
|
||||||
|
//okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
//{
|
||||||
|
// await rect.DOMoveX(10f * (flip ? -1 : 1), 3).OnUpdate(() => { Debug.Log("UPDATE YEAH"); }).WithCancellation(ct);
|
||||||
|
// flip = !flip;
|
||||||
|
// // ok.
|
||||||
|
//}));
|
||||||
|
//cancelButton.onClick.AddListener(() =>
|
||||||
|
//{
|
||||||
|
// cts.Cancel();
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
// DG.Tweening.Core.TweenerCore<int>
|
// DG.Tweening.Core.TweenerCore<int>
|
||||||
//Debug.Log("GO MOVEX");
|
//Debug.Log("GO MOVEX");
|
||||||
//await okButton.GetComponent<RectTransform>().DOMoveX(-10.2f, 3).WithCancellation(CancellationToken.None);
|
//await okButton.GetComponent<RectTransform>().DOMoveX(-10.2f, 3).WithCancellation(CancellationToken.None);
|
||||||
@@ -329,7 +553,7 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//await okButton.GetComponent<RectTransform>().DOMoveY(10.2f, 3).WithCancellation(CancellationToken.None);
|
//await okButton.GetComponent<RectTransform>().DOMoveY(10.2f, 3).WithCancellation(CancellationToken.None);
|
||||||
//Debug.Log("AGAIN END MOVE");
|
//Debug.Log("AGAIN END MOVE");
|
||||||
|
|
||||||
Debug.Log(Test().GetType().FullName);
|
//Debug.Log(Test().GetType().FullName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -383,11 +607,10 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//{
|
//{
|
||||||
|
|
||||||
|
|
||||||
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
//foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||||
{
|
//{
|
||||||
await UniTask.Yield();
|
// Debug.Log(type + ":" + size);
|
||||||
Debug.Log("Yeha");
|
//}
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
//}).Forget();
|
//}).Forget();
|
||||||
@@ -396,7 +619,7 @@ public class SandboxMain : MonoBehaviour
|
|||||||
|
|
||||||
//okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
|
//okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
|
||||||
|
|
||||||
PlayerLoopInfo.Inject();
|
|
||||||
|
|
||||||
//UpdateUniTask().Forget();
|
//UpdateUniTask().Forget();
|
||||||
|
|
||||||
@@ -405,15 +628,21 @@ public class SandboxMain : MonoBehaviour
|
|||||||
//await UniTask.Delay(TimeSpan.FromSeconds(1));
|
//await UniTask.Delay(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
|
||||||
_ = ReturnToMainThreadTest();
|
// _ = ReturnToMainThreadTest();
|
||||||
|
|
||||||
//GameObject.Destroy(this.gameObject);
|
//GameObject.Destroy(this.gameObject);
|
||||||
|
|
||||||
|
|
||||||
SynchronizationContext.Current.Post(_ =>
|
}
|
||||||
{
|
|
||||||
//UnityEngine.Debug.Log("Post:" + PlayerLoopInfo.CurrentLoopType);
|
private void Application_logMessageReceived2(string condition, string stackTrace, LogType type)
|
||||||
}, null);
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Application_logMessageReceived1(string condition, string stackTrace, LogType type)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
async UniTaskVoid UpdateUniTask()
|
async UniTaskVoid UpdateUniTask()
|
||||||
|
|||||||
@@ -126,15 +126,15 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
||||||
});
|
});
|
||||||
|
|
||||||
[UnityTest]
|
//[UnityTest]
|
||||||
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
//public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
//{
|
||||||
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
// var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
||||||
JobHandle.ScheduleBatchedJobs();
|
// JobHandle.ScheduleBatchedJobs();
|
||||||
await job.Schedule();
|
// await job.Schedule();
|
||||||
job.inOut[0].Should().Be(999);
|
// job.inOut[0].Should().Be(999);
|
||||||
job.inOut.Dispose();
|
// job.inOut.Dispose();
|
||||||
});
|
//});
|
||||||
|
|
||||||
class MyMyClass
|
class MyMyClass
|
||||||
{
|
{
|
||||||
@@ -269,7 +269,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
var first = Time.frameCount;
|
var first = Time.frameCount;
|
||||||
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
|
|
||||||
(Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
var r = (Time.frameCount - first);
|
||||||
|
(9 < r && r < 11).Should().BeTrue();
|
||||||
canceled.Should().Be(true);
|
canceled.Should().Be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -369,6 +370,24 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
throw new Exception("MyException");
|
throw new Exception("MyException");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator NextFrame1() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
||||||
|
var frame = Time.frameCount;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
Time.frameCount.Should().Be(frame + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator NextFrame2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
var frame = Time.frameCount;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
Time.frameCount.Should().Be(frame + 1);
|
||||||
|
});
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
|||||||
97
src/UniTask/Assets/Tests/CachelikeTest.cs
Normal file
97
src/UniTask/Assets/Tests/CachelikeTest.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class Cachelike
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator Check() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var v = await CachedCheck("foo", 10);
|
||||||
|
v.Should().Be(10);
|
||||||
|
|
||||||
|
var v2 = await CachedCheck("bar", 20);
|
||||||
|
v2.Should().Be(20);
|
||||||
|
|
||||||
|
var v3 = await CachedCheck("baz", 30);
|
||||||
|
v3.Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = await CachedCheck("foo", 10);
|
||||||
|
v.Should().Be(10);
|
||||||
|
|
||||||
|
var v2 = await CachedCheck("bar", 20);
|
||||||
|
v2.Should().Be(20);
|
||||||
|
|
||||||
|
var v3 = await CachedCheck("baz", 30);
|
||||||
|
v3.Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = CachedCheck("foo", 10);
|
||||||
|
var v2 = CachedCheck("bar", 20);
|
||||||
|
var v3 = CachedCheck("baz", 30);
|
||||||
|
|
||||||
|
(await v).Should().Be(10);
|
||||||
|
(await v2).Should().Be(20);
|
||||||
|
(await v3).Should().Be(30);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var v = CachedCheck("foo", 10, true);
|
||||||
|
var v2 = CachedCheck("bar", 20, true);
|
||||||
|
var v3 = CachedCheck("baz", 30, true);
|
||||||
|
|
||||||
|
(await v).Should().Be(10);
|
||||||
|
(await v2).Should().Be(20);
|
||||||
|
(await v3).Should().Be(30);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
static Dictionary<string, int> cacheDict = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
async UniTask<int> CachedCheck(string cache, int value, bool yield = false)
|
||||||
|
{
|
||||||
|
if (!cacheDict.ContainsKey(cache))
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yield)
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheDict.TryGetValue(cache, out var v))
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheDict.Add(cache, value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
src/UniTask/Assets/Tests/CachelikeTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/CachelikeTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 416e0e77b4408b0498792eb218ed2870
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
394
src/UniTask/Assets/Tests/DelayTest.cs
Normal file
394
src/UniTask/Assets/Tests/DelayTest.cs
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class DelayTest
|
||||||
|
{
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator DelayFrame() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// for (int i = 1; i < 5; i++)
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(i);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 1; i < 5; i++)
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(i);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + i);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator DelayFrameZero() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(0);
|
||||||
|
// Time.frameCount.Should().Be(frameCount); // same frame
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var frameCount = Time.frameCount;
|
||||||
|
// await UniTask.DelayFrame(0);
|
||||||
|
// Time.frameCount.Should().Be(frameCount + 1); // next frame
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFramePre() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
|
||||||
|
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
|
||||||
|
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
|
||||||
|
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFramePost() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
|
||||||
|
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
|
||||||
|
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
|
||||||
|
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameTest() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(0, 0).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame);
|
||||||
|
// xs[1].Should().Be(initialFrame + 1);
|
||||||
|
// xs[2].Should().Be(initialFrame + 2);
|
||||||
|
// xs[3].Should().Be(initialFrame + 3);
|
||||||
|
// xs[4].Should().Be(initialFrame + 4);
|
||||||
|
//});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
//Debug.Log("------------------");
|
||||||
|
//{
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await new MyTimerFrame(0, null)/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
|
||||||
|
// Debug.Log("OK 0 ------------------");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// var xs = await new MyTimerFrame(1, null)/*.Select(_ =>
|
||||||
|
// {
|
||||||
|
// var t = Time.frameCount;
|
||||||
|
// UnityEngine.Debug.Log("store frameCount:" + t);
|
||||||
|
// return t;
|
||||||
|
// })*/.ToArrayAsync();
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePre() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame);
|
||||||
|
// Debug.Log("OK 0 ------------------");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// Debug.Log("initialFrame:" + initialFrame);
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ =>
|
||||||
|
// {
|
||||||
|
// var t = Time.frameCount;
|
||||||
|
// UnityEngine.Debug.Log("store frameCount:" + t);
|
||||||
|
// return t;
|
||||||
|
// })*/.ToArrayAsync();
|
||||||
|
// Debug.Log("xs len:" + xs.Length);
|
||||||
|
// Debug.Log("xs[0]:" + xs[0]);
|
||||||
|
|
||||||
|
// xs[0].Should().Be(initialFrame + 1);
|
||||||
|
// Debug.Log("OK 1");
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// Debug.Log("OK 2");
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator TimerFrameSinglePost() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// //var initialFrame = Time.frameCount;
|
||||||
|
// //var xs = await UniTaskAsyncEnumerable.TimerFrame(0).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// //xs[0].Should().Be(initialFrame);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 1);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
// var initialFrame = Time.frameCount;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
|
||||||
|
// xs[0].Should().Be(initialFrame + 2);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[UnityTest]
|
||||||
|
//public IEnumerator Timer() => UniTask.ToCoroutine(async () =>
|
||||||
|
//{
|
||||||
|
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
|
||||||
|
|
||||||
|
// {
|
||||||
|
// var initialSeconds = Time.realtimeSinceStartup;
|
||||||
|
// var xs = await UniTaskAsyncEnumerable.Timer(TimeSpan.FromSeconds(2)).Select(_ => Time.realtimeSinceStartup).ToArrayAsync();
|
||||||
|
|
||||||
|
// Mathf.Approximately(initialSeconds, xs[0]).Should().BeFalse();
|
||||||
|
// Debug.Log("Init:" + initialSeconds);
|
||||||
|
// Debug.Log("After:" + xs[0]);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DelayTest2
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
Debug.Log("------------------");
|
||||||
|
{
|
||||||
|
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ThreadRunner
|
||||||
|
{
|
||||||
|
Thread thread;
|
||||||
|
|
||||||
|
public void Start(IPlayerLoopItem runner)
|
||||||
|
{
|
||||||
|
thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
Thread.Sleep(30);
|
||||||
|
while (runner.MoveNext())
|
||||||
|
{
|
||||||
|
Thread.Sleep(30);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MyTimerFrame : IUniTaskAsyncEnumerable<AsyncUnit>
|
||||||
|
{
|
||||||
|
//readonly PlayerLoopTiming updateTiming;
|
||||||
|
readonly int dueTimeFrameCount;
|
||||||
|
readonly int? periodFrameCount;
|
||||||
|
|
||||||
|
public MyTimerFrame(int dueTimeFrameCount, int? periodFrameCount)
|
||||||
|
{
|
||||||
|
//this.updateTiming = updateTiming;
|
||||||
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
|
{
|
||||||
|
readonly int dueTimeFrameCount;
|
||||||
|
readonly int? periodFrameCount;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int initialFrame;
|
||||||
|
int currentFrame;
|
||||||
|
bool dueTimePhase;
|
||||||
|
bool completed;
|
||||||
|
bool disposed;
|
||||||
|
ThreadRunner runner;
|
||||||
|
|
||||||
|
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
||||||
|
if (periodFrameCount != null)
|
||||||
|
{
|
||||||
|
if (periodFrameCount <= 0) periodFrameCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this.initialFrame = Time.frameCount;
|
||||||
|
this.dueTimePhase = true;
|
||||||
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
|
||||||
|
//TaskTracker.TrackActiveTask(this, 2);
|
||||||
|
//PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
|
|
||||||
|
runner = new ThreadRunner();
|
||||||
|
runner.Start(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncUnit Current => default;
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
// return false instead of throw
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested || completed) return default;
|
||||||
|
|
||||||
|
|
||||||
|
// reset value here.
|
||||||
|
this.currentFrame = 0;
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (!disposed)
|
||||||
|
{
|
||||||
|
disposed = true;
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Called MoveNext");
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Disposing");
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dueTimePhase)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("In DueTime Phase");
|
||||||
|
if (currentFrame == 0)
|
||||||
|
{
|
||||||
|
if (dueTimeFrameCount == 0)
|
||||||
|
{
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip in initial frame.
|
||||||
|
/*
|
||||||
|
UnityEngine.Debug.Log("(Init, frameConut)" + (initialFrame, Time.frameCount));
|
||||||
|
if (initialFrame == Time.frameCount)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Skip Here");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEngine.Debug.Log("Which Go?");
|
||||||
|
if (++currentFrame >= dueTimeFrameCount)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("END Go?");
|
||||||
|
dueTimePhase = false;
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("NG Go?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (periodFrameCount == null)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("PERIOD");
|
||||||
|
completed = true;
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++currentFrame >= periodFrameCount)
|
||||||
|
{
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
src/UniTask/Assets/Tests/DelayTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/DelayTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1376b93d9e1083a4a9b4081e08f3a7b7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,400 +1,400 @@
|
|||||||
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
//#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine.SceneManagement;
|
//using UnityEngine.SceneManagement;
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
#endif
|
//#endif
|
||||||
using UnityEngine.Networking;
|
//using UnityEngine.Networking;
|
||||||
|
|
||||||
#if !UNITY_2019_3_OR_NEWER
|
//#if !UNITY_2019_3_OR_NEWER
|
||||||
using UnityEngine.Experimental.LowLevel;
|
//using UnityEngine.Experimental.LowLevel;
|
||||||
#else
|
//#else
|
||||||
using UnityEngine.LowLevel;
|
//using UnityEngine.LowLevel;
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
using Unity.Jobs;
|
//using Unity.Jobs;
|
||||||
#endif
|
//#endif
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class AsyncTest
|
// public class AsyncTest
|
||||||
{
|
// {
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
|
|
||||||
public struct MyJob : IJob
|
// public struct MyJob : IJob
|
||||||
{
|
// {
|
||||||
public int loopCount;
|
// public int loopCount;
|
||||||
public NativeArray<int> inOut;
|
// public NativeArray<int> inOut;
|
||||||
public int result;
|
// public int result;
|
||||||
|
|
||||||
public void Execute()
|
// public void Execute()
|
||||||
{
|
// {
|
||||||
result = 0;
|
// result = 0;
|
||||||
for (int i = 0; i < loopCount; i++)
|
// for (int i = 0; i < loopCount; i++)
|
||||||
{
|
// {
|
||||||
result++;
|
// result++;
|
||||||
}
|
// }
|
||||||
inOut[0] = result;
|
// inOut[0] = result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
Time.timeScale = 0.5f;
|
// Time.timeScale = 0.5f;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(3));
|
// await UniTask.Delay(TimeSpan.FromSeconds(3));
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
Time.timeScale = 1.0f;
|
// Time.timeScale = 1.0f;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
Time.timeScale = 0.5f;
|
// Time.timeScale = 0.5f;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
|
// await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
Time.timeScale = 1.0f;
|
// Time.timeScale = 1.0f;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var a = UniTask.FromResult(999);
|
// var a = UniTask.FromResult(999);
|
||||||
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
// var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
||||||
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
// var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
||||||
|
|
||||||
var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
|
// var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
|
||||||
a2.Should().Be(999);
|
// a2.Should().Be(999);
|
||||||
b2.Should().Be(AsyncUnit.Default);
|
// b2.Should().Be(AsyncUnit.Default);
|
||||||
c2.Should().Be(AsyncUnit.Default);
|
// c2.Should().Be(AsyncUnit.Default);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var a = UniTask.FromResult(999);
|
// var a = UniTask.FromResult(999);
|
||||||
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
// var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
|
||||||
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
// var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
|
||||||
|
|
||||||
var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
|
// var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
|
||||||
win.Should().Be(0);
|
// win.Should().Be(0);
|
||||||
a2.Should().Be(999);
|
// a2.Should().Be(999);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
// await ToaruCoroutineEnumerator(); // wait 5 frame:)
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
// var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
|
||||||
JobHandle.ScheduleBatchedJobs();
|
// JobHandle.ScheduleBatchedJobs();
|
||||||
await job.Schedule();
|
// await job.Schedule();
|
||||||
job.inOut[0].Should().Be(999);
|
// job.inOut[0].Should().Be(999);
|
||||||
job.inOut.Dispose();
|
// job.inOut.Dispose();
|
||||||
});
|
// });
|
||||||
|
|
||||||
class MyMyClass
|
// class MyMyClass
|
||||||
{
|
// {
|
||||||
public int MyProperty { get; set; }
|
// public int MyProperty { get; set; }
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool t = false;
|
// bool t = false;
|
||||||
|
|
||||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||||
|
|
||||||
UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget();
|
// UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool t = true;
|
// bool t = true;
|
||||||
|
|
||||||
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget();
|
// UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var v = new MyMyClass { MyProperty = 99 };
|
// var v = new MyMyClass { MyProperty = 99 };
|
||||||
|
|
||||||
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget();
|
// UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget();
|
||||||
|
|
||||||
var startFrame = Time.frameCount;
|
// var startFrame = Time.frameCount;
|
||||||
await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
// await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
var diff = Time.frameCount - startFrame;
|
// var diff = Time.frameCount - startFrame;
|
||||||
diff.Should().Be(11);
|
// diff.Should().Be(11);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
|
|
||||||
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
|
// var currentThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await UniTask.SwitchToThreadPool();
|
// await UniTask.SwitchToThreadPool();
|
||||||
//await UniTask.SwitchToThreadPool();
|
// //await UniTask.SwitchToThreadPool();
|
||||||
//await UniTask.SwitchToThreadPool();
|
// //await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
|
// var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
currentThreadId.Should().NotBe(switchedThreadId);
|
// currentThreadId.Should().NotBe(switchedThreadId);
|
||||||
|
|
||||||
|
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
|
|
||||||
var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
|
// var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
currentThreadId.Should().Be(switchedThreadId2);
|
// currentThreadId.Should().Be(switchedThreadId2);
|
||||||
});
|
// });
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var v = await Observable.Range(1, 10).ToUniTask();
|
// // var v = await Observable.Range(1, 10).ToUniTask();
|
||||||
// v.Is(10);
|
// // v.Is(10);
|
||||||
|
|
||||||
// v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
|
// // v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
|
||||||
// v.Is(1);
|
// // v.Is(1);
|
||||||
|
|
||||||
// v = await UniTask.DelayFrame(10).ToObservable().ToTask();
|
// // v = await UniTask.DelayFrame(10).ToObservable().ToTask();
|
||||||
// v.Is(10);
|
// // v.Is(10);
|
||||||
|
|
||||||
// v = await UniTask.FromResult(99).ToObservable();
|
// // v = await UniTask.FromResult(99).ToObservable();
|
||||||
// v.Is(99);
|
// // v.Is(99);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var rp1 = new ReactiveProperty<int>(99);
|
// // var rp1 = new ReactiveProperty<int>(99);
|
||||||
|
|
||||||
// UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
|
// // UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
|
||||||
|
|
||||||
// await rp1;
|
// // await rp1;
|
||||||
|
|
||||||
// rp1.Value.Is(100);
|
// // rp1.Value.Is(100);
|
||||||
|
|
||||||
// // var delay2 = UniTask.DelayFrame(10);
|
// // // var delay2 = UniTask.DelayFrame(10);
|
||||||
// // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
|
// // // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
|
||||||
|
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var rc = new ReactiveCommand<int>();
|
// // var rc = new ReactiveCommand<int>();
|
||||||
|
|
||||||
// UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
|
// // UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
|
||||||
|
|
||||||
// var v = await rc;
|
// // var v = await rc;
|
||||||
|
|
||||||
// v.Is(100);
|
// // v.Is(100);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
// UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
||||||
|
|
||||||
var first = Time.frameCount;
|
// var first = Time.frameCount;
|
||||||
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
// var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
|
|
||||||
(Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
// (Time.frameCount - first).Should().Be(11); // 10 frame canceled
|
||||||
canceled.Should().Be(true);
|
// canceled.Should().Be(true);
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
// UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
|
||||||
|
|
||||||
bool occur = false;
|
// bool occur = false;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.DelayFrame(100, cancellationToken: cts.Token);
|
// await UniTask.DelayFrame(100, cancellationToken: cts.Token);
|
||||||
}
|
// }
|
||||||
catch (OperationCanceledException)
|
// catch (OperationCanceledException)
|
||||||
{
|
// {
|
||||||
occur = true;
|
// occur = true;
|
||||||
}
|
// }
|
||||||
occur.Should().BeTrue();
|
// occur.Should().BeTrue();
|
||||||
});
|
// });
|
||||||
|
|
||||||
IEnumerator ToaruCoroutineEnumerator()
|
// IEnumerator ToaruCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
yield return null;
|
// yield return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool calledEx = false;
|
// bool calledEx = false;
|
||||||
Action<Exception> action = exx =>
|
// Action<Exception> action = exx =>
|
||||||
{
|
// {
|
||||||
calledEx = true;
|
// calledEx = true;
|
||||||
exx.Message.Should().Be("MyException");
|
// exx.Message.Should().Be("MyException");
|
||||||
};
|
// };
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException += action;
|
// UniTaskScheduler.UnobservedTaskException += action;
|
||||||
|
|
||||||
var ex = InException1();
|
// var ex = InException1();
|
||||||
ex = default(UniTask);
|
// ex = default(UniTask);
|
||||||
|
|
||||||
await UniTask.DelayFrame(3);
|
// await UniTask.DelayFrame(3);
|
||||||
|
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
// GC.WaitForPendingFinalizers();
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
|
|
||||||
await UniTask.DelayFrame(1);
|
// await UniTask.DelayFrame(1);
|
||||||
|
|
||||||
calledEx.Should().BeTrue();
|
// calledEx.Should().BeTrue();
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException -= action;
|
// UniTaskScheduler.UnobservedTaskException -= action;
|
||||||
});
|
// });
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
bool calledEx = false;
|
// bool calledEx = false;
|
||||||
Action<Exception> action = exx =>
|
// Action<Exception> action = exx =>
|
||||||
{
|
// {
|
||||||
calledEx = true;
|
// calledEx = true;
|
||||||
exx.Message.Should().Be("MyException");
|
// exx.Message.Should().Be("MyException");
|
||||||
};
|
// };
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException += action;
|
// UniTaskScheduler.UnobservedTaskException += action;
|
||||||
|
|
||||||
var ex = InException2();
|
// var ex = InException2();
|
||||||
ex = default(UniTask<int>);
|
// ex = default(UniTask<int>);
|
||||||
|
|
||||||
await UniTask.DelayFrame(3);
|
// await UniTask.DelayFrame(3);
|
||||||
|
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
// GC.WaitForPendingFinalizers();
|
||||||
GC.Collect();
|
// GC.Collect();
|
||||||
|
|
||||||
await UniTask.DelayFrame(1);
|
// await UniTask.DelayFrame(1);
|
||||||
|
|
||||||
calledEx.Should().BeTrue();
|
// calledEx.Should().BeTrue();
|
||||||
|
|
||||||
UniTaskScheduler.UnobservedTaskException -= action;
|
// UniTaskScheduler.UnobservedTaskException -= action;
|
||||||
});
|
// });
|
||||||
|
|
||||||
async UniTask InException1()
|
// async UniTask InException1()
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
throw new Exception("MyException");
|
// throw new Exception("MyException");
|
||||||
}
|
// }
|
||||||
|
|
||||||
async UniTask<int> InException2()
|
// async UniTask<int> InException2()
|
||||||
{
|
// {
|
||||||
await UniTask.Yield();
|
// await UniTask.Yield();
|
||||||
throw new Exception("MyException");
|
// throw new Exception("MyException");
|
||||||
}
|
// }
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var time = Time.realtimeSinceStartup;
|
// var time = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
await ParentCoroutineEnumerator();
|
// await ParentCoroutineEnumerator();
|
||||||
|
|
||||||
var elapsed = Time.realtimeSinceStartup - time;
|
// var elapsed = Time.realtimeSinceStartup - time;
|
||||||
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
// ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
|
||||||
});
|
// });
|
||||||
|
|
||||||
IEnumerator ParentCoroutineEnumerator()
|
// IEnumerator ParentCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return ChildCoroutineEnumerator();
|
// yield return ChildCoroutineEnumerator();
|
||||||
}
|
// }
|
||||||
|
|
||||||
IEnumerator ChildCoroutineEnumerator()
|
// IEnumerator ChildCoroutineEnumerator()
|
||||||
{
|
// {
|
||||||
yield return new WaitForSeconds(3);
|
// yield return new WaitForSeconds(3);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
//#endif
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -1,95 +1,95 @@
|
|||||||
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
//#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine.SceneManagement;
|
//using UnityEngine.SceneManagement;
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
#endif
|
//#endif
|
||||||
using UnityEngine.Networking;
|
//using UnityEngine.Networking;
|
||||||
|
|
||||||
#if !UNITY_2019_3_OR_NEWER
|
//#if !UNITY_2019_3_OR_NEWER
|
||||||
using UnityEngine.Experimental.LowLevel;
|
//using UnityEngine.Experimental.LowLevel;
|
||||||
#else
|
//#else
|
||||||
using UnityEngine.LowLevel;
|
//using UnityEngine.LowLevel;
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
using Unity.Jobs;
|
//using Unity.Jobs;
|
||||||
#endif
|
//#endif
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class RunTest
|
// public class RunTest
|
||||||
{
|
// {
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#if !UNITY_WSA
|
//#if !UNITY_WSA
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var main = Thread.CurrentThread.ManagedThreadId;
|
// // var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
// var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
|
// // var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
|
||||||
// UnityEngine.Debug.Log("Ret Value is:" + v);
|
// // UnityEngine.Debug.Log("Ret Value is:" + v);
|
||||||
// UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
// // UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||||
// //v.Should().Be(3);
|
// // //v.Should().Be(3);
|
||||||
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
// // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var main = Thread.CurrentThread.ManagedThreadId;
|
// var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
var v = await UniTask.Run(() => 3, true);
|
// var v = await UniTask.Run(() => 3, true);
|
||||||
v.Should().Be(3);
|
// v.Should().Be(3);
|
||||||
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
// main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
||||||
});
|
// });
|
||||||
|
|
||||||
//[UnityTest]
|
// //[UnityTest]
|
||||||
//public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
|
// //public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
// //{
|
||||||
// var main = Thread.CurrentThread.ManagedThreadId;
|
// // var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
// try
|
// // try
|
||||||
// {
|
// // {
|
||||||
// await UniTask.Run<int>(() => throw new Exception(), false);
|
// // await UniTask.Run<int>(() => throw new Exception(), false);
|
||||||
// }
|
// // }
|
||||||
// catch
|
// // catch
|
||||||
// {
|
// // {
|
||||||
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
// // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
|
||||||
// }
|
// // }
|
||||||
//});
|
// //});
|
||||||
|
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var main = Thread.CurrentThread.ManagedThreadId;
|
// var main = Thread.CurrentThread.ManagedThreadId;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await UniTask.Run<int>(() => throw new Exception(), true);
|
// await UniTask.Run<int>(() => throw new Exception(), true);
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
// main.Should().Be(Thread.CurrentThread.ManagedThreadId);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
//#endif
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -1,43 +1,43 @@
|
|||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
//#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
//#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections;
|
//using System.Collections;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
using UnityEngine.Scripting;
|
//using UnityEngine.Scripting;
|
||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using Unity.Collections;
|
//using Unity.Collections;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using NUnit.Framework;
|
//using NUnit.Framework;
|
||||||
using UnityEngine.TestTools;
|
//using UnityEngine.TestTools;
|
||||||
using FluentAssertions;
|
//using FluentAssertions;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
//namespace Cysharp.Threading.TasksTests
|
||||||
{
|
//{
|
||||||
public class WhenAnyTest
|
// public class WhenAnyTest
|
||||||
{
|
// {
|
||||||
[UnityTest]
|
// [UnityTest]
|
||||||
public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
|
// public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
// {
|
||||||
var cts = new CancellationTokenSource();
|
// var cts = new CancellationTokenSource();
|
||||||
var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
|
// var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
|
||||||
var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
|
// var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
|
||||||
cts.CancelAfterSlim(200);
|
// cts.CancelAfterSlim(200);
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
|
// var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
ex.Should().BeAssignableTo<OperationCanceledException>();
|
// ex.Should().BeAssignableTo<OperationCanceledException>();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
@@ -6,13 +6,20 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.TestTools;
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
namespace Cysharp.Threading.TasksTests
|
namespace Cysharp.Threading.TasksTests
|
||||||
{
|
{
|
||||||
public class Preserve
|
public class Preserve
|
||||||
{
|
{
|
||||||
|
public Preserve()
|
||||||
|
{
|
||||||
|
// TaskPool.SetMaxPoolSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () =>
|
public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -33,12 +40,17 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () =>
|
public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
await UniTask.Yield(PlayerLoopTiming.Update);
|
||||||
|
|
||||||
var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve();
|
var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve();
|
||||||
var before = UnityEngine.Time.frameCount;
|
|
||||||
|
var before = UnityEngine.Time.frameCount; // 0
|
||||||
|
|
||||||
await delay;
|
await delay;
|
||||||
var afterOne = UnityEngine.Time.frameCount;
|
var afterOne = UnityEngine.Time.frameCount; // 5
|
||||||
|
|
||||||
await delay;
|
await delay;
|
||||||
var afterTwo = UnityEngine.Time.frameCount;
|
var afterTwo = UnityEngine.Time.frameCount; // 5
|
||||||
|
|
||||||
(afterOne - before).Should().Be(5);
|
(afterOne - before).Should().Be(5);
|
||||||
afterOne.Should().Be(afterTwo);
|
afterOne.Should().Be(afterTwo);
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"UnityEditor.TestRunner",
|
"UnityEditor.TestRunner",
|
||||||
"UniTask",
|
"UniTask",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager",
|
||||||
"DOTween.Modules"
|
"DOTween.Modules",
|
||||||
|
"UniTask.Linq"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ EditorBuildSettings:
|
|||||||
- enabled: 1
|
- enabled: 1
|
||||||
path: Assets/Scenes/SandboxMain.unity
|
path: Assets/Scenes/SandboxMain.unity
|
||||||
guid: 2cda990e2423bbf4892e6590ba056729
|
guid: 2cda990e2423bbf4892e6590ba056729
|
||||||
- enabled: 0
|
- enabled: 1
|
||||||
path:
|
path: Assets/Scenes/ExceptionExamples.unity
|
||||||
guid: 00000000000000000000000000000000
|
guid: b5fed17e3ece238439bc796d8747df5d
|
||||||
m_configObjects: {}
|
m_configObjects: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user