Compare commits

..

51 Commits

Author SHA1 Message Date
neuecc
52cdadc035 u 2021-01-07 17:43:35 +09:00
neuecc
5401b9b227 ready for release 2.1.0 2021-01-07 17:28:09 +09:00
neuecc
38de930f81 s 2021-01-07 17:25:03 +09:00
neuecc
9be6ef7ba6 new PlayerLoopType detector supports before 2019_4 2021-01-07 17:18:21 +09:00
neuecc
739bc6e26c add stale 2021-01-07 16:59:38 +09:00
neuecc
71879266ac Fix DelayType.Realtime does not work when use BuildPlayer in UnityEditor 2021-01-07 16:40:41 +09:00
neuecc
5ced0a1d4b Add UnityWebRequestException.ResponseHeaders #198 2021-01-07 16:03:27 +09:00
neuecc
908e361985 Add PlayerLoopTiming.TimeUpdate/LastTimeUpdate in Unity 2020.2 2021-01-07 13:02:18 +09:00
neuecc
797affae4d throw 2021-01-07 12:09:55 +09:00
Yoshifumi Kawai
ae3b825e29 Merge pull request #210 from WallyCZ/2020.2_fix
Unity 2020.2 changed order of the PlayerLoop subsystem list (should fix #208)
2021-01-07 12:01:11 +09:00
neuecc
143d97a73b update version 2021-01-07 11:59:31 +09:00
Václav Lipert
90631c54b1 More robust finding of right player loop system 2021-01-06 23:32:23 +01:00
Yoshifumi Kawai
478e2998a8 Merge pull request #204 from piti6/fix-defer
Accept calling DeferPromise.GetStatus multiple times
2021-01-06 17:45:28 +09:00
Yoshifumi Kawai
9406305b2e Merge pull request #203 from RamType0/FixCompletedTaskAsUniTaskAllocating
Suppress allocations around UniTask<T>.AsUniTask and UniTask.AsAsyncUnitUniTask
2021-01-06 17:19:19 +09:00
Václav Lipert
1c26c81b20 2020.2 changed PlayerLoopSystem order fix 2021-01-03 00:29:00 +01:00
RamType0
a455de88b0 Suppress allocations around UniTask<T>.AsUniTask and UniTask.AsAsyncUnitUniTask
- Fix completedTask.AsUniTask or completedTask.AsAsyncUnitUniTask leaks IUniTaskSource
- UniTask.AsAsyncUnitUniTask no longer allocates when its inner IUniTaskSource is IUniTaskSource<AsyncUnit>
2020-12-17 14:28:10 +09:00
piti6
fba6942d5f Accept GetStatus calling multiple times 2020-12-17 12:31:43 +09:00
Yoshifumi Kawai
3115efb672 Merge pull request #196 from RamType0/ForceCompleteJobHandleOnApplicationQuit
Force complete awaiting JobHandles when quitted in UnityEditor
2020-11-25 09:00:21 +09:00
Ram.Type-0
fd70c031cb Force complete awaiting JobHandles when quitted in UnityEditor 2020-11-24 23:50:01 +09:00
neuecc
a2eb75df68 Merge remote-tracking branch 'origin/master' 2020-11-09 16:08:20 +09:00
neuecc
4a62d7eba6 2.0.37 2020-11-09 16:08:17 +09:00
Yoshifumi Kawai
40d2d2fe06 Merge pull request #189 from IllusionCui/master
[DoTween]:fix CancellationToken can't stop UniTask
2020-11-09 15:52:13 +09:00
neuecc
d5d2cb5937 use Dictionary instead of ConcurrentDictionary for safety of WebGL build, #179 2020-11-09 14:34:11 +09:00
neuecc
854100c075 fix invalid usage of SpinLock, #195 2020-11-09 14:20:03 +09:00
cuibeibei
5837b26208 [DoTween]:fix CancellationToken can't stop UniTask 2020-10-28 18:48:10 +08:00
Yoshifumi Kawai
da0e654e7d Merge pull request #183 from Cysharp/chore/github_Actions_security_fix
chore: replace set-env to ENV FILE $GITHUB_ENV
2020-10-14 12:39:48 +09:00
Ikiru Yoshizaki
a3e9932be7 chore: replace set-env to ENV FILE $GITHUB_ENV
fix https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
2020-10-14 12:12:28 +09:00
neuecc
e82353b4d9 UNITY_WEBGL unittest 2020-10-07 10:38:27 +09:00
Yoshifumi Kawai
944b61f28c Update README.md 2020-09-25 17:32:17 +09:00
Yoshifumi Kawai
457c574865 Update README.md 2020-09-24 10:31:59 +09:00
Yoshifumi Kawai
089a509663 Update README.md 2020-09-23 17:16:09 +09:00
neuecc
3bebaef969 2.0.36 2020-09-22 10:49:04 +09:00
neuecc
37e8b4500e Add enumerator.ToUniTask(MonoBehaviour coroutineRunner), log WARN on await enumerator when yield not supported types(Coroutine, WaitForEndOfFrame, WaitForFixedUpdate). 2020-09-22 10:08:03 +09:00
neuecc
8537ddf8a6 fix Forget when source is already completed and source is manualy optimized task source, does not work correctly 2020-09-22 09:54:05 +09:00
neuecc
346b1e0a6b 2.0.35 2020-09-21 12:56:13 +09:00
neuecc
fc7b9660a5 remove OnMouse_event trigger to prevent warning on Andoird, iOS, #170 2020-09-21 12:50:25 +09:00
neuecc
21e5cc22c7 notice for WaitForEndOfFrame #169 2020-09-21 12:49:26 +09:00
neuecc
3f18b37e5f changed clear loop runner queue timing in UnityEditor and run rest action when quitted 2020-09-21 12:30:31 +09:00
neuecc
5d4a90e9bd fix broken loop-runner from 2.0.32, #172 2020-09-21 11:42:02 +09:00
neuecc
2bf9f4f062 fix 2020-09-16 09:58:30 +09:00
neuecc
d69490cb49 one more things 2020-09-16 09:55:14 +09:00
neuecc
4e460c11ca 2.0.34 2020-09-16 09:48:57 +09:00
neuecc
9313969314 2.0.33 2020-09-15 06:53:58 +09:00
neuecc
a40f89a922 Merge remote-tracking branch 'origin/master' 2020-09-15 06:35:28 +09:00
neuecc
e0d8410b62 fix IEnumerator.ToUniTask, does not work correctly when coroutine complete immediately 2020-09-15 06:35:22 +09:00
Yoshifumi Kawai
bef1bd8ad1 Merge pull request #164 from c0nd3v/master
Fixed AwaitForAllAssets()
2020-09-12 06:09:29 +09:00
c0nd3v
81b4fcfac1 Fixed AwaitForAllAssets() 2020-09-11 10:41:41 -04:00
Yoshifumi Kawai
f1e4a3c65d Merge pull request #162 from hikarin522/patch-3
Fix UniTaskExtensions.Unwrap()
2020-09-09 15:38:03 +09:00
hikari
65622b01f6 [Unwrap] add ConfigureAwait 2020-09-09 14:15:03 +09:00
hikari
87dd5f13fd [Unwrap()] fix: remove type parameter 2020-09-09 14:05:37 +09:00
Yoshifumi Kawai
79cd2c17ba Update README.md 2020-09-07 18:55:44 +09:00
39 changed files with 694 additions and 200 deletions

View File

@@ -3,7 +3,7 @@ name: Build-Debug
on: on:
push: push:
branches: branches:
- "**" - "master"
tags: tags:
- "!*" # not a tag push - "!*" # not a tag push
pull_request: pull_request:
@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.101 dotnet-version: 3.1.x
- run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj - run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj
build-unity: build-unity:

View File

@@ -16,9 +16,9 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.101 dotnet-version: 3.1.x
# set release tag(*.*.*) to env.GIT_TAG # set release tag(*.*.*) to env.GIT_TAG
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/} - run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
# build and pack # build and pack
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }} - run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
@@ -34,7 +34,7 @@ jobs:
build-unity: build-unity:
strategy: strategy:
matrix: matrix:
unity: ['2019.3.9f1'] unity: ["2019.3.9f1"]
include: include:
- unity: 2019.3.9f1 - unity: 2019.3.9f1
license: UNITY_2019_3 license: UNITY_2019_3
@@ -51,14 +51,14 @@ jobs:
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0 - run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0
# set release tag(*.*.*) to env.GIT_TAG # set release tag(*.*.*) to env.GIT_TAG
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/} - run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
# Execute scripts: Export Package # Execute scripts: Export Package
- name: Export unitypackage - name: Export unitypackage
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
working-directory: src/UniTask working-directory: src/UniTask
# Store artifacts. # Store artifacts.
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: UniTask.${{ env.GIT_TAG }}.unitypackage name: UniTask.${{ env.GIT_TAG }}.unitypackage
@@ -72,34 +72,34 @@ jobs:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip NUGET_XMLDOC_MODE: skip
steps: steps:
# setup dotnet for nuget push # setup dotnet for nuget push
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.101 dotnet-version: 3.1.x
# set release tag(*.*.*) to env.GIT_TAG # set release tag(*.*.*) to env.GIT_TAG
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/} - run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
# Create Releases # Create Releases
- uses: actions/create-release@v1 - uses: actions/create-release@v1
id: create_release id: create_release
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: Ver.${{ github.ref }} release_name: Ver.${{ github.ref }}
# Download(All) Artifacts to current directory # Download(All) Artifacts to current directory
- uses: actions/download-artifact@v2-preview - uses: actions/download-artifact@v2-preview
# Upload to NuGet # Upload to NuGet
- run: dotnet nuget push "./nuget/*.nupkg" -s https://www.nuget.org/api/v2/package -k ${{ secrets.NUGET_KEY }} - run: dotnet nuget push "./nuget/*.nupkg" -s https://www.nuget.org/api/v2/package -k ${{ secrets.NUGET_KEY }}
# Upload to Releases(unitypackage) # Upload to Releases(unitypackage)
- uses: actions/upload-release-asset@v1 - uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./UniTask.${{ env.GIT_TAG }}.unitypackage/UniTask.${{ env.GIT_TAG }}.unitypackage asset_path: ./UniTask.${{ env.GIT_TAG }}.unitypackage/UniTask.${{ env.GIT_TAG }}.unitypackage
asset_name: UniTask.${{ env.GIT_TAG }}.unitypackage asset_name: UniTask.${{ env.GIT_TAG }}.unitypackage
asset_content_type: application/octet-stream asset_content_type: application/octet-stream

24
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: "Close stale issues"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# enable issue
stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
stale-issue-label: "stale"
# enable pr
stale-pr-message: "This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
stale-pr-label: "stale"
days-before-stale: 90
days-before-close: 7
exempt-issue-labels: "wip"
exempt-pr-labels: "wip"
remove-stale-when-updated: true

4
.gitignore vendored
View File

@@ -255,3 +255,7 @@ src/UniTask/DOTween.Modules.Player.csproj
src/UniTask/Assembly-CSharp.Player.csproj src/UniTask/Assembly-CSharp.Player.csproj
src/UniTask/Unity.EditorCoroutines.Editor.csproj src/UniTask/Unity.EditorCoroutines.Editor.csproj
src/UniTask/.vsconfig
src/UniTask/Logs/ApiUpdaterCheck.txt

View File

@@ -14,7 +14,8 @@ Provides an efficient allocation free async/await integration to Unity.
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource * Highly compatible behaviour with Task/ValueTask/IValueTaskSource
Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd) ](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
Advanced tips, see blog post: [Extends UnityWebRequest via async decorator pattern — Advanced Techniques of UniTask](https://medium.com/@neuecc/extends-unitywebrequest-via-async-decorator-pattern-advanced-techniques-of-unitask-ceff9c5ee846)
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
@@ -214,6 +215,8 @@ await task; // NG, throws Exception
Store to the class field, you can use `UniTask.Lazy` that gurantee call multipletimes. `.Preserve()` allows for multiple calls (internally cached results). This is useful when multiple calls in a function scope. Store to the class field, you can use `UniTask.Lazy` that gurantee call multipletimes. `.Preserve()` allows for multiple calls (internally cached results). This is useful when multiple calls in a function scope.
Also `UniTaskCompletionSource` can await multipletimes and await from many caller.
Cancellation and Exception handling Cancellation and Exception handling
--- ---
Some UniTask factory methods have `CancellationToken cancellationToken = default` parameter. Andalso some async operation for unity have `WithCancellation(CancellationToken)` and `ToUniTask(..., CancellationToken cancellation = default)` extension methods. Some UniTask factory methods have `CancellationToken cancellationToken = default` parameter. Andalso some async operation for unity have `WithCancellation(CancellationToken)` and `ToUniTask(..., CancellationToken cancellation = default)` extension methods.
@@ -343,6 +346,11 @@ public enum PlayerLoopTiming
PostLateUpdate = 12, PostLateUpdate = 12,
LastPostLateUpdate = 13 LastPostLateUpdate = 13
#if UNITY_2020_2_OR_NEWER
TimeUpdate = 14,
LastTimeUpdate = 15,
#endif
} }
``` ```
@@ -350,6 +358,8 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
`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.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.
> `await UniTask.WaitForEndOfFrame()` is not equilavelnt to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) does not work correctly when replace to async/await. In that case, use a 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`. `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. > UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
@@ -496,10 +506,10 @@ DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) aw
AsyncEnumerable and Async LINQ AsyncEnumerable and Async LINQ
--- ---
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era. Unity 2020.2 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.
```csharp ```csharp
// Unity 2020.2.0a12, C# 8.0 // Unity 2020.2, C# 8.0
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token)) await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
{ {
Debug.Log("Update() " + Time.frameCount); Debug.Log("Update() " + Time.frameCount);
@@ -793,9 +803,11 @@ IEnumerator.ToUniTask limitation
--- ---
You can convert coroutine(IEnumerator) to UniTask(or await directly) but has some limitations. You can convert coroutine(IEnumerator) to UniTask(or await directly) but has some limitations.
* `WaitForEndOfFrame`/`WaitForFixedUpdate` is not supported, used `yield return null` instead. * `WaitForEndOfFrame`/`WaitForFixedUpdate`/`Coroutine` is not supported.
* Consuming loop timing is not same as StartCoroutine, it is used specified PlayerLoopTiming, and default's `PlayerLoopTiming.Update` is run before MonoBehaviour's Update and StartCoroutine's loop. * Consuming loop timing is not same as StartCoroutine, it is used specified PlayerLoopTiming, and default's `PlayerLoopTiming.Update` is run before MonoBehaviour's Update and StartCoroutine's loop.
If you want to convert fully compatible from coroutine to async, use `IEnumerator.ToUniTask(MonoBehaviour coroutineRunner)` overload. It executes StartCoroutine on an instance of the argument MonoBehaviour and waits for it to complete in UniTask.
For UnityEditor For UnityEditor
--- ---
UniTask can run on Unity Edtitor like Editor Coroutine. However, there are some limitations. UniTask can run on Unity Edtitor like Editor Coroutine. However, there are some limitations.
@@ -851,7 +863,7 @@ Use UniTask type.
Pooling Configuration 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. UniTask is aggressively caching async promise object to achive zero allocation(technical details, see blog post [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)). 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 ```csharp
foreach (var (type, size) in TaskPool.GetCacheSizeInfo()) foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
@@ -905,7 +917,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`. or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.31`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.31`. If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
### Install via OpenUPM ### Install via OpenUPM

View File

@@ -32,6 +32,19 @@ namespace Cysharp.Threading.Tasks
return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token); return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token);
} }
public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner)
{
var source = AutoResetUniTaskCompletionSource.Create();
coroutineRunner.StartCoroutine(Core(enumerator, coroutineRunner, source));
return source.Task;
}
static IEnumerator Core(IEnumerator inner, MonoBehaviour coroutineRunner, AutoResetUniTaskCompletionSource source)
{
yield return coroutineRunner.StartCoroutine(inner);
source.TrySetResult();
}
sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise> sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
{ {
static TaskPool<EnumeratorPromise> pool; static TaskPool<EnumeratorPromise> pool;
@@ -46,6 +59,8 @@ namespace Cysharp.Threading.Tasks
IEnumerator innerEnumerator; IEnumerator innerEnumerator;
CancellationToken cancellationToken; CancellationToken cancellationToken;
int initialFrame; int initialFrame;
bool loopRunning;
bool calledGetResult;
UniTaskCompletionSourceCore<object> core; UniTaskCompletionSourceCore<object> core;
@@ -68,6 +83,8 @@ namespace Cysharp.Threading.Tasks
result.innerEnumerator = ConsumeEnumerator(innerEnumerator); result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
result.loopRunning = true;
result.calledGetResult = false;
result.initialFrame = -1; result.initialFrame = -1;
PlayerLoopHelper.AddAction(timing, result); PlayerLoopHelper.AddAction(timing, result);
@@ -82,11 +99,15 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
calledGetResult = true;
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
TryReturn(); if (!loopRunning)
{
TryReturn();
}
} }
} }
@@ -107,8 +128,21 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext() public bool MoveNext()
{ {
if (calledGetResult)
{
loopRunning = false;
TryReturn();
return false;
}
if (innerEnumerator == null) // invalid status, returned but loop running?
{
return false;
}
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
loopRunning = false;
core.TrySetCanceled(cancellationToken); core.TrySetCanceled(cancellationToken);
return false; return false;
} }
@@ -135,10 +169,12 @@ namespace Cysharp.Threading.Tasks
} }
catch (Exception ex) catch (Exception ex)
{ {
loopRunning = false;
core.TrySetException(ex); core.TrySetException(ex);
return false; return false;
} }
loopRunning = false;
core.TrySetResult(null); core.TrySetResult(null);
return false; return false;
} }
@@ -192,7 +228,7 @@ namespace Cysharp.Threading.Tasks
} }
else else
{ {
yield return null; goto WARN;
} }
} }
else if (current is IEnumerator e3) else if (current is IEnumerator e3)
@@ -205,9 +241,15 @@ namespace Cysharp.Threading.Tasks
} }
else else
{ {
// WaitForEndOfFrame, WaitForFixedUpdate, others. goto WARN;
yield return null;
} }
continue;
WARN:
// WaitForEndOfFrame, WaitForFixedUpdate, others.
UnityEngine.Debug.LogWarning($"yield {current.GetType().Name} is not supported on await IEnumerator or IEnumerator.ToUniTask(), please use ToUniTask(MonoBehaviour coroutineRunner) instead.");
yield return null;
} }
} }
@@ -238,5 +280,4 @@ namespace Cysharp.Threading.Tasks
} }
} }
} }
} }

View File

@@ -31,7 +31,8 @@ namespace Cysharp.Threading.Tasks
if (!handle.IsValid()) if (!handle.IsValid())
{ {
throw new Exception("Attempting to use an invalid operation handle"); // autoReleaseHandle:true handle is invalid(immediately internal handle == null) so return completed.
return UniTask.CompletedTask;
} }
if (handle.IsDone) if (handle.IsDone)

View File

@@ -223,6 +223,17 @@ namespace Cysharp.Threading.Tasks
void OnCompleteCallbackDelegate() void OnCompleteCallbackDelegate()
{ {
if (cancellationToken.IsCancellationRequested)
{
if (this.cancelBehaviour == TweenCancelBehaviour.KillAndCancelAwait
|| this.cancelBehaviour == TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait
|| this.cancelBehaviour == TweenCancelBehaviour.CompleteAndCancelAwait
|| this.cancelBehaviour == TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait
|| this.cancelBehaviour == TweenCancelBehaviour.CancelAwait)
{
canceled = true;
}
}
if (canceled) if (canceled)
{ {
core.TrySetCanceled(cancellationToken); core.TrySetCanceled(cancellationToken);

View File

@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.Internal
readonly PlayerLoopTiming timing; readonly PlayerLoopTiming timing;
SpinLock gate = new SpinLock(); SpinLock gate = new SpinLock(false);
bool dequing = false; bool dequing = false;
int actionListCount = 0; int actionListCount = 0;
@@ -70,13 +70,17 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
public void Clear() public int Clear()
{ {
var rest = actionListCount + waitingListCount;
actionListCount = 0; actionListCount = 0;
actionList = new Action[InitialSize]; actionList = new Action[InitialSize];
waitingListCount = 0; waitingListCount = 0;
waitingList = new Action[InitialSize]; waitingList = new Action[InitialSize];
return rest;
} }
// delegate entrypoint. // delegate entrypoint.
@@ -128,6 +132,14 @@ namespace Cysharp.Threading.Tasks.Internal
case PlayerLoopTiming.LastPostLateUpdate: case PlayerLoopTiming.LastPostLateUpdate:
LastPostLateUpdate(); LastPostLateUpdate();
break; break;
#if UNITY_2020_2_OR_NEWER
case PlayerLoopTiming.TimeUpdate:
TimeUpdate();
break;
case PlayerLoopTiming.LastTimeUpdate:
LastTimeUpdate();
break;
#endif
default: default:
break; break;
} }
@@ -150,6 +162,10 @@ namespace Cysharp.Threading.Tasks.Internal
void LastPreLateUpdate() => RunCore(); void LastPreLateUpdate() => RunCore();
void PostLateUpdate() => RunCore(); void PostLateUpdate() => RunCore();
void LastPostLateUpdate() => RunCore(); void LastPostLateUpdate() => RunCore();
#if UNITY_2020_2_OR_NEWER
void TimeUpdate() => RunCore();
void LastTimeUpdate() => RunCore();
#endif
[System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerHidden]
void RunCore() void RunCore()

View File

@@ -48,14 +48,24 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
public void Clear() public int Clear()
{ {
lock (arrayLock) lock (arrayLock)
{ {
var rest = 0;
for (var index = 0; index < loopItems.Length; index++) for (var index = 0; index < loopItems.Length; index++)
{ {
if (loopItems[index] != null)
{
rest++;
}
loopItems[index] = null; loopItems[index] = null;
} }
tail = 0;
return rest;
} }
} }
@@ -108,6 +118,14 @@ namespace Cysharp.Threading.Tasks.Internal
case PlayerLoopTiming.LastPostLateUpdate: case PlayerLoopTiming.LastPostLateUpdate:
LastPostLateUpdate(); LastPostLateUpdate();
break; break;
#if UNITY_2020_2_OR_NEWER
case PlayerLoopTiming.TimeUpdate:
TimeUpdate();
break;
case PlayerLoopTiming.LastTimeUpdate:
LastTimeUpdate();
break;
#endif
default: default:
break; break;
} }
@@ -130,6 +148,10 @@ namespace Cysharp.Threading.Tasks.Internal
void LastPreLateUpdate() => RunCore(); void LastPreLateUpdate() => RunCore();
void PostLateUpdate() => RunCore(); void PostLateUpdate() => RunCore();
void LastPostLateUpdate() => RunCore(); void LastPostLateUpdate() => RunCore();
#if UNITY_2020_2_OR_NEWER
void TimeUpdate() => RunCore();
void LastTimeUpdate() => RunCore();
#endif
[System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerHidden]
void RunCore() void RunCore()
@@ -143,8 +165,6 @@ namespace Cysharp.Threading.Tasks.Internal
{ {
var j = tail - 1; var j = tail - 1;
var loopItems = this.loopItems;
// eliminate array-bound check for i
for (int i = 0; i < loopItems.Length; i++) for (int i = 0; i < loopItems.Length; i++)
{ {
var action = loopItems[i]; var action = loopItems[i];

View File

@@ -18,6 +18,8 @@ namespace Cysharp.Threading.Tasks.Internal
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks); public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
public bool IsInvalid => startTimestamp == 0;
public long ElapsedTicks public long ElapsedTicks
{ {
get get

View File

@@ -8,8 +8,10 @@ using System.Threading;
#if UNITY_2019_3_OR_NEWER #if UNITY_2019_3_OR_NEWER
using UnityEngine.LowLevel; using UnityEngine.LowLevel;
using PlayerLoopType = UnityEngine.PlayerLoop;
#else #else
using UnityEngine.Experimental.LowLevel; using UnityEngine.Experimental.LowLevel;
using PlayerLoopType = UnityEngine.Experimental.PlayerLoop;
#endif #endif
#if UNITY_EDITOR #if UNITY_EDITOR
@@ -57,6 +59,13 @@ namespace Cysharp.Threading.Tasks
public struct UniTaskLoopRunnerLastYieldUpdate { }; public struct UniTaskLoopRunnerLastYieldUpdate { };
public struct UniTaskLoopRunnerLastYieldPreLateUpdate { }; public struct UniTaskLoopRunnerLastYieldPreLateUpdate { };
public struct UniTaskLoopRunnerLastYieldPostLateUpdate { }; public struct UniTaskLoopRunnerLastYieldPostLateUpdate { };
#if UNITY_2020_2_OR_NEWER
public struct UniTaskLoopRunnerTimeUpdate { };
public struct UniTaskLoopRunnerLastTimeUpdate { };
public struct UniTaskLoopRunnerYieldTimeUpdate { };
public struct UniTaskLoopRunnerLastYieldTimeUpdate { };
#endif
} }
public enum PlayerLoopTiming public enum PlayerLoopTiming
@@ -80,7 +89,13 @@ namespace Cysharp.Threading.Tasks
LastPreLateUpdate = 11, LastPreLateUpdate = 11,
PostLateUpdate = 12, PostLateUpdate = 12,
LastPostLateUpdate = 13 LastPostLateUpdate = 13,
#if UNITY_2020_2_OR_NEWER
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html
TimeUpdate = 14,
LastTimeUpdate = 15,
#endif
} }
public interface IPlayerLoopItem public interface IPlayerLoopItem
@@ -101,7 +116,7 @@ namespace Cysharp.Threading.Tasks
static SynchronizationContext unitySynchronizationContetext; static SynchronizationContext unitySynchronizationContetext;
static ContinuationQueue[] yielders; static ContinuationQueue[] yielders;
static PlayerLoopRunner[] runners; static PlayerLoopRunner[] runners;
internal static bool IsEditorApplicationQuitting { get; private set; }
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem, static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem,
Type loopRunnerYieldType, ContinuationQueue cq, Type lastLoopRunnerYieldType, ContinuationQueue lastCq, Type loopRunnerYieldType, ContinuationQueue cq, Type lastLoopRunnerYieldType, ContinuationQueue lastCq,
Type loopRunnerType, PlayerLoopRunner runner, Type lastLoopRunnerType, PlayerLoopRunner lastRunner) Type loopRunnerType, PlayerLoopRunner runner, Type lastLoopRunnerType, PlayerLoopRunner lastRunner)
@@ -110,27 +125,32 @@ namespace Cysharp.Threading.Tasks
#if UNITY_EDITOR #if UNITY_EDITOR
EditorApplication.playModeStateChanged += (state) => EditorApplication.playModeStateChanged += (state) =>
{ {
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode) if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode)
{ {
return; IsEditorApplicationQuitting = true;
} // run rest action before clear.
if (runner != null)
{
runner.Run();
runner.Clear();
}
if (lastRunner != null)
{
lastRunner.Run();
lastRunner.Clear();
}
if (runner != null) if (cq != null)
{ {
runner.Clear(); cq.Run();
} cq.Clear();
if (lastRunner != null) }
{ if (lastCq != null)
lastRunner.Clear(); {
} lastCq.Run();
lastCq.Clear();
if (cq != null) }
{ IsEditorApplicationQuitting = false;
cq.Clear();
}
if (lastCq != null)
{
lastCq.Clear();
} }
}; };
#endif #endif
@@ -278,51 +298,84 @@ namespace Cysharp.Threading.Tasks
#endif #endif
private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType)
{
for (int i = 0; i < playerLoopList.Length; i++)
{
if (playerLoopList[i].type == systemType)
{
return i;
}
}
throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName);
}
public static void Initialize(ref PlayerLoopSystem playerLoop) public static void Initialize(ref PlayerLoopSystem playerLoop)
{ {
#if UNITY_2020_2_OR_NEWER
yielders = new ContinuationQueue[16];
runners = new PlayerLoopRunner[16];
#else
yielders = new ContinuationQueue[14]; yielders = new ContinuationQueue[14];
runners = new PlayerLoopRunner[14]; runners = new PlayerLoopRunner[14];
#endif
var copyList = playerLoop.subSystemList.ToArray(); var copyList = playerLoop.subSystemList.ToArray();
// Initialization var i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Initialization));
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(PlayerLoopTiming.Initialization), copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(PlayerLoopTiming.Initialization),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(PlayerLoopTiming.LastInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(PlayerLoopTiming.LastInitialization),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[0] = new PlayerLoopRunner(PlayerLoopTiming.Initialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[0] = new PlayerLoopRunner(PlayerLoopTiming.Initialization),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.LastInitialization)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.LastInitialization));
// EarlyUpdate // EarlyUpdate
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(PlayerLoopTiming.EarlyUpdate), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.EarlyUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(PlayerLoopTiming.EarlyUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), yielders[3] = new ContinuationQueue(PlayerLoopTiming.LastEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), yielders[3] = new ContinuationQueue(PlayerLoopTiming.LastEarlyUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[2] = new PlayerLoopRunner(PlayerLoopTiming.EarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[2] = new PlayerLoopRunner(PlayerLoopTiming.EarlyUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), runners[3] = new PlayerLoopRunner(PlayerLoopTiming.LastEarlyUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), runners[3] = new PlayerLoopRunner(PlayerLoopTiming.LastEarlyUpdate));
// FixedUpdate // FixedUpdate
copyList[2].subSystemList = InsertRunner(copyList[2], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[4] = new ContinuationQueue(PlayerLoopTiming.FixedUpdate), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.FixedUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[4] = new ContinuationQueue(PlayerLoopTiming.FixedUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), yielders[5] = new ContinuationQueue(PlayerLoopTiming.LastFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), yielders[5] = new ContinuationQueue(PlayerLoopTiming.LastFixedUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[4] = new PlayerLoopRunner(PlayerLoopTiming.FixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[4] = new PlayerLoopRunner(PlayerLoopTiming.FixedUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), runners[5] = new PlayerLoopRunner(PlayerLoopTiming.LastFixedUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), runners[5] = new PlayerLoopRunner(PlayerLoopTiming.LastFixedUpdate));
// PreUpdate // PreUpdate
copyList[3].subSystemList = InsertRunner(copyList[3], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[6] = new ContinuationQueue(PlayerLoopTiming.PreUpdate), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.PreUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[6] = new ContinuationQueue(PlayerLoopTiming.PreUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), yielders[7] = new ContinuationQueue(PlayerLoopTiming.LastPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), yielders[7] = new ContinuationQueue(PlayerLoopTiming.LastPreUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[6] = new PlayerLoopRunner(PlayerLoopTiming.PreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[6] = new PlayerLoopRunner(PlayerLoopTiming.PreUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), runners[7] = new PlayerLoopRunner(PlayerLoopTiming.LastPreUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), runners[7] = new PlayerLoopRunner(PlayerLoopTiming.LastPreUpdate));
// Update // Update
copyList[4].subSystemList = InsertRunner(copyList[4], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[8] = new ContinuationQueue(PlayerLoopTiming.Update), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Update));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[8] = new ContinuationQueue(PlayerLoopTiming.Update),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), yielders[9] = new ContinuationQueue(PlayerLoopTiming.LastUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), yielders[9] = new ContinuationQueue(PlayerLoopTiming.LastUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[8] = new PlayerLoopRunner(PlayerLoopTiming.Update), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[8] = new PlayerLoopRunner(PlayerLoopTiming.Update),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), runners[9] = new PlayerLoopRunner(PlayerLoopTiming.LastUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), runners[9] = new PlayerLoopRunner(PlayerLoopTiming.LastUpdate));
// PreLateUpdate // PreLateUpdate
copyList[5].subSystemList = InsertRunner(copyList[5], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[10] = new ContinuationQueue(PlayerLoopTiming.PreLateUpdate), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.PreLateUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[10] = new ContinuationQueue(PlayerLoopTiming.PreLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), yielders[11] = new ContinuationQueue(PlayerLoopTiming.LastPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), yielders[11] = new ContinuationQueue(PlayerLoopTiming.LastPreLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[10] = new PlayerLoopRunner(PlayerLoopTiming.PreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[10] = new PlayerLoopRunner(PlayerLoopTiming.PreLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), runners[11] = new PlayerLoopRunner(PlayerLoopTiming.LastPreLateUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), runners[11] = new PlayerLoopRunner(PlayerLoopTiming.LastPreLateUpdate));
// PostLateUpdate // PostLateUpdate
copyList[6].subSystemList = InsertRunner(copyList[6], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[12] = new ContinuationQueue(PlayerLoopTiming.PostLateUpdate), i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.PostLateUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[12] = new ContinuationQueue(PlayerLoopTiming.PostLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), yielders[13] = new ContinuationQueue(PlayerLoopTiming.LastPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), yielders[13] = new ContinuationQueue(PlayerLoopTiming.LastPostLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(PlayerLoopTiming.PostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(PlayerLoopTiming.PostLateUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner(PlayerLoopTiming.LastPostLateUpdate)); typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner(PlayerLoopTiming.LastPostLateUpdate));
#if UNITY_2020_2_OR_NEWER
// TimeUpdate
i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.TimeUpdate));
copyList[i].subSystemList = InsertRunner(copyList[i], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), yielders[14] = new ContinuationQueue(PlayerLoopTiming.TimeUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), yielders[15] = new ContinuationQueue(PlayerLoopTiming.LastTimeUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), runners[14] = new PlayerLoopRunner(PlayerLoopTiming.TimeUpdate),
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), runners[15] = new PlayerLoopRunner(PlayerLoopTiming.LastTimeUpdate));
#endif
// Insert UniTaskSynchronizationContext to Update loop // Insert UniTaskSynchronizationContext to Update loop
copyList[4].subSystemList = InsertUniTaskSynchronizationContext(copyList[4]); i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Update));
copyList[i].subSystemList = InsertUniTaskSynchronizationContext(copyList[i]);
playerLoop.subSystemList = copyList; playerLoop.subSystemList = copyList;
PlayerLoop.SetPlayerLoop(playerLoop); PlayerLoop.SetPlayerLoop(playerLoop);

View File

@@ -12,7 +12,9 @@ namespace Cysharp.Threading.Tasks
public static class TaskPool public static class TaskPool
{ {
internal static int MaxPoolSize; internal static int MaxPoolSize;
static ConcurrentDictionary<Type, Func<int>> sizes = new ConcurrentDictionary<Type, Func<int>>();
// avoid to use ConcurrentDictionary for safety of WebGL build.
static Dictionary<Type, Func<int>> sizes = new Dictionary<Type, Func<int>>();
static TaskPool() static TaskPool()
{ {
@@ -40,19 +42,24 @@ namespace Cysharp.Threading.Tasks
public static IEnumerable<(Type, int)> GetCacheSizeInfo() public static IEnumerable<(Type, int)> GetCacheSizeInfo()
{ {
foreach (var item in sizes) lock (sizes)
{ {
yield return (item.Key, item.Value()); foreach (var item in sizes)
{
yield return (item.Key, item.Value());
}
} }
} }
public static void RegisterSizeGetter(Type type, Func<int> getSize) public static void RegisterSizeGetter(Type type, Func<int> getSize)
{ {
sizes[type] = getSize; lock (sizes)
{
sizes[type] = getSize;
}
} }
} }
public interface ITaskPoolNode<T> public interface ITaskPoolNode<T>
{ {
ref T NextNode { get; } ref T NextNode { get; }

View File

@@ -1541,6 +1541,7 @@ namespace Cysharp.Threading.Tasks.Triggers
#endregion #endregion
#region MouseDown #region MouseDown
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseDownHandler public interface IAsyncOnMouseDownHandler
{ {
@@ -1597,9 +1598,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseDownHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDownAsync(); return ((IAsyncOnMouseDownHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDownAsync();
} }
} }
#endif
#endregion #endregion
#region MouseDrag #region MouseDrag
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseDragHandler public interface IAsyncOnMouseDragHandler
{ {
@@ -1656,9 +1659,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseDragHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDragAsync(); return ((IAsyncOnMouseDragHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDragAsync();
} }
} }
#endif
#endregion #endregion
#region MouseEnter #region MouseEnter
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseEnterHandler public interface IAsyncOnMouseEnterHandler
{ {
@@ -1715,9 +1720,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseEnterHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseEnterAsync(); return ((IAsyncOnMouseEnterHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseEnterAsync();
} }
} }
#endif
#endregion #endregion
#region MouseExit #region MouseExit
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseExitHandler public interface IAsyncOnMouseExitHandler
{ {
@@ -1774,9 +1781,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseExitHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseExitAsync(); return ((IAsyncOnMouseExitHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseExitAsync();
} }
} }
#endif
#endregion #endregion
#region MouseOver #region MouseOver
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseOverHandler public interface IAsyncOnMouseOverHandler
{ {
@@ -1833,9 +1842,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseOverHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseOverAsync(); return ((IAsyncOnMouseOverHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseOverAsync();
} }
} }
#endif
#endregion #endregion
#region MouseUp #region MouseUp
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseUpHandler public interface IAsyncOnMouseUpHandler
{ {
@@ -1892,9 +1903,11 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseUpHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsync(); return ((IAsyncOnMouseUpHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsync();
} }
} }
#endif
#endregion #endregion
#region MouseUpAsButton #region MouseUpAsButton
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
public interface IAsyncOnMouseUpAsButtonHandler public interface IAsyncOnMouseUpAsButtonHandler
{ {
@@ -1951,6 +1964,7 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((IAsyncOnMouseUpAsButtonHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsButtonAsync(); return ((IAsyncOnMouseUpAsButtonHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsButtonAsync();
} }
} }
#endif
#endregion #endregion
#region ParticleCollision #region ParticleCollision

View File

@@ -25,13 +25,7 @@
("Update", "Update", "AsyncUnit", null, empty), ("Update", "Update", "AsyncUnit", null, empty),
("FixedUpdate", "FixedUpdate", "AsyncUnit", null, empty), ("FixedUpdate", "FixedUpdate", "AsyncUnit", null, empty),
("LateUpdate", "LateUpdate", "AsyncUnit", null, empty), ("LateUpdate", "LateUpdate", "AsyncUnit", null, empty),
("MouseDown", "OnMouseDown", "AsyncUnit", null, empty),
("MouseDrag", "OnMouseDrag", "AsyncUnit", null, empty),
("MouseEnter", "OnMouseEnter", "AsyncUnit", null, empty),
("MouseExit", "OnMouseExit", "AsyncUnit", null, empty),
("MouseOver", "OnMouseOver", "AsyncUnit", null, empty),
("MouseUp", "OnMouseUp", "AsyncUnit", null, empty),
("MouseUpAsButton", "OnMouseUpAsButton", "AsyncUnit", null, empty),
("ParticleCollision", "OnParticleCollision", "GameObject", null, new []{ ("GameObject", "other") }), ("ParticleCollision", "OnParticleCollision", "GameObject", null, new []{ ("GameObject", "other") }),
("RectTransformDimensionsChange", "OnRectTransformDimensionsChange", "AsyncUnit", null, empty), ("RectTransformDimensionsChange", "OnRectTransformDimensionsChange", "AsyncUnit", null, empty),
("RectTransformRemoved", "OnRectTransformRemoved", "AsyncUnit", null, empty), ("RectTransformRemoved", "OnRectTransformRemoved", "AsyncUnit", null, empty),
@@ -47,6 +41,15 @@
("BecameInvisible", "OnBecameInvisible", "AsyncUnit", null, empty), ("BecameInvisible", "OnBecameInvisible", "AsyncUnit", null, empty),
("BecameVisible", "OnBecameVisible", "AsyncUnit", null, empty), ("BecameVisible", "OnBecameVisible", "AsyncUnit", null, empty),
// Mouse... #if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
("MouseDown", "OnMouseDown", "AsyncUnit", null, empty),
("MouseDrag", "OnMouseDrag", "AsyncUnit", null, empty),
("MouseEnter", "OnMouseEnter", "AsyncUnit", null, empty),
("MouseExit", "OnMouseExit", "AsyncUnit", null, empty),
("MouseOver", "OnMouseOver", "AsyncUnit", null, empty),
("MouseUp", "OnMouseUp", "AsyncUnit", null, empty),
("MouseUpAsButton", "OnMouseUpAsButton", "AsyncUnit", null, empty),
// new in v2 // new in v2
("ApplicationFocus", "OnApplicationFocus", "bool", null, new []{("bool", "hasFocus") }), ("ApplicationFocus", "OnApplicationFocus", "bool", null, new []{("bool", "hasFocus") }),
("ApplicationPause", "OnApplicationPause", "bool", null, new []{("bool", "pauseStatus") }), ("ApplicationPause", "OnApplicationPause", "bool", null, new []{("bool", "pauseStatus") }),
@@ -104,6 +107,7 @@
Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")"; Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")";
Func<string, bool> Is2019_3 = x => x == "ParticleUpdateJobScheduled"; Func<string, bool> Is2019_3 = x => x == "ParticleUpdateJobScheduled";
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
#> #>
#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
@@ -117,6 +121,9 @@ namespace Cysharp.Threading.Tasks.Triggers
#region <#= t.triggerName #> #region <#= t.triggerName #>
<# if(Is2019_3(t.triggerName)) { #> <# if(Is2019_3(t.triggerName)) { #>
#if UNITY_2019_3_OR_NEWER #if UNITY_2019_3_OR_NEWER
<# } #>
<# if(IsMouseTrigger(t.triggerName)) { #>
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
<# } #> <# } #>
public interface <#= ToInterfaceName(t.methodName) #> public interface <#= ToInterfaceName(t.methodName) #>
@@ -174,7 +181,7 @@ namespace Cysharp.Threading.Tasks.Triggers
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async(); return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async();
} }
} }
<# if(Is2019_3(t.triggerName)) { #> <# if(Is2019_3(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
#endif #endif
<# } #> <# } #>
#endregion #endregion

View File

@@ -726,6 +726,12 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
if (stopwatch.IsInvalid)
{
core.TrySetResult(AsyncUnit.Default);
return false;
}
if (stopwatch.ElapsedTicks >= delayTimeSpanTicks) if (stopwatch.ElapsedTicks >= delayTimeSpanTicks)
{ {
core.TrySetResult(AsyncUnit.Default); core.TrySetResult(AsyncUnit.Default);

View File

@@ -341,10 +341,12 @@ namespace Cysharp.Threading.Tasks
public UniTaskStatus GetStatus(short token) public UniTaskStatus GetStatus(short token)
{ {
var f = Interlocked.Exchange(ref factory, null); var f = Interlocked.Exchange(ref factory, null);
if (f == null) throw new InvalidOperationException("Can't call twice."); if (f != null)
{
task = f();
awaiter = task.GetAwaiter();
}
task = f();
awaiter = task.GetAwaiter();
return task.Status; return task.Status;
} }
@@ -383,10 +385,12 @@ namespace Cysharp.Threading.Tasks
public UniTaskStatus GetStatus(short token) public UniTaskStatus GetStatus(short token)
{ {
var f = Interlocked.Exchange(ref factory, null); var f = Interlocked.Exchange(ref factory, null);
if (f == null) throw new InvalidOperationException("Can't call twice."); if (f != null)
{
task = f();
awaiter = task.GetAwaiter();
}
task = f();
awaiter = task.GetAwaiter();
return task.Status; return task.Status;
} }

View File

@@ -11,7 +11,7 @@ namespace Cysharp.Threading.Tasks
// Run is a confusing name, use only RunOnThreadPool in the future. // Run is a confusing name, use only RunOnThreadPool in the future.
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask Run(Action action, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask Run(Action action, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -39,7 +39,7 @@ namespace Cysharp.Threading.Tasks
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask Run(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask Run(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -67,7 +67,7 @@ namespace Cysharp.Threading.Tasks
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask Run(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask Run(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -95,7 +95,7 @@ namespace Cysharp.Threading.Tasks
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask Run(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask Run(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -123,7 +123,7 @@ namespace Cysharp.Threading.Tasks
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask<T> Run<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask<T> Run<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -150,7 +150,7 @@ namespace Cysharp.Threading.Tasks
} }
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask<T> Run<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask<T> Run<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -180,7 +180,7 @@ namespace Cysharp.Threading.Tasks
} }
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -207,7 +207,7 @@ namespace Cysharp.Threading.Tasks
} }
} }
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary> /// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
public static async UniTask<T> Run<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default) public static async UniTask<T> Run<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();

View File

@@ -115,8 +115,13 @@ namespace Cysharp.Threading.Tasks
var status = this.source.GetStatus(this.token); var status = this.source.GetStatus(this.token);
if (status.IsCompletedSuccessfully()) if (status.IsCompletedSuccessfully())
{ {
this.source.GetResult(this.token);
return CompletedTasks.AsyncUnit; return CompletedTasks.AsyncUnit;
} }
else if(this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
{
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
}
return new UniTask<AsyncUnit>(new AsyncUnitSource(this.source), this.token); return new UniTask<AsyncUnit>(new AsyncUnitSource(this.source), this.token);
} }
@@ -422,6 +427,7 @@ namespace Cysharp.Threading.Tasks
var status = this.source.GetStatus(this.token); var status = this.source.GetStatus(this.token);
if (status.IsCompletedSuccessfully()) if (status.IsCompletedSuccessfully())
{ {
this.source.GetResult(this.token);
return UniTask.CompletedTask; return UniTask.CompletedTask;
} }

View File

@@ -561,21 +561,23 @@ namespace Cysharp.Threading.Tasks
UniTaskScheduler.PublishUnobservedTaskException(ex); UniTaskScheduler.PublishUnobservedTaskException(ex);
} }
} }
else
awaiter.SourceOnCompleted(state =>
{ {
using (var t = (StateTuple<UniTask.Awaiter>)state) awaiter.SourceOnCompleted(state =>
{ {
try using (var t = (StateTuple<UniTask.Awaiter>)state)
{ {
t.Item1.GetResult(); try
{
t.Item1.GetResult();
}
catch (Exception ex)
{
UniTaskScheduler.PublishUnobservedTaskException(ex);
}
} }
catch (Exception ex) }, StateTuple.Create(awaiter));
{ }
UniTaskScheduler.PublishUnobservedTaskException(ex);
}
}
}, StateTuple.Create(awaiter));
} }
public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true) public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
@@ -629,21 +631,23 @@ namespace Cysharp.Threading.Tasks
UniTaskScheduler.PublishUnobservedTaskException(ex); UniTaskScheduler.PublishUnobservedTaskException(ex);
} }
} }
else
awaiter.SourceOnCompleted(state =>
{ {
using (var t = (StateTuple<UniTask<T>.Awaiter>)state) awaiter.SourceOnCompleted(state =>
{ {
try using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
{ {
t.Item1.GetResult(); try
{
t.Item1.GetResult();
}
catch (Exception ex)
{
UniTaskScheduler.PublishUnobservedTaskException(ex);
}
} }
catch (Exception ex) }, StateTuple.Create(awaiter));
{ }
UniTaskScheduler.PublishUnobservedTaskException(ex);
}
}
}, StateTuple.Create(awaiter));
} }
public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true) public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
@@ -732,31 +736,51 @@ namespace Cysharp.Threading.Tasks
return await await task; return await await task;
} }
public static async UniTask Unwrap<T>(this UniTask<UniTask> task) public static async UniTask Unwrap(this UniTask<UniTask> task)
{ {
await await task; await await task;
} }
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task) public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
{ {
return await await task; return await await task;
} }
public static async UniTask Unwrap<T>(this Task<UniTask> task) public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task, bool continueOnCapturedContext)
{
return await await task.ConfigureAwait(continueOnCapturedContext);
}
public static async UniTask Unwrap(this Task<UniTask> task)
{ {
await await task; await await task;
} }
public static async UniTask Unwrap(this Task<UniTask> task, bool continueOnCapturedContext)
{
await await task.ConfigureAwait(continueOnCapturedContext);
}
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task) public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task)
{ {
return await await task; return await await task;
} }
public static async UniTask Unwrap<T>(this UniTask<Task> task) public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task, bool continueOnCapturedContext)
{
return await (await task).ConfigureAwait(continueOnCapturedContext);
}
public static async UniTask Unwrap(this UniTask<Task> task)
{ {
await await task; await await task;
} }
public static async UniTask Unwrap(this UniTask<Task> task, bool continueOnCapturedContext)
{
await (await task).ConfigureAwait(continueOnCapturedContext);
}
#if UNITY_2018_3_OR_NEWER #if UNITY_2018_3_OR_NEWER
sealed class ToCoroutineEnumerator : IEnumerator sealed class ToCoroutineEnumerator : IEnumerator

View File

@@ -9,7 +9,7 @@ namespace Cysharp.Threading.Tasks
const int MaxArrayLength = 0X7FEFFFFF; const int MaxArrayLength = 0X7FEFFFFF;
const int InitialSize = 16; const int InitialSize = 16;
static SpinLock gate = new SpinLock(); static SpinLock gate = new SpinLock(false);
static bool dequing = false; static bool dequing = false;
static int actionListCount = 0; static int actionListCount = 0;

View File

@@ -46,6 +46,11 @@ namespace Cysharp.Threading.Tasks
this.continuationAction = null; this.continuationAction = null;
} }
public AssetBundleRequestAllAssetsAwaiter GetAwaiter()
{
return this;
}
public bool IsCompleted => asyncOperation.isDone; public bool IsCompleted => asyncOperation.isDone;
public UnityEngine.Object[] GetResult() public UnityEngine.Object[] GetResult()

View File

@@ -4,6 +4,7 @@
using System; using System;
using System.Threading; using System.Threading;
using Unity.Jobs; using Unity.Jobs;
using UnityEngine;
namespace Cysharp.Threading.Tasks namespace Cysharp.Threading.Tasks
{ {
@@ -85,7 +86,7 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext() public bool MoveNext()
{ {
if (jobHandle.IsCompleted) if (jobHandle.IsCompleted | PlayerLoopHelper.IsEditorApplicationQuitting)
{ {
jobHandle.Complete(); jobHandle.Complete();
core.TrySetResult(AsyncUnit.Default); core.TrySetResult(AsyncUnit.Default);

View File

@@ -1,6 +1,7 @@
#if ENABLE_UNITYWEBREQUEST #if ENABLE_UNITYWEBREQUEST
using System; using System;
using System.Collections.Generic;
using UnityEngine.Networking; using UnityEngine.Networking;
namespace Cysharp.Threading.Tasks namespace Cysharp.Threading.Tasks
@@ -17,6 +18,7 @@ namespace Cysharp.Threading.Tasks
public string Error { get; } public string Error { get; }
public string Text { get; } public string Text { get; }
public long ResponseCode { get; } public long ResponseCode { get; }
public Dictionary<string, string> ResponseHeaders { get; }
string msg; string msg;
@@ -38,6 +40,7 @@ namespace Cysharp.Threading.Tasks
this.Text = dhb.text; this.Text = dhb.text;
} }
} }
this.ResponseHeaders = unityWebRequest.GetResponseHeaders();
} }
public override string Message public override string Message

View File

@@ -1,7 +1,7 @@
{ {
"name": "com.cysharp.unitask", "name": "com.cysharp.unitask",
"displayName": "UniTask", "displayName": "UniTask",
"version": "2.0.32", "version": "2.1.0",
"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" ],

View File

@@ -0,0 +1,41 @@
#if UNITY_EDITOR
using System;
using Cysharp.Threading.Tasks;
using UnityEditor;
using UnityEngine;
public class Test1
{
[MenuItem("Test/Test1")]
public static async UniTaskVoid TestFunc()
{
await DoSomeThing();
string[] scenes = new string[]
{
"Assets/Scenes/SandboxMain.unity",
};
try
{
Debug.Log("Build Begin");
BuildPipeline.BuildPlayer(scenes, Application.dataPath + "../target", BuildTarget.StandaloneWindows, BuildOptions.CompressWithLz4);
Debug.Log("Build After");
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
public static async UniTask DoSomeThing()
{
Debug.Log("Dosomething");
await UniTask.Delay(1500, DelayType.Realtime);
Debug.Log("Dosomething 2");
await UniTask.Delay(1000, DelayType.Realtime);
Debug.Log("Dosomething 3");
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48003021292963e48b2493e915dca5ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,6 +2,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
// using UnityEngine.AddressableAssets;
/*UNniTastWhenAnyTester*/ /*UNniTastWhenAnyTester*/
@@ -49,4 +50,9 @@ public class ExceptionExamples : MonoBehaviour
await UniTask.Delay(100); await UniTask.Delay(100);
return taskIndex; return taskIndex;
} }
//void AddressablesTest()
//{
// Addressables.ClearDependencyCacheAsync("key", true);
//}
} }

View File

@@ -145,50 +145,50 @@ namespace Cysharp.Threading.Tasks.Sample
} }
} }
public class LoggingDecorator : IAsyncDecorator //public class LoggingDecorator : IAsyncDecorator
{ //{
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next) // public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
{ // {
var sw = Stopwatch.StartNew(); // var sw = Stopwatch.StartNew();
try // try
{ // {
UnityEngine.Debug.Log("Start Network Request:" + context.Path); // UnityEngine.Debug.Log("Start Network Request:" + context.Path);
var response = await next(context, cancellationToken); // var response = await next(context, cancellationToken);
UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}"); // UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}");
return response; // return response;
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
if (ex is OperationCanceledException) // if (ex is OperationCanceledException)
{ // {
UnityEngine.Debug.Log("Request Canceled:" + context.Path); // UnityEngine.Debug.Log("Request Canceled:" + context.Path);
} // }
else if (ex is TimeoutException) // else if (ex is TimeoutException)
{ // {
UnityEngine.Debug.Log("Request Timeout:" + context.Path); // UnityEngine.Debug.Log("Request Timeout:" + context.Path);
} // }
else if (ex is UnityWebRequestException webex) // else if (ex is UnityWebRequestException webex)
{ // {
if (webex.IsHttpError) // if (webex.IsHttpError)
{ // {
UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}"); // UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
} // }
else if (webex.IsNetworkError) // else if (webex.IsNetworkError)
{ // {
UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}"); // UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
} // }
} // }
throw; // throw;
} // }
finally // finally
{ // {
/* log other */ // /* log other */
} // }
} // }
} //}
public class SetupHeaderDecorator : IAsyncDecorator public class SetupHeaderDecorator : IAsyncDecorator
{ {

View File

@@ -428,15 +428,15 @@ public class SandboxMain : MonoBehaviour
Debug.Log("after"); Debug.Log("after");
} }
private async UniTaskVoid ExecuteAsync() //private async UniTaskVoid ExecuteAsync()
{ //{
var req = UnityWebRequest.Get("https://google.com/"); // var req = UnityWebRequest.Get("https://google.com/");
var v = await req.SendWebRequest().ToUniTask(); // var v = await req.SendWebRequest().ToUniTask();
// req.Dispose(); // // req.Dispose();
Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}"); // Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}");
Debug.Log(v.downloadHandler.text); // Debug.Log(v.downloadHandler.text);
} //}
private async void Go() private async void Go()
{ {
await UniTask.DelayFrame(0); await UniTask.DelayFrame(0);
@@ -493,8 +493,50 @@ public class SandboxMain : MonoBehaviour
} }
async UniTask QuitCheck()
{
try
{
await UniTask.Delay(TimeSpan.FromMinutes(1), cancellationToken: quitSource.Token);
}
finally
{
Debug.Log("End QuitCheck async");
}
}
CancellationTokenSource quitSource = new CancellationTokenSource();
IEnumerator TestCor()
{
Debug.Log("start cor");
yield return null;
yield return new WaitForEndOfFrame();
Debug.Log("end cor");
}
IEnumerator LastYieldCore()
{
Debug.Log("YieldBegin:" + Time.frameCount);
yield return new WaitForEndOfFrame();
Debug.Log("YieldEnd:" + Time.frameCount);
}
async UniTaskVoid Start() async UniTaskVoid Start()
{ {
await TestCor().ToUniTask(this);
Debug.Log("App Start");
Application.quitting += () =>
{
Debug.Log("called quitting");
quitSource.Cancel();
};
QuitCheck().Forget();
//Expression.Lambda<Func<int>>(null).Compile(true); //Expression.Lambda<Func<int>>(null).Compile(true);
//RunStandardTaskAsync(); //RunStandardTaskAsync();
@@ -532,17 +574,14 @@ public class SandboxMain : MonoBehaviour
okButton.onClick.AddListener(UniTask.UnityAction(async () => okButton.onClick.AddListener(UniTask.UnityAction(async () =>
{ {
StartCoroutine(LastYieldCore());
var client = new NetworkClient("http://localhost:5000", TimeSpan.FromSeconds(2), Debug.Log("BEFORE:" + Time.frameCount);
new QueueRequestDecorator(),
new LoggingDecorator());
//new AppendTokenDecorator(),
//new SetupHeaderDecorator());
await client.PostAsync("", new { Id = 100 });
await UniTask.Yield();
// await UniTask.Yield(PlayerLoopTiming.LastTimeUpdate);
Debug.Log("AFTER:" + Time.frameCount);
})); }));
// _ = ExecuteAsync(); // _ = ExecuteAsync();

View File

@@ -55,6 +55,8 @@ namespace Cysharp.Threading.TasksTests
} }
} }
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () => public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
{ {
@@ -76,6 +78,8 @@ namespace Cysharp.Threading.TasksTests
} }
}); });
#endif
[UnityTest] [UnityTest]
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () => public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
{ {
@@ -183,6 +187,8 @@ namespace Cysharp.Threading.TasksTests
diff.Should().Be(11); diff.Should().Be(11);
}); });
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () => public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
{ {
@@ -215,6 +221,8 @@ namespace Cysharp.Threading.TasksTests
currentThreadId.Should().Be(switchedThreadId2); currentThreadId.Should().Be(switchedThreadId2);
}); });
#endif
//[UnityTest] //[UnityTest]
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () => //public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
//{ //{

View File

@@ -96,6 +96,47 @@ namespace Cysharp.Threading.TasksTests
// l[1].Item2.Should().NotBe(currentFrame); // l[1].Item2.Should().NotBe(currentFrame);
//} //}
[UnityTest]
public IEnumerator ImmediateRunTest() => UniTask.ToCoroutine(async () =>
{
var l = new List<int>();
var x1 = Immediate(l);
var x2 = Immediate(l);
var x3 = DelayOne(l);
var t1 = x1.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3 });
await t1;
var t2 = x2.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3 });
var t3 = x3.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10 });
await UniTask.WhenAll(t2, t3);
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10, 20, 30 });
});
IEnumerator Immediate(List<int> l)
{
l.Add(1);
l.Add(2);
l.Add(3);
yield break;
}
IEnumerator DelayOne(List<int> l)
{
l.Add(10);
yield return null;
l.Add(20);
l.Add(30);
}
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () => public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
{ {
@@ -123,6 +164,8 @@ namespace Cysharp.Threading.TasksTests
yield return new WaitForSeconds(3.0f); yield return new WaitForSeconds(3.0f);
} }
#endif
IEnumerator Worker(List<(int, int)> l) IEnumerator Worker(List<(int, int)> l)
{ {
l.Add((0, Time.frameCount)); l.Add((0, Time.frameCount));

View File

@@ -175,6 +175,7 @@ namespace Cysharp.Threading.TasksTests
} }
}); });
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator DelayInThreadPool() => UniTask.ToCoroutine(async () => public IEnumerator DelayInThreadPool() => UniTask.ToCoroutine(async () =>
@@ -185,6 +186,8 @@ namespace Cysharp.Threading.TasksTests
}); });
}); });
#endif
[UnityTest] [UnityTest]
public IEnumerator DelayRealtime() => UniTask.ToCoroutine(async () => public IEnumerator DelayRealtime() => UniTask.ToCoroutine(async () =>
{ {
@@ -200,5 +203,16 @@ namespace Cysharp.Threading.TasksTests
okay1.Should().Be(true); okay1.Should().Be(true);
okay2.Should().Be(true); okay2.Should().Be(true);
}); });
[UnityTest]
public IEnumerator LoopTest() => UniTask.ToCoroutine(async () =>
{
for (int i = 0; i < 20; ++i)
{
UniTask.DelayFrame(100).Forget();
await UniTask.DelayFrame(1);
}
});
} }
} }

View File

@@ -37,6 +37,7 @@ namespace Cysharp.Threading.TasksTests
{ {
#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
#if !UNITY_WEBGL
//[UnityTest] //[UnityTest]
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () => //public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
@@ -88,7 +89,7 @@ namespace Cysharp.Threading.TasksTests
} }
}); });
#endif
#endif #endif
#endif #endif
} }

View File

@@ -0,0 +1,43 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_EnablePreviewPackages: 0
m_EnablePackageDependencies: 0
m_AdvancedSettingsExpanded: 1
m_ScopedRegistriesSettingsExpanded: 1
oneTimeWarningShown: 0
m_Registries:
- m_Id: main
m_Name:
m_Url: https://packages.unity.com
m_Scopes: []
m_IsDefault: 1
m_Capabilities: 7
m_UserSelectedRegistryName:
m_UserAddingNewScopedRegistry: 0
m_RegistryInfoDraft:
m_ErrorMessage:
m_Original:
m_Id:
m_Name:
m_Url:
m_Scopes: []
m_IsDefault: 0
m_Capabilities: 0
m_Modified: 0
m_Name:
m_Url:
m_Scopes:
-
m_SelectedScopeIndex: 0

View File

@@ -543,7 +543,7 @@ PlayerSettings:
platformArchitecture: {} platformArchitecture: {}
scriptingBackend: scriptingBackend:
Android: 1 Android: 1
Standalone: 0 Standalone: 1
il2cppCompilerConfiguration: {} il2cppCompilerConfiguration: {}
managedStrippingLevel: {} managedStrippingLevel: {}
incrementalIl2cppBuild: {} incrementalIl2cppBuild: {}

View File

@@ -1,2 +1,2 @@
m_EditorVersion: 2019.4.5f1 m_EditorVersion: 2020.2.1f1
m_EditorVersionWithRevision: 2019.4.5f1 (81610f64359c) m_EditorVersionWithRevision: 2020.2.1f1 (270dd8c3da1c)

View File

@@ -0,0 +1,8 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!890905787 &1
VersionControlSettings:
m_ObjectHideFlags: 0
m_Mode: Visible Meta Files
m_CollabEditorSettings:
inProgressEnabled: 1

View File

@@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!162 &1
EditorUserSettings:
m_ObjectHideFlags: 0
serializedVersion: 4
m_ConfigSettings:
vcSharedLogLevel:
value: 0d5e400f0650
flags: 0
m_VCAutomaticAdd: 1
m_VCDebugCom: 0
m_VCDebugCmd: 0
m_VCDebugOut: 0
m_SemanticMergeMode: 2
m_VCShowFailedCheckout: 1
m_VCOverwriteFailedCheckoutAssets: 1
m_VCOverlayIcons: 1
m_VCAllowAsyncUpdate: 0