mirror of https://github.com/Cysharp/UniTask
Compare commits
No commits in common. "master" and "2.0.31" have entirely different histories.
|
@ -1 +0,0 @@
|
||||||
github: [neuecc]
|
|
|
@ -1,12 +0,0 @@
|
||||||
# ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly" # Check for updates to GitHub Actions every week
|
|
||||||
ignore:
|
|
||||||
# I just want update action when major/minor version is updated. patch updates are too noisy.
|
|
||||||
- dependency-name: '*'
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-patch
|
|
|
@ -3,86 +3,65 @@ name: Build-Debug
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "master"
|
- "**"
|
||||||
|
tags:
|
||||||
|
- "!*" # not a tag push
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
types:
|
||||||
- "master"
|
- opened
|
||||||
|
- synchronize
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-dotnet:
|
build-dotnet:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
env:
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
|
NUGET_XMLDOC_MODE: skip
|
||||||
steps:
|
steps:
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
- uses: actions/checkout@v2
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
- uses: actions/setup-dotnet@v1
|
||||||
- run: dotnet build -c Debug
|
with:
|
||||||
- run: dotnet test -c Debug
|
dotnet-version: 3.1.101
|
||||||
|
- run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
if: ${{ ((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:')) && github.triggering_actor != 'dependabot[bot]' }}
|
if: "(github.event == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:')"
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
max-parallel: 2
|
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2022.3.39f1", "6000.0.12f1"] # Test with LTS
|
unity: ["2019.3.9f1", "2020.1.0b5"]
|
||||||
|
include:
|
||||||
|
- unity: 2019.3.9f1
|
||||||
|
license: UNITY_2019_3
|
||||||
|
- unity: 2020.1.0b5
|
||||||
|
license: UNITY_2020_1
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30 # Unity build takes more than 20min.
|
container:
|
||||||
|
# with linux-il2cpp. image from https://hub.docker.com/r/gableroux/unity3d/tags
|
||||||
|
image: gableroux/unity3d:${{ matrix.unity }}-linux-il2cpp
|
||||||
steps:
|
steps:
|
||||||
- name: Load secrets
|
- run: apt update && apt install git -y
|
||||||
id: op-load-secret
|
- uses: actions/checkout@v2
|
||||||
uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0
|
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
||||||
with:
|
|
||||||
export-env: false
|
|
||||||
env:
|
env:
|
||||||
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }}
|
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||||
UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username"
|
- name: Activate Unity, always returns a success. But if a subsequent run fails, the activation may have failed(if succeeded, shows `Next license update check is after` and not shows other message(like GUID != GUID). If fails not). In that case, upload the artifact's .alf file to https://license.unity3d.com/manual to get the .ulf file and set it to secrets.
|
||||||
UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential"
|
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0
|
||||||
UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial"
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
# Execute scripts: RuntimeUnitTestToolkit
|
||||||
|
- name: Build UnitTest(Linux64, mono)
|
||||||
|
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
||||||
|
working-directory: src/UniTask
|
||||||
|
- name: Execute UnitTest
|
||||||
|
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
||||||
|
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
- name: Export unitypackage
|
||||||
- name: Build Unity (.unitypacakge)
|
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
if: ${{ startsWith(matrix.unity, '2022') }} # only execute once
|
working-directory: src/UniTask
|
||||||
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
|
||||||
env:
|
|
||||||
UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }}
|
|
||||||
UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }}
|
|
||||||
UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }}
|
|
||||||
with:
|
|
||||||
projectPath: src/UniTask
|
|
||||||
unityVersion: ${{ matrix.unity }}
|
|
||||||
targetPlatform: StandaloneLinux64
|
|
||||||
buildMethod: PackageExporter.Export
|
|
||||||
|
|
||||||
# Execute UnitTest
|
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend IL2CPP /BuildTarget StandaloneLinux64
|
|
||||||
- name: Build UnitTest (IL2CPP)
|
|
||||||
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
|
||||||
env:
|
|
||||||
UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }}
|
|
||||||
UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }}
|
|
||||||
UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }}
|
|
||||||
with:
|
|
||||||
projectPath: src/UniTask
|
|
||||||
unityVersion: ${{ matrix.unity }}
|
|
||||||
targetPlatform: StandaloneLinux64
|
|
||||||
buildMethod: UnitTestBuilder.BuildUnitTest
|
|
||||||
customParameters: "/headless /ScriptBackend IL2CPP"
|
|
||||||
- name: Check UnitTest file is generated
|
|
||||||
run: ls -lR ./src/UniTask/bin/UnitTest
|
|
||||||
- name: Execute UnitTest
|
|
||||||
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_IL2CPP/test
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
|
||||||
with:
|
|
||||||
directory: src/UniTask
|
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
- uses: actions/upload-artifact@v2
|
||||||
if: ${{ startsWith(matrix.unity, '2021') }} # only execute 2021
|
|
||||||
with:
|
with:
|
||||||
name: UniTask.unitypackage-${{ matrix.unity }}.zip
|
name: UniTask.unitypackage.zip
|
||||||
path: ./src/UniTask/*.unitypackage
|
path: ./src/UniTask/*.unitypackage
|
||||||
retention-days: 1
|
|
||||||
|
|
|
@ -8,24 +8,24 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-docfx:
|
run-docfx:
|
||||||
|
if: "!(contains(github.event.head_commit.message, '[skip ci]') || contains(github.event.head_commit.message, '[ci skip]'))"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
steps:
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
- uses: actions/checkout@v2
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
repository: Cysharp/DocfxTemplate
|
repository: Cysharp/DocfxTemplate
|
||||||
path: docs/_DocfxTemplate
|
path: docs/_DocfxTemplate
|
||||||
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
- uses: Kirbyrawr/docfx-action@master
|
||||||
name: Docfx metadata
|
name: Docfx metadata
|
||||||
with:
|
with:
|
||||||
args: metadata docs/docfx.json
|
args: metadata docs/docfx.json
|
||||||
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
- uses: Kirbyrawr/docfx-action@master
|
||||||
name: Docfx build
|
name: Docfx build
|
||||||
with:
|
with:
|
||||||
args: build docs/docfx.json
|
args: build docs/docfx.json
|
||||||
- name: Publish to GitHub Pages
|
- name: Publish to GitHub Pages
|
||||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: docs/_site
|
publish_dir: docs/_site
|
|
@ -1,110 +1,105 @@
|
||||||
name: build-release
|
name: Build-Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
push:
|
||||||
inputs:
|
tags:
|
||||||
tag:
|
- "[0-9]+.[0-9]+.[0-9]+*"
|
||||||
description: "tag: git tag you want create. (sample 1.0.0)"
|
|
||||||
required: true
|
|
||||||
dry-run:
|
|
||||||
description: "dry-run: true will never create relase/nuget."
|
|
||||||
required: true
|
|
||||||
default: false
|
|
||||||
type: boolean
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-packagejson:
|
|
||||||
uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
|
|
||||||
with:
|
|
||||||
file-path: ./src/UniTask/Assets/Plugins/UniTask/package.json
|
|
||||||
tag: ${{ inputs.tag }}
|
|
||||||
dry-run: ${{ inputs.dry-run }}
|
|
||||||
|
|
||||||
build-dotnet:
|
build-dotnet:
|
||||||
needs: [update-packagejson]
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
env:
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
|
NUGET_XMLDOC_MODE: skip
|
||||||
steps:
|
steps:
|
||||||
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
- uses: actions/checkout@v2
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
dotnet-version: 3.1.101
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
# set release tag(*.*.*) to env.GIT_TAG
|
||||||
|
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
||||||
|
|
||||||
# build and pack
|
# build and pack
|
||||||
- run: dotnet build -c Release -p:Version=${{ inputs.tag }}
|
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
|
||||||
- run: dotnet test -c Release --no-build
|
- run: dotnet test -c Release --no-build
|
||||||
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ inputs.tag }} -o ./publish
|
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ env.GIT_TAG }}
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
- uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: nuget
|
name: nuget
|
||||||
path: ./publish/
|
path: ./src/UniTask.NetCore/bin/Release/UniTask.${{ env.GIT_TAG }}.nupkg
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
needs: [update-packagejson]
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2022.3.39f1"]
|
unity: ['2019.3.9f1']
|
||||||
|
include:
|
||||||
|
- unity: 2019.3.9f1
|
||||||
|
license: UNITY_2019_3
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
container:
|
||||||
|
# with linux-il2cpp. image from https://hub.docker.com/r/gableroux/unity3d/tags
|
||||||
|
image: gableroux/unity3d:${{ matrix.unity }}-linux-il2cpp
|
||||||
steps:
|
steps:
|
||||||
- name: Load secrets
|
- run: apt update && apt install git -y
|
||||||
id: op-load-secret
|
- uses: actions/checkout@v2
|
||||||
uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0
|
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
||||||
with:
|
|
||||||
export-env: false
|
|
||||||
env:
|
env:
|
||||||
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }}
|
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||||
UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username"
|
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0
|
||||||
UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential"
|
|
||||||
UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial"
|
# set release tag(*.*.*) to env.GIT_TAG
|
||||||
|
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
||||||
|
|
||||||
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
|
||||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
|
||||||
with:
|
|
||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
- name: Export unitypackage
|
||||||
- name: Build Unity (.unitypacakge)
|
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
working-directory: src/UniTask
|
||||||
env:
|
|
||||||
UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }}
|
|
||||||
UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }}
|
|
||||||
UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }}
|
|
||||||
with:
|
|
||||||
projectPath: src/UniTask
|
|
||||||
unityVersion: ${{ matrix.unity }}
|
|
||||||
targetPlatform: StandaloneLinux64
|
|
||||||
buildMethod: PackageExporter.Export
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
|
||||||
with:
|
|
||||||
directory: src/UniTask
|
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: UniTask.${{ inputs.tag }}.unitypackage
|
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
path: ./src/UniTask/UniTask.${{ inputs.tag }}.unitypackage
|
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
# release
|
|
||||||
create-release:
|
create-release:
|
||||||
needs: [update-packagejson, build-dotnet, build-unity]
|
needs: [build-dotnet, build-unity]
|
||||||
uses: Cysharp/Actions/.github/workflows/create-release.yaml@main
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
|
NUGET_XMLDOC_MODE: skip
|
||||||
|
steps:
|
||||||
|
# setup dotnet for nuget push
|
||||||
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
commit-id: ${{ needs.update-packagejson.outputs.sha }}
|
dotnet-version: 3.1.101
|
||||||
dry-run: ${{ inputs.dry-run }}
|
# set release tag(*.*.*) to env.GIT_TAG
|
||||||
tag: ${{ inputs.tag }}
|
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
||||||
nuget-push: true
|
|
||||||
release-upload: true
|
|
||||||
release-asset-path: ./UniTask.${{ inputs.tag }}.unitypackage/UniTask.${{ inputs.tag }}.unitypackage
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
cleanup:
|
# Create Releases
|
||||||
if: ${{ needs.update-packagejson.outputs.is-branch-created == 'true' }}
|
- uses: actions/create-release@v1
|
||||||
needs: [update-packagejson, build-dotnet, build-unity]
|
id: create_release
|
||||||
uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
branch: ${{ needs.update-packagejson.outputs.branch-name }}
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Ver.${{ github.ref }}
|
||||||
|
|
||||||
|
# Download(All) Artifacts to current directory
|
||||||
|
- uses: actions/download-artifact@v2-preview
|
||||||
|
|
||||||
|
# Upload to NuGet
|
||||||
|
- run: dotnet nuget push "./nuget/*.nupkg" -s https://www.nuget.org/api/v2/package -k ${{ secrets.NUGET_KEY }}
|
||||||
|
|
||||||
|
# Upload to Releases(unitypackage)
|
||||||
|
- uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./UniTask.${{ env.GIT_TAG }}.unitypackage/UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
asset_name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
asset_content_type: application/octet-stream
|
|
@ -1,10 +0,0 @@
|
||||||
name: Prevent github change
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- ".github/**/*.yaml"
|
|
||||||
- ".github/**/*.yml"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detect:
|
|
||||||
uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main
|
|
|
@ -1,10 +0,0 @@
|
||||||
name: "Close stale issues"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
uses: Cysharp/Actions/.github/workflows/stale-issue.yaml@main
|
|
|
@ -8,7 +8,8 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
generateTOC:
|
generateTOC:
|
||||||
name: TOC Generator
|
name: TOC Generator
|
||||||
uses: Cysharp/Actions/.github/workflows/toc-generator.yaml@main
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: technote-space/toc-generator@v2.4.0
|
||||||
with:
|
with:
|
||||||
TOC_TITLE: "## Table of Contents"
|
TOC_TITLE: "## Table of Contents"
|
||||||
secrets: inherit
|
|
||||||
|
|
|
@ -130,15 +130,126 @@ UpgradeLog*.XML
|
||||||
Assets/WSATestCertificate.pfx
|
Assets/WSATestCertificate.pfx
|
||||||
.vs/
|
.vs/
|
||||||
|
|
||||||
# Unity
|
Assembly-CSharp\.csproj
|
||||||
|
|
||||||
# Unity
|
UniRx\.Async\.csproj
|
||||||
.vsconfig
|
|
||||||
src/UniTask/Library/*
|
UniRx\.Async\.Editor\.csproj
|
||||||
src/UniTask/Temp/*
|
|
||||||
src/UniTask/Logs/*
|
UniRx\.Async\.Tests\.csproj
|
||||||
src/UniTask/[Uu]ser[Ss]ettings/
|
|
||||||
src/UniTask/*.sln
|
UniTask\.sln
|
||||||
src/UniTask/*.csproj
|
|
||||||
src/UniTask/*.unitypackage
|
RuntimeUnitTestToolkit\.csproj
|
||||||
!src/UniTask/Packages/
|
|
||||||
|
Assembly-CSharp-Editor\.csproj
|
||||||
|
|
||||||
|
UniRx\.Async\.unitypackage
|
||||||
|
|
||||||
|
UniRx.Async.Tests.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Tests.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Tests.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.*.unitypackage
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
src/UniTask/TempAsm.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Addressables.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.DOTween.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.TextMeshPro.csproj
|
||||||
|
|
||||||
|
src/UniTask/RuntimeUnitTestToolkit.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/TempAsm.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Addressables.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.DOTween.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Linq.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.Tests.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UniTask.TextMeshPro.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Addressables.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Analytics.DataPrivacy.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.ResourceManager.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.ScriptableBuildPipeline.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.TextMeshPro.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Unity.Timeline.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.Advertisements.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.Monetization.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.TestRunner.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/UnityEngine.UI.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/DOTween.Modules.Player.csproj
|
||||||
|
|
||||||
|
src/UniTask/Assembly-CSharp.Player.csproj
|
||||||
|
|
483
README.md
483
README.md
|
@ -1,21 +1,20 @@
|
||||||
UniTask
|
UniTask
|
||||||
===
|
===
|
||||||
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases) [](https://github.com/Cysharp/UniTask/blob/master/README_CN.md)
|
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases)
|
||||||
|
|
||||||
Provides an efficient allocation free async/await integration for Unity.
|
Provides an efficient allocation free async/await integration to Unity.
|
||||||
|
|
||||||
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achieve zero allocation
|
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
||||||
* Makes all Unity AsyncOperations and Coroutines awaitable
|
* All Unity AsyncOperations and Coroutine to awaitable
|
||||||
* PlayerLoop based task(`UniTask.Yield`, `UniTask.Delay`, `UniTask.DelayFrame`, etc..) that enable replacing all coroutine operations
|
* 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
|
||||||
* Runs completely on Unity's PlayerLoop so doesn't use threads and runs 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
|
||||||
* TaskTracker window to prevent memory leaks
|
* TaskTracker window to prevent memory leak
|
||||||
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
||||||
|
|
||||||
For technical 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)
|
||||||
For 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 -->
|
||||||
|
@ -24,7 +23,6 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
- [Getting started](#getting-started)
|
- [Getting started](#getting-started)
|
||||||
- [Basics of UniTask and AsyncOperation](#basics-of-unitask-and-asyncoperation)
|
- [Basics of UniTask and AsyncOperation](#basics-of-unitask-and-asyncoperation)
|
||||||
- [Cancellation and Exception handling](#cancellation-and-exception-handling)
|
- [Cancellation and Exception handling](#cancellation-and-exception-handling)
|
||||||
- [Timeout handling](#timeout-handling)
|
|
||||||
- [Progress](#progress)
|
- [Progress](#progress)
|
||||||
- [PlayerLoop](#playerloop)
|
- [PlayerLoop](#playerloop)
|
||||||
- [async void vs async UniTaskVoid](#async-void-vs-async-unitaskvoid)
|
- [async void vs async UniTaskVoid](#async-void-vs-async-unitaskvoid)
|
||||||
|
@ -33,11 +31,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
- [AsyncEnumerable and Async LINQ](#asyncenumerable-and-async-linq)
|
- [AsyncEnumerable and Async LINQ](#asyncenumerable-and-async-linq)
|
||||||
- [Awaitable Events](#awaitable-events)
|
- [Awaitable Events](#awaitable-events)
|
||||||
- [Channel](#channel)
|
- [Channel](#channel)
|
||||||
- [vs Awaitable](#vs-awaitable)
|
|
||||||
- [For Unit Testing](#for-unit-testing)
|
- [For Unit Testing](#for-unit-testing)
|
||||||
- [ThreadPool limitation](#threadpool-limitation)
|
|
||||||
- [IEnumerator.ToUniTask limitation](#ienumeratortounitask-limitation)
|
|
||||||
- [For UnityEditor](#for-unityeditor)
|
|
||||||
- [Compare with Standard Task API](#compare-with-standard-task-api)
|
- [Compare with Standard Task API](#compare-with-standard-task-api)
|
||||||
- [Pooling Configuration](#pooling-configuration)
|
- [Pooling Configuration](#pooling-configuration)
|
||||||
- [Allocation on Profiler](#allocation-on-profiler)
|
- [Allocation on Profiler](#allocation-on-profiler)
|
||||||
|
@ -45,6 +39,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
- [API References](#api-references)
|
- [API References](#api-references)
|
||||||
- [UPM Package](#upm-package)
|
- [UPM Package](#upm-package)
|
||||||
- [Install via git URL](#install-via-git-url)
|
- [Install via git URL](#install-via-git-url)
|
||||||
|
- [Install via OpenUPM](#install-via-openupm)
|
||||||
- [.NET Core](#net-core)
|
- [.NET Core](#net-core)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
|
@ -52,7 +47,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
---
|
---
|
||||||
Install via [UPM package](#upm-package) with git reference or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases).
|
Install via [UPM package](#upm-package) or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases) page.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// extension awaiter/methods can be used by this namespace
|
// extension awaiter/methods can be used by this namespace
|
||||||
|
@ -68,13 +63,12 @@ async UniTask<string> DemoAsync()
|
||||||
await SceneManager.LoadSceneAsync("scene2");
|
await SceneManager.LoadSceneAsync("scene2");
|
||||||
|
|
||||||
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
||||||
// after Unity 2022.2, you can use `destroyCancellationToken` in MonoBehaviour
|
|
||||||
var asset2 = await Resources.LoadAsync<TextAsset>("bar").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>
|
||||||
var asset3 = await Resources.LoadAsync<TextAsset>("baz").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 a coroutine
|
// await frame-based operation like coroutine
|
||||||
await UniTask.DelayFrame(100);
|
await UniTask.DelayFrame(100);
|
||||||
|
|
||||||
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
||||||
|
@ -87,13 +81,8 @@ async UniTask<string> DemoAsync()
|
||||||
await UniTask.Yield();
|
await UniTask.Yield();
|
||||||
await UniTask.NextFrame();
|
await UniTask.NextFrame();
|
||||||
|
|
||||||
// replacement of WaitForEndOfFrame
|
// replacement of WaitForEndOfFrame(same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate))
|
||||||
#if UNITY_2023_1_OR_NEWER
|
|
||||||
await UniTask.WaitForEndOfFrame();
|
await UniTask.WaitForEndOfFrame();
|
||||||
#else
|
|
||||||
// requires MonoBehaviour(CoroutineRunner))
|
|
||||||
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
||||||
await UniTask.WaitForFixedUpdate();
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
@ -104,10 +93,10 @@ async UniTask<string> DemoAsync()
|
||||||
// special helper of WaitUntil
|
// special helper of WaitUntil
|
||||||
await UniTask.WaitUntilValueChanged(this, x => x.isActive);
|
await UniTask.WaitUntilValueChanged(this, x => x.isActive);
|
||||||
|
|
||||||
// You can await IEnumerator coroutines
|
// You can await IEnumerator coroutine
|
||||||
await FooCoroutineEnumerator();
|
await FooCoroutineEnumerator();
|
||||||
|
|
||||||
// You can await a standard task
|
// You can await standard task
|
||||||
await Task.Run(() => 100);
|
await Task.Run(() => 100);
|
||||||
|
|
||||||
// Multithreading, run on ThreadPool under this code
|
// Multithreading, run on ThreadPool under this code
|
||||||
|
@ -129,12 +118,15 @@ async UniTask<string> DemoAsync()
|
||||||
var task2 = GetTextAsync(UnityWebRequest.Get("http://bing.com"));
|
var task2 = GetTextAsync(UnityWebRequest.Get("http://bing.com"));
|
||||||
var task3 = GetTextAsync(UnityWebRequest.Get("http://yahoo.com"));
|
var task3 = GetTextAsync(UnityWebRequest.Get("http://yahoo.com"));
|
||||||
|
|
||||||
// concurrent async-wait and get results easily by tuple syntax
|
// concurrent async-wait and get result easily by tuple syntax
|
||||||
var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);
|
var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);
|
||||||
|
|
||||||
// shorthand of WhenAll, tuple can await directly
|
// shorthand of WhenAll, tuple can await directly
|
||||||
var (google2, bing2, yahoo2) = await (task1, task2, task3);
|
var (google2, bing2, yahoo2) = await (task1, task2, task3);
|
||||||
|
|
||||||
|
// You can handle timeout easily
|
||||||
|
await GetTextAsync(UnityWebRequest.Get("http://unity.com")).Timeout(TimeSpan.FromMilliseconds(300));
|
||||||
|
|
||||||
// return async-value.(or you can use `UniTask`(no result), `UniTaskVoid`(fire and forget)).
|
// return async-value.(or you can use `UniTask`(no result), `UniTaskVoid`(fire and forget)).
|
||||||
return (asset as TextAsset)?.text ?? throw new InvalidOperationException("Asset not found");
|
return (asset as TextAsset)?.text ?? throw new InvalidOperationException("Asset not found");
|
||||||
}
|
}
|
||||||
|
@ -142,9 +134,9 @@ async UniTask<string> DemoAsync()
|
||||||
|
|
||||||
Basics of UniTask and AsyncOperation
|
Basics of UniTask and AsyncOperation
|
||||||
---
|
---
|
||||||
UniTask features rely on C# 7.0([task-like custom async method builder feature](https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md)) so the required Unity version is after `Unity 2018.3`, the official lowest version supported is `Unity 2018.4.13f1`.
|
UniTask feature rely on C# 7.0([task-like custom async method builder feature](https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md)) so required Unity version is after `Unity 2018.3`, officialy lower support version is `Unity 2018.4.13f1`.
|
||||||
|
|
||||||
Why is UniTask(custom task-like object) required? Because Task is too heavy and not matched to Unity threading (single-thread). UniTask does not use threads and SynchronizationContext/ExecutionContext because Unity's asynchronous object is automaticaly dispatched by Unity's engine layer. It achieves faster and lower allocation, and is completely integrated with Unity.
|
Why UniTask(custom task-like object) is required? Because Task is too heavy, not matched to Unity threading(single-thread). UniTask does not use thread and SynchronizationContext/ExecutionContext because almost Unity's asynchronous object is automaticaly dispatched by Unity's engine layer. It acquires more fast and more less allocation, completely integrated with Unity.
|
||||||
|
|
||||||
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `AsyncGPUReadbackRequest`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `AsyncGPUReadbackRequest`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
||||||
|
|
||||||
|
@ -156,13 +148,13 @@ UniTask provides three pattern of extension methods.
|
||||||
* .ToUniTask(IProgress, PlayerLoopTiming, CancellationToken);
|
* .ToUniTask(IProgress, PlayerLoopTiming, CancellationToken);
|
||||||
```
|
```
|
||||||
|
|
||||||
`WithCancellation` is a simple version of `ToUniTask`, both return `UniTask`. For 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: await directly is returned from native timing of PlayerLoop but WithCancellation and ToUniTask are returned from specified PlayerLoopTiming. For details of timing, see: [PlayerLoop](#playerloop) section.
|
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
||||||
|
|
||||||
> Note: AssetBundleRequest has `asset` and `allAssets`, default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
> Note: AssetBundleRequest has `asset` and `allAssets`, in default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
||||||
|
|
||||||
The type of `UniTask` can use utilities like `UniTask.WhenAll`, `UniTask.WhenAny`, `UniTask.WhenEach`. They are like `Task.WhenAll`/`Task.WhenAny` but the return type is more useful. They return value tuples so you can deconstruct each result and pass multiple types.
|
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
|
||||||
public async UniTaskVoid LoadManyAsync()
|
public async UniTaskVoid LoadManyAsync()
|
||||||
|
@ -181,7 +173,7 @@ async UniTask<Sprite> LoadAsSprite(string path)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to convert a callback to UniTask, you can use `UniTaskCompletionSource<T>` which is a lightweight edition of `TaskCompletionSource<T>`.
|
If you want to convert callback to UniTask, you can use `UniTaskCompletionSource<T>` that is the lightweight edition of `TaskCompletionSource<T>`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public UniTask<int> WrapByUniTaskCompletionSource()
|
public UniTask<int> WrapByUniTaskCompletionSource()
|
||||||
|
@ -198,7 +190,7 @@ public UniTask<int> WrapByUniTaskCompletionSource()
|
||||||
|
|
||||||
You can convert Task -> UniTask: `AsUniTask`, `UniTask` -> `UniTask<AsyncUnit>`: `AsAsyncUnitUniTask`, `UniTask<T>` -> `UniTask`: `AsUniTask`. `UniTask<T>` -> `UniTask`'s conversion cost is free.
|
You can convert Task -> UniTask: `AsUniTask`, `UniTask` -> `UniTask<AsyncUnit>`: `AsAsyncUnitUniTask`, `UniTask<T>` -> `UniTask`: `AsUniTask`. `UniTask<T>` -> `UniTask`'s conversion cost is free.
|
||||||
|
|
||||||
If you want to convert async to coroutine, you can use `.ToCoroutine()`, this is useful if you want to only allow using the coroutine system.
|
If you want to convert async to coroutine, you can use `.ToCoroutine()`, this is useful to use only allow coroutine system.
|
||||||
|
|
||||||
UniTask can not await twice. This is a similar constraint to the [ValueTask/IValueTaskSource](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-3.1) introduced in .NET Standard 2.1.
|
UniTask can not await twice. This is a similar constraint to the [ValueTask/IValueTaskSource](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-3.1) introduced in .NET Standard 2.1.
|
||||||
|
|
||||||
|
@ -217,13 +209,11 @@ await task;
|
||||||
await task; // NG, throws Exception
|
await task; // NG, throws Exception
|
||||||
```
|
```
|
||||||
|
|
||||||
Store to the class field, you can use `UniTask.Lazy` that supports calling multiple times. `.Preserve()` allows for multiple calls (internally cached results). This is useful when there are 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 multiple times and await from many callers.
|
|
||||||
|
|
||||||
Cancellation and Exception handling
|
Cancellation and Exception handling
|
||||||
---
|
---
|
||||||
Some UniTask factory methods have a `CancellationToken cancellationToken = default` parameter. Also some async operations 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.
|
||||||
|
|
||||||
You can pass `CancellationToken` to parameter by standard [`CancellationTokenSource`](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource).
|
You can pass `CancellationToken` to parameter by standard [`CancellationTokenSource`](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource).
|
||||||
|
|
||||||
|
@ -240,68 +230,18 @@ await UnityWebRequest.Get("http://google.co.jp").SendWebRequest().WithCancellati
|
||||||
await UniTask.DelayFrame(1000, cancellationToken: cts.Token);
|
await UniTask.DelayFrame(1000, cancellationToken: cts.Token);
|
||||||
```
|
```
|
||||||
|
|
||||||
CancellationToken can be created by `CancellationTokenSource` or MonoBehaviour's extension method `GetCancellationTokenOnDestroy`.
|
CancellationToken can create by `CancellationTokenSource` or MonoBehaviour's extension method `GetCancellationTokenOnDestroy`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// this CancellationToken lifecycle is same as GameObject.
|
// this CancellationToken lifecycle is same as GameObject.
|
||||||
await UniTask.DelayFrame(1000, cancellationToken: this.GetCancellationTokenOnDestroy());
|
await UniTask.DelayFrame(1000, cancellationToken: this.GetCancellationTokenOnDestroy());
|
||||||
```
|
```
|
||||||
|
|
||||||
For propagate Cancellation, all async method recommend to accept `CancellationToken cancellationToken` at last argument, and pass `CancellationToken` from root to end.
|
When detect cancellation, all methods throws `OperationCanceledException` and propagate to upstream. `OperationCanceledException` is special exception, if not handled this exception, finally it is propagated to `UniTaskScheduler.UnobservedTaskException`.
|
||||||
|
|
||||||
```csharp
|
Default behaviour of received unhandled exception is write log as exception. Log level can change by `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to change custom beavhiour, set action to `UniTaskScheduler.UnobservedTaskException.`
|
||||||
await FooAsync(this.GetCancellationTokenOnDestroy());
|
|
||||||
|
|
||||||
// ---
|
If you want to cancel behaviour in async UniTask method, throws `OperationCanceledException` manually.
|
||||||
|
|
||||||
async UniTask FooAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await BarAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTask BarAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`CancellationToken` means lifecycle of async. You can hold your own lifecycle insteadof default CancellationTokenOnDestroy.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class MyBehaviour : MonoBehaviour
|
|
||||||
{
|
|
||||||
CancellationTokenSource disableCancellation = new CancellationTokenSource();
|
|
||||||
CancellationTokenSource destroyCancellation = new CancellationTokenSource();
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
if (disableCancellation != null)
|
|
||||||
{
|
|
||||||
disableCancellation.Dispose();
|
|
||||||
}
|
|
||||||
disableCancellation = new CancellationTokenSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
disableCancellation.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroy()
|
|
||||||
{
|
|
||||||
destroyCancellation.Cancel();
|
|
||||||
destroyCancellation.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
After Unity 2022.2, Unity adds CancellationToken in [MonoBehaviour.destroyCancellationToken](https://docs.unity3d.com/ScriptReference/MonoBehaviour-destroyCancellationToken.html) and [Application.exitCancellationToken](https://docs.unity3d.com/ScriptReference/Application-exitCancellationToken.html).
|
|
||||||
|
|
||||||
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. When exception(not limited to `OperationCanceledException`) is not handled in async method, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`. The default behaviour of received unhandled exception is to write log as exception. Log level can be changed using `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to use custom behaviour, set an action to `UniTaskScheduler.UnobservedTaskException.`
|
|
||||||
|
|
||||||
And also `OperationCanceledException` is a special exception, this is silently ignored at `UnobservedTaskException`.
|
|
||||||
|
|
||||||
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask<int> FooAsync()
|
public async UniTask<int> FooAsync()
|
||||||
|
@ -311,7 +251,7 @@ public async UniTask<int> FooAsync()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you handle an exception but want to ignore(propagate to global cancellation handling), use an exception filter.
|
If you handle exception but want to ignore(propagete to global cancellation handling), use exception filter.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask<int> BarAsync()
|
public async UniTask<int> BarAsync()
|
||||||
|
@ -321,14 +261,14 @@ public async UniTask<int> BarAsync()
|
||||||
var x = await FooAsync();
|
var x = await FooAsync();
|
||||||
return x * 2;
|
return x * 2;
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (!(ex is OperationCanceledException)) // when (ex is not OperationCanceledException) at C# 9.0
|
catch (Exception ex) when (!(ex is OperationCanceledException))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
throws/catch `OperationCanceledException` is slightly heavy, so if performance is a concern, use `UniTask.SuppressCancellationThrow` to avoid OperationCanceledException throw. It returns `(bool IsCanceled, T Result)` instead of throwing.
|
throws/catch `OperationCanceledException` is slightly heavy, if you want to care performance, use `UniTask.SuppressCancellationThrow` to avoid OperationCanceledException throw. It returns `(bool IsCanceled, T Result)` instead of throw.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var (isCanceled, _) = await UniTask.DelayFrame(10, cancellationToken: cts.Token).SuppressCancellationThrow();
|
var (isCanceled, _) = await UniTask.DelayFrame(10, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
|
@ -338,117 +278,11 @@ if (isCanceled)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Only suppress throws if you call directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not suppress throws.
|
Note: Only suppress throws if you call it directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not be suppressed throws.
|
||||||
|
|
||||||
Some features that use Unity's player loop, such as `UniTask.Yield` and `UniTask.Delay` etc, determines CancellationToken state on the player loop.
|
|
||||||
This means it does not cancel immediately upon `CancellationToken` fired.
|
|
||||||
|
|
||||||
If you want to change this behaviour, the cancellation to be immediate, set the `cancelImmediately` flag as an argument.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
await UniTask.Yield(cancellationToken, cancelImmediately: true);
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: Setting `cancelImmediately` to true and detecting an immediate cancellation is more costly than the default behavior.
|
|
||||||
This is because it uses `CancellationToken.Register`; it is heavier than checking CancellationToken on the player loop.
|
|
||||||
|
|
||||||
Timeout handling
|
|
||||||
---
|
|
||||||
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
cts.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(cts.Token);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException ex)
|
|
||||||
{
|
|
||||||
if (ex.CancellationToken == cts.Token)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("Timeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> `CancellationTokenSouce.CancelAfter` is a standard api. However in Unity you should not use it because it depends threading timer. `CancelAfterSlim` is UniTask's extension methods, it uses PlayerLoop instead.
|
|
||||||
|
|
||||||
If you want to use timeout with other source of cancellation, use `CancellationTokenSource.CreateLinkedTokenSource`.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var cancelToken = new CancellationTokenSource();
|
|
||||||
cancelButton.onClick.AddListener(() =>
|
|
||||||
{
|
|
||||||
cancelToken.Cancel(); // cancel from button click.
|
|
||||||
});
|
|
||||||
|
|
||||||
var timeoutToken = new CancellationTokenSource();
|
|
||||||
timeoutToken.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// combine token
|
|
||||||
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken.Token, timeoutToken.Token);
|
|
||||||
|
|
||||||
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(linkedTokenSource.Token);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException ex)
|
|
||||||
{
|
|
||||||
if (timeoutToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("Timeout.");
|
|
||||||
}
|
|
||||||
else if (cancelToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("Cancel clicked.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Optimize for reduce allocation of CancellationTokenSource for timeout per call async method, you can use UniTask's `TimeoutController`.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
TimeoutController timeoutController = new TimeoutController(); // setup to field for reuse.
|
|
||||||
|
|
||||||
async UniTask FooAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// you can pass timeoutController.Timeout(TimeSpan) to cancellationToken.
|
|
||||||
await UnityWebRequest.Get("http://foo").SendWebRequest()
|
|
||||||
.WithCancellation(timeoutController.Timeout(TimeSpan.FromSeconds(5)));
|
|
||||||
timeoutController.Reset(); // call Reset(Stop timeout timer and ready for reuse) when succeed.
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException ex)
|
|
||||||
{
|
|
||||||
if (timeoutController.IsTimeout())
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("timeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to use timeout with other source of cancellation, use `new TimeoutController(CancellationToken)`.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
TimeoutController timeoutController;
|
|
||||||
CancellationTokenSource clickCancelSource;
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
this.clickCancelSource = new CancellationTokenSource();
|
|
||||||
this.timeoutController = new TimeoutController(clickCancelSource);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: UniTask has `.Timeout`, `.TimeoutWithoutException` methods however, if possible, do not use these, please pass `CancellationToken`. Because `.Timeout` work from external of task, can not stop timeoutted task. `.Timeout` means ignore result when timeout. If you pass a `CancellationToken` to the method, it will act from inside of the task, so it is possible to stop a running task.
|
|
||||||
|
|
||||||
Progress
|
Progress
|
||||||
---
|
---
|
||||||
Some async operations for unity have `ToUniTask(IProgress<float> progress = null, ...)` extension methods.
|
Some async operation for unity have `ToUniTask(IProgress<float> progress = null, ...)` extension methods.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var progress = Progress.Create<float>(x => Debug.Log(x));
|
var progress = Progress.Create<float>(x => Debug.Log(x));
|
||||||
|
@ -458,9 +292,9 @@ var request = await UnityWebRequest.Get("http://google.co.jp")
|
||||||
.ToUniTask(progress: progress);
|
.ToUniTask(progress: progress);
|
||||||
```
|
```
|
||||||
|
|
||||||
You should not use standard `new System.Progress<T>`, because it causes allocation every time. Use `Cysharp.Threading.Tasks.Progress` instead. This progress factory has two methods, `Create` and `CreateOnlyValueChanged`. `CreateOnlyValueChanged` calls only when the progress value has changed.
|
You should not use standard `new System.Progress<T>`, because it causes allocation every times. Use `Cysharp.Threading.Tasks.Progress` instead. This progress factory has two methods, `Create` and `CreateOnlyValueChanged`. `CreateOnlyValueChanged` calls only when progress value changed.
|
||||||
|
|
||||||
Implementing IProgress interface to caller is better as there is no lambda allocation.
|
Implements IProgress interface to caller is more better, there is no allocation of lambda.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class Foo : MonoBehaviour, IProgress<float>
|
public class Foo : MonoBehaviour, IProgress<float>
|
||||||
|
@ -481,7 +315,7 @@ public class Foo : MonoBehaviour, IProgress<float>
|
||||||
|
|
||||||
PlayerLoop
|
PlayerLoop
|
||||||
---
|
---
|
||||||
UniTask is run on a custom [PlayerLoop](https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html). UniTask's playerloop based methods (such as `Delay`, `DelayFrame`, `asyncOperation.ToUniTask`, etc...) accept this `PlayerLoopTiming`.
|
UniTask is run on custom [PlayerLoop](https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html). UniTask's playerloop based method(such as `Delay`, `DelayFrame`, `asyncOperation.ToUniTask`, etc...) accepts this `PlayerLoopTiming`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public enum PlayerLoopTiming
|
public enum PlayerLoopTiming
|
||||||
|
@ -506,40 +340,28 @@ public enum PlayerLoopTiming
|
||||||
|
|
||||||
PostLateUpdate = 12,
|
PostLateUpdate = 12,
|
||||||
LastPostLateUpdate = 13
|
LastPostLateUpdate = 13
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
TimeUpdate = 14,
|
|
||||||
LastTimeUpdate = 15,
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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 to `yield return null` in a coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar to `WaitForFixedUpdate`.
|
`PlayerLoopTiming.Update` is similar 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.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
|
`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`.
|
||||||
>
|
|
||||||
> Note: In Unity 2023.1 or newer, `await UniTask.WaitForEndOfFrame();` no longer requires MonoBehaviour. It uses `UnityEngine.Awaitable.EndOfFrameAsync`.
|
|
||||||
|
|
||||||
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
|
> 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 runs on YieldRunner. It is the most lightweight and fastest.
|
AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene's `Start` called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
|
||||||
|
|
||||||
`AsyncOperation` is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after being called, the loaded scene's `Start` is 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 UniTask, await directly uses native timing, while `WithCancellation` and `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, it causes a different order of Start and continuation after await. So it is recommended not to use `LoadSceneAsync.ToUniTask`.
|
In stacktrace, you can check where is running in playerloop.
|
||||||
|
|
||||||
> Note: When using Unity 2023.1 or newer, ensure you have `using UnityEngine;` in the using statements of your file when working with new `UnityEngine.Awaitable` methods like `SceneManager.LoadSceneAsync`.
|
|
||||||
> This prevents compilation errors by avoiding the use of the `UnityEngine.AsyncOperation` version.
|
|
||||||
|
|
||||||
In the stacktrace, you can check where it is running in playerloop.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
By default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
In default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
||||||
|
|
||||||
The order in which methods are called in BeforeSceneLoad is nondeterministic, so if you want to use UniTask in other BeforeSceneLoad methods, you should try to initialize it before this.
|
The order in which methods are called in BeforeSceneLoad is indeterminate, so if you want to use UniTask in other BeforeSceneLoad methods, you should try to initialize it before this.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// AfterAssembliesLoaded is called before BeforeSceneLoad
|
// AfterAssembliesLoaded is called before BeforeSceneLoad
|
||||||
|
@ -551,9 +373,9 @@ public static void InitUniTaskLoop()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you import Unity's `Entities` package, that resets the custom player loop to default at `BeforeSceneLoad` and injects ECS's loop. When Unity calls ECS's inject method after UniTask's initialize method, UniTask will no longer work.
|
If you import Unity's `Entities` package, that reset custom player loop to default at `BeforeSceneLoad` and inject ECS's loop. When Unity call ECS's inject method after UniTask's initialize method, UniTask will no longer work.
|
||||||
|
|
||||||
To solve this issue, you can re-initialize the UniTask PlayerLoop after ECS is initialized.
|
To solve this issue, you can re-initialize UniTask PlayerLoop after ECS initialized.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Get ECS Loop.
|
// Get ECS Loop.
|
||||||
|
@ -563,7 +385,7 @@ var playerLoop = ScriptBehaviourUpdateOrder.CurrentPlayerLoop;
|
||||||
PlayerLoopHelper.Initialize(ref playerLoop);
|
PlayerLoopHelper.Initialize(ref playerLoop);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can diagnose whether UniTask's player loop is ready by calling `PlayerLoopHelper.IsInjectedUniTaskPlayerLoop()`. And also `PlayerLoopHelper.DumpCurrentPlayerLoop` logs all current playerloops to console.
|
You can diagnostic UniTask's player loop is ready by `PlayerLoopHelper.IsInjectedUniTaskPlayerLoop()`. And also `PlayerLoopHelper.DumpCurrentPlayerLoop` shows current all playerloop to console.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void Start()
|
void Start()
|
||||||
|
@ -573,40 +395,9 @@ void Start()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can optimize loop cost slightly by remove unuse PlayerLoopTiming injection. You can call `PlayerLoopHelper.Initialize(InjectPlayerLoopTimings)` on initialize.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var loop = PlayerLoop.GetCurrentPlayerLoop();
|
|
||||||
PlayerLoopHelper.Initialize(ref loop, InjectPlayerLoopTimings.Minimum); // minimum is Update | FixedUpdate | LastPostLateUpdate
|
|
||||||
```
|
|
||||||
|
|
||||||
`InjectPlayerLoopTimings` has three preset, `All` and `Standard`(All without last except LastPostLateUpdate), `Minimum`(`Update | FixedUpdate | LastPostLateUpdate`). Default is All and you can combine custom inject timings like `InjectPlayerLoopTimings.Update | InjectPlayerLoopTimings.FixedUpdate | InjectPlayerLoopTimings.PreLateUpdate`.
|
|
||||||
|
|
||||||
You can make error to use uninjected `PlayerLoopTiming` by [Microsoft.CodeAnalysis.BannedApiAnalyzers](https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md). For example, you can setup `BannedSymbols.txt` like this for `InjectPlayerLoopTimings.Minimum`.
|
|
||||||
|
|
||||||
```txt
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.Initialization; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastInitialization; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.EarlyUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastEarlyUpdate; Isn't injected this PlayerLoop in this project.d
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastFixedUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PreUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastPreUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PreLateUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastPreLateUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PostLateUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.TimeUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastTimeUpdate; Isn't injected this PlayerLoop in this project.
|
|
||||||
```
|
|
||||||
|
|
||||||
You can configure `RS0030` severity to error.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
async void vs async UniTaskVoid
|
async void vs async UniTaskVoid
|
||||||
---
|
---
|
||||||
`async void` is a standard C# task system so it does not run on UniTask systems. It is better not to use it. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and reports errors immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require awaiting (fire and forget), using `UniTaskVoid` is better. Unfortunately to dismiss warning, you're required to call `Forget()`.
|
`async void` is a standard C# task system so does not run on UniTask systems. It is better not to use. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and report error immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require to await it(fire and forget), use `UniTaskVoid` is better. Unfortunately to dismiss warning, require to using with `Forget()`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTaskVoid FireAndForgetMethod()
|
public async UniTaskVoid FireAndForgetMethod()
|
||||||
|
@ -621,7 +412,7 @@ public void Caller()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Also UniTask has the `Forget` method, it is similar to `UniTaskVoid` and has the same effects. However `UniTaskVoid` is more efficient if you completely don't use `await`。
|
Also UniTask have `Forget` method, it is similar with UniTaskVoid and same effects with it. However still UniTaskVoid is more efficient if completely do not use await。
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask DoAsync()
|
public async UniTask DoAsync()
|
||||||
|
@ -636,7 +427,7 @@ public void Caller()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
To use an async lambda registered to an event, don't use `async void`. Instead you can use `UniTask.Action` or `UniTask.UnityAction`, both of which create a delegate via `async UniTaskVoid` lambda.
|
Using async lambda in register event, it is used `async void`. To avoid it, you can use `UniTask.Action` or `UniTask.UnityAction` that creates delegate via `async UniTaskVoid` lambda.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
Action actEvent;
|
Action actEvent;
|
||||||
|
@ -651,7 +442,7 @@ actEvent += UniTask.Action(async () => { await UniTask.Yield(); });
|
||||||
unityEvent += UniTask.UnityAction(async () => { await UniTask.Yield(); });
|
unityEvent += UniTask.UnityAction(async () => { await UniTask.Yield(); });
|
||||||
```
|
```
|
||||||
|
|
||||||
`UniTaskVoid` can also be used in MonoBehaviour's `Start` method.
|
`UniTaskVoid` can also use in MonoBehaviour's `Start` method.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
class Sample : MonoBehaviour
|
class Sample : MonoBehaviour
|
||||||
|
@ -665,7 +456,7 @@ class Sample : MonoBehaviour
|
||||||
|
|
||||||
UniTaskTracker
|
UniTaskTracker
|
||||||
---
|
---
|
||||||
useful for checking (leaked) UniTasks. You can open tracker window in `Window -> UniTask Tracker`.
|
useful for check(leak) UniTasks. You can open tracker window in `Window -> UniTask Tracker`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -675,16 +466,15 @@ useful for checking (leaked) UniTasks. You can open tracker window in `Window ->
|
||||||
* Enable Tracking(Toggle) - Start to track async/await UniTask. Performance impact: low.
|
* Enable Tracking(Toggle) - Start to track async/await UniTask. Performance impact: low.
|
||||||
* Enable StackTrace(Toggle) - Capture StackTrace when task is started. Performance impact: high.
|
* Enable StackTrace(Toggle) - Capture StackTrace when task is started. Performance impact: high.
|
||||||
|
|
||||||
UniTaskTracker is intended for debugging use only as enabling tracking and capturing stacktraces is useful but has a heavy performance impact. Recommended usage is to enable both tracking and stacktraces to find task leaks and to disable them both when done.
|
For debug use, enable tracking and capture stacktrace is useful but it it decline performance. Recommended usage is enable both to find task leak, and when done, finally disable both.
|
||||||
|
|
||||||
External Assets
|
External Assets
|
||||||
---
|
---
|
||||||
By default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField` event extensions like standard uGUI `InputField`), DOTween(`Tween` as awaitable) and Addressables(`AsyncOperationHandle` and `AsyncOperationHandle<T>` as awaitable).
|
In default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField` event extensions like standard uGUI `InputField`), DOTween(`Tween` as awaitable) and Addressables(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
||||||
|
|
||||||
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
There are defined in separated asmdef like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
||||||
|
|
||||||
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager.
|
TextMeshPro and Addressables support are automatically enabled when import there package from package manager. However DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||||
However for DOTween support, after importing from the [DOTWeen assets](https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676r) and define the scripting define symbol `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// sequential
|
// sequential
|
||||||
|
@ -699,15 +489,15 @@ await UniTask.WhenAll(
|
||||||
transform.DOScale(10, 3).WithCancellation(ct));
|
transform.DOScale(10, 3).WithCancellation(ct));
|
||||||
```
|
```
|
||||||
|
|
||||||
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works on both Complete(true/false) and Kill(true/false). But if you want to reuse tweens (`SetAutoKill(false)`), it does not work as expected. If you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works both Complete(true/false) and Kill(true/false). But if you want to tween reuse(`SetAutoKill(false)`), it does not work you expected. Or, if you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
||||||
|
|
||||||
AsyncEnumerable and Async LINQ
|
AsyncEnumerable and Async LINQ
|
||||||
---
|
---
|
||||||
Unity 2020.2 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in the async era.
|
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Unity 2020.2, C# 8.0
|
// Unity 2020.2.0a12, C# 8.0
|
||||||
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate().WithCancellation(token))
|
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
}
|
}
|
||||||
|
@ -717,23 +507,10 @@ In a C# 7.3 environment, you can use the `ForEachAsync` method to work in almost
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// C# 7.3(Unity 2018.3~)
|
// C# 7.3(Unity 2018.3~)
|
||||||
await UniTaskAsyncEnumerable.EveryUpdate().ForEachAsync(_ =>
|
await UniTaskAsyncEnumerable.EveryUpdate(token).ForEachAsync(_ =>
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
}, token);
|
});
|
||||||
```
|
|
||||||
|
|
||||||
`UniTask.WhenEach` that is similar to .NET 9's `Task.WhenEach` can consume new way for await multiple tasks.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
await foreach (var result in UniTask.WhenEach(task1, task2, task3))
|
|
||||||
{
|
|
||||||
// The result is of type WhenEachResult<T>.
|
|
||||||
// It contains either `T Result` or `Exception Exception`.
|
|
||||||
// You can check `IsCompletedSuccessfully` or `IsFaulted` to determine whether to access `.Result` or `.Exception`.
|
|
||||||
// If you want to throw an exception when `IsFaulted` and retrieve the result when successful, use `GetResult()`.
|
|
||||||
Debug.Log(result.GetResult());
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
||||||
|
@ -744,7 +521,7 @@ await okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).ForEachAsy
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Fire and Forget style(for example, event handling), you can also use `Subscribe`.
|
Fire and Forget style(for example, event handling), also you can use `Subscribe`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).Subscribe(_ =>
|
okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).Subscribe(_ =>
|
||||||
|
@ -756,7 +533,7 @@ Async LINQ is enabled when `using Cysharp.Threading.Tasks.Linq;`, and `UniTaskAs
|
||||||
|
|
||||||
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
|
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
|
||||||
|
|
||||||
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`,`Merge` `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
|
`UniTaskAsyncEnumerable` is the entry point like `Enumerbale`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`, `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
|
||||||
|
|
||||||
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
||||||
|
|
||||||
|
@ -768,7 +545,7 @@ SelectAwaitWithCancellation(Func<T, CancellationToken, UniTask<TR>> selector)
|
||||||
|
|
||||||
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
|
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
|
||||||
|
|
||||||
How to create an async iterator: C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
|
How to create async iterator, C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
|
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
|
||||||
|
@ -844,13 +621,32 @@ async UniTask TripleClick(CancellationToken token)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All MonoBehaviour message events can convert async-streams by `AsyncTriggers` that can be enabled by `using Cysharp.Threading.Tasks.Triggers;`. AsyncTrigger can be created using `GetAsync***Trigger` and triggers itself as UniTaskAsyncEnumerable.
|
All MonoBehaviour message events can convert async-streams by `AsyncTriggers` that can enable by `using Cysharp.Threading.Tasks.Triggers;`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var trigger = this.GetOnCollisionEnterAsyncHandler();
|
using Cysharp.Threading.Tasks.Triggers;
|
||||||
await trigger.OnCollisionEnterAsync();
|
|
||||||
await trigger.OnCollisionEnterAsync();
|
async UniTaskVoid MonitorCollision()
|
||||||
await trigger.OnCollisionEnterAsync();
|
{
|
||||||
|
await gameObject.OnCollisionEnterAsync();
|
||||||
|
Debug.Log("Collision Enter");
|
||||||
|
/* do anything */
|
||||||
|
|
||||||
|
await gameObject.OnCollisionExitAsync();
|
||||||
|
Debug.Log("Collision Exit");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Similar as uGUI event, AsyncTrigger can get by `GetAsync***Trigger` and trigger it self is UniTaskAsyncEnumerable.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// use await multiple times, get AsyncTriggerHandler is more efficient.
|
||||||
|
using(var trigger = this.GetOnCollisionEnterAsyncHandler())
|
||||||
|
{
|
||||||
|
await OnCollisionEnterAsync();
|
||||||
|
await OnCollisionEnterAsync();
|
||||||
|
await OnCollisionEnterAsync();
|
||||||
|
}
|
||||||
|
|
||||||
// every moves.
|
// every moves.
|
||||||
await this.GetAsyncMoveTrigger().ForEachAsync(axisEventData =>
|
await this.GetAsyncMoveTrigger().ForEachAsync(axisEventData =>
|
||||||
|
@ -858,7 +654,7 @@ await this.GetAsyncMoveTrigger().ForEachAsync(axisEventData =>
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
`AsyncReactiveProperty`, `AsyncReadOnlyReactiveProperty` is UniTask's version of ReactiveProperty. `BindTo` extension method of `IUniTaskAsyncEnumerable<T>` for binding asynchronous stream values to Unity components(Text/Selectable/TMP/Text).
|
`AsyncReactiveProperty`, `AsyncReadOnlyReactiveProperty` is UniTask version of UniTask's ReactiveProperty. `BindTo` extension method of `IUniTaskAsyncEnumerable<T>` for binding asynchronous stream values to Unity components(Text/Selectable/TMP/Text).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var rp = new AsyncReactiveProperty<int>(99);
|
var rp = new AsyncReactiveProperty<int>(99);
|
||||||
|
@ -878,9 +674,9 @@ rp.WithoutCurrent().BindTo(this.textComponent);
|
||||||
|
|
||||||
await rp.WaitAsync(); // wait until next value set
|
await rp.WaitAsync(); // wait until next value set
|
||||||
|
|
||||||
// also exists ToReadOnlyAsyncReactiveProperty
|
// also exists ToReadOnlyReactiveProperty
|
||||||
var rp2 = new AsyncReactiveProperty<int>(99);
|
var rp2 = new AsyncReactiveProperty<int>(99);
|
||||||
var rorp = rp.CombineLatest(rp2, (x, y) => (x, y)).ToReadOnlyAsyncReactiveProperty(CancellationToken.None);
|
var rorp = rp.CombineLatest(rp2, (x, y) => (x, y)).ToReadOnlyReactiveProperty();
|
||||||
```
|
```
|
||||||
|
|
||||||
A pull-type asynchronous stream does not get the next values until the asynchronous processing in the sequence is complete. This could spill data from push-type events such as buttons.
|
A pull-type asynchronous stream does not get the next values until the asynchronous processing in the sequence is complete. This could spill data from push-type events such as buttons.
|
||||||
|
@ -893,9 +689,9 @@ await button.OnClickAsAsyncEnumerable().ForEachAwaitAsync(async x =>
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
It is useful (prevent double-click) but not useful sometimes.
|
It is useful(prevent double-click) but not useful in sometimes.
|
||||||
|
|
||||||
Using the `Queue()` method will also queue events during asynchronous processing.
|
Using `Queue()` method, which will also queue events during asynchronous processing.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// queued message in asynchronous processing
|
// queued message in asynchronous processing
|
||||||
|
@ -916,13 +712,13 @@ button.OnClickAsAsyncEnumerable().Subscribe(async x =>
|
||||||
|
|
||||||
Channel
|
Channel
|
||||||
---
|
---
|
||||||
`Channel` is the same as [System.Threading.Tasks.Channels](https://docs.microsoft.com/en-us/dotnet/api/system.threading.channels?view=netcore-3.1) which is similar to a GoLang Channel.
|
`Channel` is same as [System.Threading.Tasks.Channels](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.channels?view=netcore-3.1) that is similar as GoLang Channel.
|
||||||
|
|
||||||
Currently it only supports multiple-producer, single-consumer unbounded channels. It can create by `Channel.CreateSingleConsumerUnbounded<T>()`.
|
Currently only supports multiple-producer, single-consumer unbounded channel. It can create by `Channel.CreateSingleConsumerUnbounded<T>()`.
|
||||||
|
|
||||||
For producer(`.Writer`), use `TryWrite` to push value and `TryComplete` to complete channel. For consumer(`.Reader`), use `TryRead`, `WaitToReadAsync`, `ReadAsync`, `Completion` and `ReadAllAsync` to read queued messages.
|
For producer(`.Writer`), `TryWrite` to push value and `TryComplete` to complete channel. For consumer(`.Reader`), `TryRead`, `WaitToReadAsync`, `ReadAsync`, `Completion` and `ReadAllAsync` to read queued messages.
|
||||||
|
|
||||||
`ReadAllAsync` returns `IUniTaskAsyncEnumerable<T>` so query LINQ operators. Reader only allows single-consumer but uses `.Publish()` query operator to enable multicast message. For example, make pub/sub utility.
|
`ReadAllAsync` returns `IUniTaskAsyncEnumerable<T>` so query LINQ operators. Reader only allows single-consumer but use `.Publish()` query operator to enable multicast message. For example, make pub/sub utility.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class AsyncMessageBroker<T> : IDisposable
|
public class AsyncMessageBroker<T> : IDisposable
|
||||||
|
@ -957,17 +753,9 @@ public class AsyncMessageBroker<T> : IDisposable
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
vs Awaitable
|
|
||||||
---
|
|
||||||
Unity 6 introduces the awaitable type, [Awaitable](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Awaitable.html). To put it simply, Awaitable can be considered a subset of UniTask, and in fact, Awaitable's design was influenced by UniTask. It should be able to handle PlayerLoop-based awaits, pooled Tasks, and support for cancellation with `CancellationToken` in a similar way. With its inclusion in the standard library, you may wonder whether to continue using UniTask or migrate to Awaitable. Here's a brief guide.
|
|
||||||
|
|
||||||
First, the functionality provided by Awaitable is equivalent to what coroutines offer. Instead of `yield return`, you use await; `await NextFrameAsync()` replaces `yield return null`; and there are equivalents for `WaitForSeconds` and `EndOfFrame`. However, that's the extent of it. Being coroutine-based in terms of functionality, it lacks Task-based features. In practical application development using async/await, operations like `WhenAll` are essential. Additionally, UniTask enables many frame-based operations (such as `DelayFrame`) and more flexible PlayerLoopTiming control, which are not available in Awaitable. Of course, there's no Tracker Window either.
|
|
||||||
|
|
||||||
Therefore, I recommend using UniTask for application development. UniTask is a superset of Awaitable and includes many essential features. For library development, where you want to avoid external dependencies, using Awaitable as a return type for methods would be appropriate. Awaitable can be converted to UniTask using `AsUniTask`, so there's no issue in handling Awaitable-based functionality within the UniTask library. Of course, if you don't need to worry about dependencies, using UniTask would be the best choice even for library development.
|
|
||||||
|
|
||||||
For Unit Testing
|
For Unit Testing
|
||||||
---
|
---
|
||||||
Unity's `[UnityTest]` attribute can test coroutine(IEnumerator) but can not test async. `UniTask.ToCoroutine` bridges async/await to coroutine so you can test async methods.
|
Unity's `[UnityTest]` attribute can test coroutine(IEnumerator) but can not test async. `UniTask.ToCoroutine` bridges async/await to coroutine so you can test async method.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
|
@ -990,34 +778,11 @@ public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTask's own unit tests are written using Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to integrate with CI and check if IL2CPP is 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.
|
||||||
|
|
||||||
ThreadPool limitation
|
|
||||||
---
|
|
||||||
Most UniTask methods run on a single thread (PlayerLoop), with only `UniTask.Run`(`Task.Run` equivalent) and `UniTask.SwitchToThreadPool` running on a thread pool. If you use a thread pool, it won't work with WebGL and so on.
|
|
||||||
|
|
||||||
`UniTask.Run` is now deprecated. You can use `UniTask.RunOnThreadPool` instead. And also consider whether you can use `UniTask.Create` or `UniTask.Void`.
|
|
||||||
|
|
||||||
IEnumerator.ToUniTask limitation
|
|
||||||
---
|
|
||||||
You can convert coroutine(IEnumerator) to UniTask(or await directly) but it has some limitations.
|
|
||||||
|
|
||||||
* `WaitForEndOfFrame`/`WaitForFixedUpdate`/`Coroutine` is not supported.
|
|
||||||
* Consuming loop timing is not the same as `StartCoroutine`, it uses the specified `PlayerLoopTiming` and the default `PlayerLoopTiming.Update` is run before MonoBehaviour's `Update` and `StartCoroutine`'s loop.
|
|
||||||
|
|
||||||
If you want fully compatible conversion from coroutine to async, use the `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
|
|
||||||
---
|
|
||||||
UniTask can run on Unity Editor like an Editor Coroutine. However, there are some limitations.
|
|
||||||
|
|
||||||
* UniTask.Delay's DelayType.DeltaTime, UnscaledDeltaTime do not work correctly because they can not get deltaTime in editor. Therefore run on EditMode, automatically change DelayType to `DelayType.Realtime` that wait for the right time.
|
|
||||||
* All PlayerLoopTiming run on the timing `EditorApplication.update`.
|
|
||||||
* `-batchmode` with `-quit` does not work because Unity does not run `EditorApplication.update` and quit after a single frame. Instead, don't use `-quit` and quit manually with `EditorApplication.Exit(0)`.
|
|
||||||
|
|
||||||
Compare with Standard Task API
|
Compare with Standard Task API
|
||||||
---
|
---
|
||||||
UniTask has many standard Task-like APIs. This table shows what the alternative apis are.
|
UniTask has many standard Task-like APIs. This table shows what is the alternative apis.
|
||||||
|
|
||||||
Use standard type.
|
Use standard type.
|
||||||
|
|
||||||
|
@ -1051,10 +816,9 @@ Use UniTask type.
|
||||||
| `IAsyncDisposable` | `IUniTaskAsyncDisposable` |
|
| `IAsyncDisposable` | `IUniTaskAsyncDisposable` |
|
||||||
| `Task.Delay` | `UniTask.Delay` |
|
| `Task.Delay` | `UniTask.Delay` |
|
||||||
| `Task.Yield` | `UniTask.Yield` |
|
| `Task.Yield` | `UniTask.Yield` |
|
||||||
| `Task.Run` | `UniTask.RunOnThreadPool` |
|
| `Task.Run` | `UniTask.Run` |
|
||||||
| `Task.WhenAll` | `UniTask.WhenAll` |
|
| `Task.WhenAll` | `UniTask.WhenAll` |
|
||||||
| `Task.WhenAny` | `UniTask.WhenAny` |
|
| `Task.WhenAny` | `UniTask.WhenAny` |
|
||||||
| `Task.WhenEach` | `UniTask.WhenEach` |
|
|
||||||
| `Task.CompletedTask` | `UniTask.CompletedTask` |
|
| `Task.CompletedTask` | `UniTask.CompletedTask` |
|
||||||
| `Task.FromException` | `UniTask.FromException` |
|
| `Task.FromException` | `UniTask.FromException` |
|
||||||
| `Task.FromResult` | `UniTask.FromResult` |
|
| `Task.FromResult` | `UniTask.FromResult` |
|
||||||
|
@ -1064,7 +828,7 @@ Use UniTask type.
|
||||||
|
|
||||||
Pooling Configuration
|
Pooling Configuration
|
||||||
---
|
---
|
||||||
UniTask aggressively caches async promise objects to achieve zero allocation (for 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)). By default, it caches all promises but you can configure `TaskPool.SetMaxPoolSize` to your value, the value indicates cache size per type. `TaskPool.GetCacheSizeInfo` returns currently cached objects in pool.
|
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
|
```csharp
|
||||||
foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||||
|
@ -1075,17 +839,17 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||||
|
|
||||||
Allocation on Profiler
|
Allocation on Profiler
|
||||||
---
|
---
|
||||||
In UnityEditor the profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generates AsyncStateMachine as class on Debug build and as struct on Release build.
|
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.
|
||||||
|
|
||||||
Unity supports Code Optimization option starting in 2020.1 (right, footer).
|
After Unity 2020.1 supports Code Optimization option on UnityEditor(right, footer).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can change C# compiler optimization to release to remove AsyncStateMachine allocation in development builds. This optimization option can also be set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
You can change C# compiler optimization to release, it removes AsyncStateMachine allocation. Andalso optimization option can set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
||||||
|
|
||||||
UniTaskSynchronizationContext
|
UniTaskSynchronizationContext
|
||||||
---
|
---
|
||||||
Unity's default SynchronizationContext(`UnitySynchronizationContext`) is a poor implementation for performance. UniTask bypasses `SynchronizationContext`(and `ExecutionContext`) so it does not use it but if exists in `async Task`, still used it. `UniTaskSynchronizationContext` is a replacement of `UnitySynchronizationContext` which is better for performance.
|
Unity's default SynchronizationContext(`UnitySynchronizationContext`) is poor implementation for performance. UniTask itself is bypass `SynchronizationContext`(and `ExecutionContext`) so does not use it but if exists in `async Task`, still used it. `UniTaskSynchronizationContext` is replacement of `UnitySynchronizationContext`, it is better for performance.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class SyncContextInjecter
|
public class SyncContextInjecter
|
||||||
|
@ -1098,19 +862,19 @@ public class SyncContextInjecter
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This is an optional choice and is not always recommended; `UniTaskSynchronizationContext` is less performant than `async UniTask` and is not a complete UniTask replacement. It also does not guarantee full behavioral compatibility with the `UnitySynchronizationContext`.
|
This is an optional choice and is not always recommended; `UniTaskSynchronizationContext` is less performance than `async UniTask` and is not a complete UniTask replacement. It also does not guarantee full behavioral compatibility with the `UnitySynchronizationContext`.
|
||||||
|
|
||||||
API References
|
API References
|
||||||
---
|
---
|
||||||
UniTask's API References are 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).
|
||||||
|
|
||||||
For example, UniTask's factory methods can be seen at [UniTask#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.UniTask.html#methods-1). UniTaskAsyncEnumerable's factory/extension methods can be seen at [UniTaskAsyncEnumerable#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.Linq.UniTaskAsyncEnumerable.html#methods-1).
|
For example, UniTask's factory methods can see at [UniTask#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.UniTask.html#methods-1). UniTaskAsyncEnumerable's factory/extension methods can see at [UniTaskAsyncEnumerable#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.Linq.UniTaskAsyncEnumerable.html#methods-1).
|
||||||
|
|
||||||
UPM Package
|
UPM Package
|
||||||
---
|
---
|
||||||
### Install via git URL
|
### Install via git URL
|
||||||
|
|
||||||
Requires a version of unity that supports path query parameter for git packages (Unity >= 2019.3.4f1, Unity >= 2020.1a21). You can add `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask` to Package Manager
|
After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of git package. You can add `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask` to Package Manager
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -1118,8 +882,15 @@ Requires a version of unity that supports path query parameter for git packages
|
||||||
|
|
||||||
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 uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
|
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.31`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.31`.
|
||||||
|
|
||||||
|
### Install via OpenUPM
|
||||||
|
|
||||||
|
The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
||||||
|
|
||||||
|
```
|
||||||
|
openupm add com.cysharp.unitask
|
||||||
|
```
|
||||||
|
|
||||||
.NET Core
|
.NET Core
|
||||||
---
|
---
|
||||||
|
@ -1127,11 +898,11 @@ For .NET Core, use NuGet.
|
||||||
|
|
||||||
> PM> Install-Package [UniTask](https://www.nuget.org/packages/UniTask)
|
> PM> Install-Package [UniTask](https://www.nuget.org/packages/UniTask)
|
||||||
|
|
||||||
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
|
UniTask of .NET Core version is a subset of Unity UniTask, removed PlayerLoop dependent methods.
|
||||||
|
|
||||||
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AsyncLocal` also does not work because it ignores ExecutionContext.
|
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AysncLocal` also does not work because it ignores ExecutionContext.
|
||||||
|
|
||||||
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
If you use UniTask internally, but provide ValueTask as an external API, you can write like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class ZeroAllocAsyncAwaitInDotNetCore
|
public class ZeroAllocAsyncAwaitInDotNetCore
|
||||||
|
@ -1164,7 +935,7 @@ public ValueTask TestAsync()
|
||||||
|
|
||||||
.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.
|
||||||
|
|
||||||
Utility methods such as WhenAll which are equivalent to UniTask are provided as [Cysharp/ValueTaskSupplement](https://github.com/Cysharp/ValueTaskSupplement).
|
Utility methods such as WhenAll which is equivalent to UniTask are provided as [Cysharp/ValueTaskSupplement](https://github.com/Cysharp/ValueTaskSupplement).
|
||||||
|
|
||||||
License
|
License
|
||||||
---
|
---
|
||||||
|
|
1170
README_CN.md
1170
README_CN.md
File diff suppressed because it is too large
Load Diff
|
@ -1,15 +1,13 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 17.0.31606.5
|
VisualStudioVersion = 16.0.29613.14
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniTask.NetCoreTests", "src\UniTask.NetCoreTests\UniTask.NetCoreTests.csproj", "{B3E311A4-70D8-4131-9965-C073A99D201A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniTask.NetCoreTests", "src\UniTask.NetCoreTests\UniTask.NetCoreTests.csproj", "{B3E311A4-70D8-4131-9965-C073A99D201A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniTask.NetCore", "src\UniTask.NetCore\UniTask.NetCore.csproj", "{16EE20D0-7FB1-483A-8467-A5EEDBF1F5BF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniTask.NetCore", "src\UniTask.NetCore\UniTask.NetCore.csproj", "{16EE20D0-7FB1-483A-8467-A5EEDBF1F5BF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniTask.NetCoreSandbox", "src\UniTask.NetCoreSandbox\UniTask.NetCoreSandbox.csproj", "{3915E72E-33E0-4A14-A6D8-872702200E58}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniTask.NetCoreSandbox", "src\UniTask.NetCoreSandbox\UniTask.NetCoreSandbox.csproj", "{3915E72E-33E0-4A14-A6D8-872702200E58}"
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniTask.Analyzer", "src\UniTask.Analyzer\UniTask.Analyzer.csproj", "{0AC6F052-A255-4EE3-9E05-1C02D49AB1C2}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -29,10 +27,6 @@ Global
|
||||||
{3915E72E-33E0-4A14-A6D8-872702200E58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3915E72E-33E0-4A14-A6D8-872702200E58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3915E72E-33E0-4A14-A6D8-872702200E58}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3915E72E-33E0-4A14-A6D8-872702200E58}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3915E72E-33E0-4A14-A6D8-872702200E58}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3915E72E-33E0-4A14-A6D8-872702200E58}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0AC6F052-A255-4EE3-9E05-1C02D49AB1C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0AC6F052-A255-4EE3-9E05-1C02D49AB1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0AC6F052-A255-4EE3-9E05-1C02D49AB1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0AC6F052-A255-4EE3-9E05-1C02D49AB1C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"profiles": {
|
|
||||||
"UniTask.Analyzer": {
|
|
||||||
"commandName": "DebugRoslynComponent",
|
|
||||||
"targetProject": "..\\UniTask.NetCoreSandbox\\UniTask.NetCoreSandbox.csproj"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>library</OutputType>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<IsRoslynComponent>true</IsRoslynComponent>
|
|
||||||
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs</TargetsForTfmSpecificContentInPackage>
|
|
||||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
|
||||||
<IncludeSymbols>false</IncludeSymbols>
|
|
||||||
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
|
|
||||||
<DevelopmentDependency>true</DevelopmentDependency>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2">
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PackBuildOutputs" DependsOnTargets="SatelliteDllsProjectOutputGroup;DebugSymbolsProjectOutputGroup">
|
|
||||||
<ItemGroup>
|
|
||||||
<TfmSpecificPackageFile Include="$(TargetDir)\*.dll" PackagePath="analyzers\dotnet\cs" />
|
|
||||||
<TfmSpecificPackageFile Include="@(SatelliteDllsProjectOutputGroupOutput->'%(FinalOutputPath)')" PackagePath="analyzers\dotnet\cs\%(SatelliteDllsProjectOutputGroupOutput.Culture)\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
|
@ -1,54 +0,0 @@
|
||||||
#pragma warning disable RS2008
|
|
||||||
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.Diagnostics;
|
|
||||||
using Microsoft.CodeAnalysis.Operations;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace UniTask.Analyzer
|
|
||||||
{
|
|
||||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
|
||||||
public class UniTaskAnalyzer : DiagnosticAnalyzer
|
|
||||||
{
|
|
||||||
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
|
|
||||||
id: "UNITASK001",
|
|
||||||
title: "UniTaskAnalyzer001: Must pass CancellationToken",
|
|
||||||
messageFormat: "Must pass CancellationToken",
|
|
||||||
category: "Usage",
|
|
||||||
defaultSeverity: DiagnosticSeverity.Error,
|
|
||||||
isEnabledByDefault: true,
|
|
||||||
description: "Pass CancellationToken or CancellationToken.None.");
|
|
||||||
|
|
||||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
|
|
||||||
|
|
||||||
public override void Initialize(AnalysisContext context)
|
|
||||||
{
|
|
||||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
|
||||||
context.EnableConcurrentExecution();
|
|
||||||
|
|
||||||
context.RegisterOperationAction(AnalyzeOperation, OperationKind.Invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AnalyzeOperation(OperationAnalysisContext context)
|
|
||||||
{
|
|
||||||
var token = context.Compilation.GetTypeByMetadataName(typeof(CancellationToken).FullName);
|
|
||||||
if (token == null) return;
|
|
||||||
|
|
||||||
if (context.Operation is IInvocationOperation invocation)
|
|
||||||
{
|
|
||||||
foreach (var arg in invocation.Arguments)
|
|
||||||
{
|
|
||||||
if (arg.ArgumentKind == ArgumentKind.DefaultValue)
|
|
||||||
{
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(arg.Parameter.Type, token))
|
|
||||||
{
|
|
||||||
var diagnostic = Diagnostic.Create(Rule, arg.Syntax.GetLocation());
|
|
||||||
context.ReportDiagnostic(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,5 @@
|
||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
|
||||||
#define SUPPORT_VALUETASK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SUPPORT_VALUETASK
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Sources;
|
using System.Threading.Tasks.Sources;
|
||||||
|
@ -16,7 +10,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public static ValueTask AsValueTask(this in UniTask task)
|
public static ValueTask AsValueTask(this in UniTask task)
|
||||||
{
|
{
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
@ -25,7 +19,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
||||||
{
|
{
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
@ -42,7 +36,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
await task;
|
await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
|
|
||||||
class UniTaskValueTaskSource : IValueTaskSource
|
class UniTaskValueTaskSource : IValueTaskSource
|
||||||
{
|
{
|
||||||
|
@ -101,4 +95,3 @@ namespace Cysharp.Threading.Tasks
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
|
@ -62,8 +62,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
||||||
{
|
{
|
||||||
static TaskPool<ThreadPoolWorkItem> pool;
|
static TaskPool<ThreadPoolWorkItem> pool;
|
||||||
ThreadPoolWorkItem nextNode;
|
public ThreadPoolWorkItem NextNode { get; set; }
|
||||||
public ref ThreadPoolWorkItem NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static ThreadPoolWorkItem()
|
static ThreadPoolWorkItem()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net7.0;netstandard2.1;netstandard2.0</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>
|
||||||
<DefineConstants>UNITASK_NETCORE</DefineConstants>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
|
||||||
|
|
||||||
<!-- NuGet Packaging -->
|
<!-- NuGet Packaging -->
|
||||||
<Id>UniTask</Id>
|
<Id>UniTask</Id>
|
||||||
|
@ -22,9 +19,6 @@
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Icon.png</PackageIcon>
|
<PackageIcon>Icon.png</PackageIcon>
|
||||||
<SignAssembly>true</SignAssembly>
|
|
||||||
<AssemblyOriginatorKeyFile>opensource.snk</AssemblyOriginatorKeyFile>
|
|
||||||
<IsPackable>true</IsPackable>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -32,8 +26,29 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs" Exclude="
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Triggers\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Linq\UnityExtensions\*.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityEqualityComparer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\DiagnosticsExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\PlayerLoopRunner.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\ContinuationQueue.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityWebRequestExtensions.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\TimeoutController.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopTimer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Bridge.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.WaitUntil.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.*;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
" />
|
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs"
|
||||||
<Compile Remove="..\UniTask\Assets\Plugins\UniTask\Runtime\_InternalVisibleTo.cs" />
|
Exclude="
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Triggers\*.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Linq\UnityExtensions\*.cs;
|
||||||
|
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityEqualityComparer.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\DiagnosticsExtensions.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\PlayerLoopRunner.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\ContinuationQueue.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityWebRequestExtensions.cs;
|
||||||
|
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Bridge.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.WaitUntil.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.*;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
|
||||||
|
" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,258 @@
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using System.Linq;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Exporters;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using PooledAwait;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Cysharp.Threading.Tasks.CompilerServices;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
[Config(typeof(BenchmarkConfig))]
|
||||||
|
public class AllocationCheck
|
||||||
|
{
|
||||||
|
// note: all the benchmarks use Task/Task<T> for the public API, because BenchmarkDotNet
|
||||||
|
// doesn't work reliably with more exotic task-types (even just ValueTask fails); instead,
|
||||||
|
// we'll obscure the cost of the outer awaitable by doing a relatively large number of
|
||||||
|
// iterations, so that we're only really measuring the inner loop
|
||||||
|
private const int InnerOps = 1000;
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps)]
|
||||||
|
public async Task ViaUniTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
{
|
||||||
|
var a = Core();
|
||||||
|
var b = Core();
|
||||||
|
var c = Core();
|
||||||
|
await a;
|
||||||
|
await b;
|
||||||
|
await c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTask Core()
|
||||||
|
{
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps)]
|
||||||
|
public async Task<int> ViaUniTaskT()
|
||||||
|
{
|
||||||
|
var sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
{
|
||||||
|
var a = Core();
|
||||||
|
var b = Core();
|
||||||
|
var c = Core();
|
||||||
|
sum += await a;
|
||||||
|
sum += await b;
|
||||||
|
sum += await c;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async UniTask<int> Core()
|
||||||
|
{
|
||||||
|
var a = await new TestAwaiter<int>(false, UniTaskStatus.Succeeded, 10);
|
||||||
|
var b = await new TestAwaiter<int>(false, UniTaskStatus.Succeeded, 10);
|
||||||
|
var c = await new TestAwaiter<int>(false, UniTaskStatus.Succeeded, 10);
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Benchmark(OperationsPerInvoke = InnerOps)]
|
||||||
|
//[Benchmark]
|
||||||
|
public void ViaUniTaskVoid()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
{
|
||||||
|
Core().Forget();
|
||||||
|
Core().Forget();
|
||||||
|
Core().Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTaskVoid Core()
|
||||||
|
{
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo : IAsyncStateMachine
|
||||||
|
{
|
||||||
|
public AsyncUniTaskVoidMethodBuilder builder;
|
||||||
|
public TestAwaiter awaiter;
|
||||||
|
public TestAwaiter awaiterawaiter;
|
||||||
|
|
||||||
|
public int state;
|
||||||
|
|
||||||
|
public void MoveNext()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
awaiterawaiter = awaiter.GetAwaiter();
|
||||||
|
if (awaiterawaiter.IsCompleted)
|
||||||
|
{
|
||||||
|
goto case 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
builder.AwaitUnsafeOnCompleted(ref awaiterawaiter, ref this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
|
||||||
|
END:
|
||||||
|
builder.SetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStateMachine(IAsyncStateMachine stateMachine)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TaskTestException : Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct TestAwaiter : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
readonly UniTaskStatus status;
|
||||||
|
readonly bool isCompleted;
|
||||||
|
|
||||||
|
public TestAwaiter(bool isCompleted, UniTaskStatus status)
|
||||||
|
{
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestAwaiter GetAwaiter() => this;
|
||||||
|
|
||||||
|
public bool IsCompleted => isCompleted;
|
||||||
|
|
||||||
|
public void GetResult()
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case UniTaskStatus.Faulted:
|
||||||
|
throw new TaskTestException();
|
||||||
|
case UniTaskStatus.Canceled:
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
case UniTaskStatus.Pending:
|
||||||
|
case UniTaskStatus.Succeeded:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(ThreadPoolWorkItem.Create(continuation), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(ThreadPoolWorkItem.Create(continuation), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct TestAwaiter<T> : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
readonly UniTaskStatus status;
|
||||||
|
readonly bool isCompleted;
|
||||||
|
readonly T value;
|
||||||
|
|
||||||
|
public TestAwaiter(bool isCompleted, UniTaskStatus status, T value)
|
||||||
|
{
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
this.status = status;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestAwaiter<T> GetAwaiter() => this;
|
||||||
|
|
||||||
|
public bool IsCompleted => isCompleted;
|
||||||
|
|
||||||
|
public T GetResult()
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case UniTaskStatus.Faulted:
|
||||||
|
throw new TaskTestException();
|
||||||
|
case UniTaskStatus.Canceled:
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
case UniTaskStatus.Pending:
|
||||||
|
case UniTaskStatus.Succeeded:
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(ThreadPoolWorkItem.Create(continuation), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(ThreadPoolWorkItem.Create(continuation), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ThreadPoolWorkItem : IThreadPoolWorkItem
|
||||||
|
{
|
||||||
|
public static readonly ConcurrentQueue<ThreadPoolWorkItem> pool = new ConcurrentQueue<ThreadPoolWorkItem>();
|
||||||
|
|
||||||
|
public static void CreatePoolItems(int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
pool.Enqueue(new ThreadPoolWorkItem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Action continuation;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ThreadPoolWorkItem Create(Action continuation)
|
||||||
|
{
|
||||||
|
if (!pool.TryDequeue(out var item))
|
||||||
|
{
|
||||||
|
item = new ThreadPoolWorkItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
item.continuation = continuation;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
var call = continuation;
|
||||||
|
continuation = null;
|
||||||
|
pool.Enqueue(this);
|
||||||
|
|
||||||
|
call.Invoke();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,283 @@
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using System.Linq;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Exporters;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using PooledAwait;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Cysharp.Threading.Tasks.CompilerServices;
|
||||||
|
|
||||||
|
//class Program
|
||||||
|
//{
|
||||||
|
// static void Main(string[] args)
|
||||||
|
// {
|
||||||
|
// var switcher = new BenchmarkSwitcher(new[]
|
||||||
|
// {
|
||||||
|
// typeof(StandardBenchmark)
|
||||||
|
// });
|
||||||
|
|
||||||
|
//#if DEBUG
|
||||||
|
// var b = new StandardBenchmark();
|
||||||
|
|
||||||
|
//#else
|
||||||
|
// switcher.Run(args);
|
||||||
|
//#endif
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public class BenchmarkConfig : ManualConfig
|
||||||
|
{
|
||||||
|
public BenchmarkConfig()
|
||||||
|
{
|
||||||
|
AddDiagnoser(MemoryDiagnoser.Default);
|
||||||
|
AddJob(Job.ShortRun.WithLaunchCount(1).WithIterationCount(1).WithWarmupCount(1)/*.RunOncePerIteration()*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// borrowed from PooledAwait
|
||||||
|
|
||||||
|
[Config(typeof(BenchmarkConfig))]
|
||||||
|
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
|
||||||
|
[CategoriesColumn]
|
||||||
|
public class ComparisonBenchmarks
|
||||||
|
{
|
||||||
|
// note: all the benchmarks use Task/Task<T> for the public API, because BenchmarkDotNet
|
||||||
|
// doesn't work reliably with more exotic task-types (even just ValueTask fails); instead,
|
||||||
|
// we'll obscure the cost of the outer awaitable by doing a relatively large number of
|
||||||
|
// iterations, so that we're only really measuring the inner loop
|
||||||
|
private const int InnerOps = 1000;
|
||||||
|
|
||||||
|
public bool ConfigureAwait { get; set; } = false;
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = ".NET")]
|
||||||
|
[BenchmarkCategory("Task<T>")]
|
||||||
|
public async Task<int> ViaTaskT()
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
sum += await Inner(1, 2).ConfigureAwait(ConfigureAwait);
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async Task<int> Inner(int x, int y)
|
||||||
|
{
|
||||||
|
int i = x;
|
||||||
|
await Task.Yield();
|
||||||
|
i *= y;
|
||||||
|
await Task.Yield();
|
||||||
|
return 5 * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = ".NET")]
|
||||||
|
[BenchmarkCategory("Task")]
|
||||||
|
public async Task ViaTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
await Inner().ConfigureAwait(ConfigureAwait);
|
||||||
|
|
||||||
|
static async Task Inner()
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = ".NET")]
|
||||||
|
[BenchmarkCategory("ValueTask<T>")]
|
||||||
|
public async Task<int> ViaValueTaskT()
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
sum += await Inner(1, 2).ConfigureAwait(ConfigureAwait);
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async ValueTask<int> Inner(int x, int y)
|
||||||
|
{
|
||||||
|
int i = x;
|
||||||
|
await Task.Yield();
|
||||||
|
i *= y;
|
||||||
|
await Task.Yield();
|
||||||
|
return 5 * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = ".NET")]
|
||||||
|
[BenchmarkCategory("ValueTask")]
|
||||||
|
public async Task ViaValueTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
await Inner().ConfigureAwait(ConfigureAwait);
|
||||||
|
|
||||||
|
static async ValueTask Inner()
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "Pooled")]
|
||||||
|
[BenchmarkCategory("ValueTask<T>")]
|
||||||
|
public async Task<int> ViaPooledValueTaskT()
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
sum += await Inner(1, 2).ConfigureAwait(ConfigureAwait);
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async PooledValueTask<int> Inner(int x, int y)
|
||||||
|
{
|
||||||
|
int i = x;
|
||||||
|
await Task.Yield();
|
||||||
|
i *= y;
|
||||||
|
await Task.Yield();
|
||||||
|
return 5 * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "Pooled")]
|
||||||
|
[BenchmarkCategory("ValueTask")]
|
||||||
|
public async Task ViaPooledValueTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
await Inner().ConfigureAwait(ConfigureAwait);
|
||||||
|
|
||||||
|
static async PooledValueTask Inner()
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "Pooled")]
|
||||||
|
[BenchmarkCategory("Task<T>")]
|
||||||
|
public async Task<int> ViaPooledTaskT()
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
sum += await Inner(1, 2).ConfigureAwait(ConfigureAwait);
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async PooledTask<int> Inner(int x, int y)
|
||||||
|
{
|
||||||
|
int i = x;
|
||||||
|
await Task.Yield();
|
||||||
|
i *= y;
|
||||||
|
await Task.Yield();
|
||||||
|
return 5 * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "Pooled")]
|
||||||
|
[BenchmarkCategory("Task")]
|
||||||
|
public async Task ViaPooledTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
await Inner().ConfigureAwait(ConfigureAwait);
|
||||||
|
|
||||||
|
static async PooledTask Inner()
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
//[Benchmark(OperationsPerInvoke = InnerOps, Description = "UniTaskVoid")]
|
||||||
|
//[BenchmarkCategory("UniTask")]
|
||||||
|
//public async Task ViaUniTaskVoid()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < InnerOps; i++)
|
||||||
|
// {
|
||||||
|
// await Inner();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static async UniTaskVoid Inner()
|
||||||
|
// {
|
||||||
|
// await UniTask.Yield();
|
||||||
|
// await UniTask.Yield();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "UniTask")]
|
||||||
|
[BenchmarkCategory("UniTask")]
|
||||||
|
public async Task ViaUniTask()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
{
|
||||||
|
await Inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTask Inner()
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = InnerOps, Description = "UniTaskT")]
|
||||||
|
[BenchmarkCategory("UniTask")]
|
||||||
|
public async Task<int> ViaUniTaskT()
|
||||||
|
{
|
||||||
|
var sum = 0;
|
||||||
|
for (int i = 0; i < InnerOps; i++)
|
||||||
|
{
|
||||||
|
sum += await Inner(1, 2);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
static async UniTask<int> Inner(int x, int y)
|
||||||
|
{
|
||||||
|
int i = x;
|
||||||
|
await UniTask.Yield();
|
||||||
|
i *= y;
|
||||||
|
await UniTask.Yield();
|
||||||
|
return 5 * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct MyAwaiter : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
public MyAwaiter GetAwaiter() => this;
|
||||||
|
|
||||||
|
public bool IsCompleted => false;
|
||||||
|
|
||||||
|
public void GetResult()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
continuation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
continuation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct MyTestStateMachine : IAsyncStateMachine
|
||||||
|
{
|
||||||
|
public void MoveNext()
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStateMachine(IAsyncStateMachine stateMachine)
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,34 +17,499 @@ using System.Reactive.Concurrency;
|
||||||
|
|
||||||
namespace NetCoreSandbox
|
namespace NetCoreSandbox
|
||||||
{
|
{
|
||||||
public class Program
|
public class MySyncContext : SynchronizationContext
|
||||||
{
|
{
|
||||||
static async Task Main(string[] args)
|
public MySyncContext()
|
||||||
{
|
{
|
||||||
var cts = new CancellationTokenSource();
|
}
|
||||||
|
|
||||||
|
public override void Post(SendOrPostCallback d, object state)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Called SyncContext Post!");
|
||||||
|
base.Post(d, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Text
|
||||||
|
{
|
||||||
|
|
||||||
|
public string text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ZeroAllocAsyncAwaitInDotNetCore
|
||||||
|
{
|
||||||
|
public ValueTask<int> NanikaAsync(int x, int y)
|
||||||
|
{
|
||||||
|
return Core(this, x, y);
|
||||||
|
|
||||||
|
static async UniTask<int> Core(ZeroAllocAsyncAwaitInDotNetCore self, int x, int y)
|
||||||
|
{
|
||||||
|
// nanika suru...
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(x + y));
|
||||||
|
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// OK.
|
public class TaskTestException : Exception
|
||||||
await FooAsync(10, cts.Token);
|
{
|
||||||
|
|
||||||
// NG(Compiler Error)
|
|
||||||
// await FooAsync(10);
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
public async UniTask MethodFooAsync()
|
||||||
|
{
|
||||||
|
await MethodBarAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async UniTask MethodBarAsync()
|
||||||
|
|
||||||
|
{
|
||||||
|
Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Throw()
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct TestAwaiter : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
readonly UniTaskStatus status;
|
||||||
|
readonly bool isCompleted;
|
||||||
|
|
||||||
|
public TestAwaiter(bool isCompleted, UniTaskStatus status)
|
||||||
|
{
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestAwaiter GetAwaiter() => this;
|
||||||
|
|
||||||
|
public bool IsCompleted => isCompleted;
|
||||||
|
|
||||||
|
public void GetResult()
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case UniTaskStatus.Faulted:
|
||||||
|
throw new TaskTestException();
|
||||||
|
case UniTaskStatus.Canceled:
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
case UniTaskStatus.Pending:
|
||||||
|
case UniTaskStatus.Succeeded:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.QueueUserWorkItem(_ => continuation(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct TestAwaiter<T> : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
readonly UniTaskStatus status;
|
||||||
|
readonly bool isCompleted;
|
||||||
|
readonly T value;
|
||||||
|
|
||||||
|
public TestAwaiter(bool isCompleted, UniTaskStatus status, T value)
|
||||||
|
{
|
||||||
|
this.isCompleted = isCompleted;
|
||||||
|
this.status = status;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestAwaiter<T> GetAwaiter() => this;
|
||||||
|
|
||||||
|
public bool IsCompleted => isCompleted;
|
||||||
|
|
||||||
|
public T GetResult()
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case UniTaskStatus.Faulted:
|
||||||
|
throw new TaskTestException();
|
||||||
|
case UniTaskStatus.Canceled:
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
case UniTaskStatus.Pending:
|
||||||
|
case UniTaskStatus.Succeeded:
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.QueueUserWorkItem(_ => continuation(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static partial class UnityUIComponentExtensions
|
||||||
|
{
|
||||||
|
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text)
|
||||||
|
{
|
||||||
|
AAAACORECORE(source, text).Forget();
|
||||||
|
|
||||||
|
async UniTaskVoid AAAACORECORE(IUniTaskAsyncEnumerable<string> source2, Text text2)
|
||||||
|
{
|
||||||
|
var e = source2.GetAsyncEnumerator();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await e.MoveNextAsync())
|
||||||
|
{
|
||||||
|
text2.text = e.Current;
|
||||||
|
// action(e.Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
await e.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static IDisposable SubscribeToText<T>(this IObservable<T> source, Text text)
|
||||||
|
//{
|
||||||
|
// return source.SubscribeWithState(text, (x, t) => t.text = x.ToString());
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public static IDisposable SubscribeToText<T>(this IObservable<T> source, Text text, Func<T, string> selector)
|
||||||
|
//{
|
||||||
|
// return source.SubscribeWithState2(text, selector, (x, t, s) => t.text = s(x));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public static IDisposable SubscribeToInteractable(this IObservable<bool> source, Selectable selectable)
|
||||||
|
//{
|
||||||
|
// return source.SubscribeWithState(selectable, (x, s) => s.interactable = x);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static string FlattenGenArgs(Type type)
|
||||||
|
{
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
var t = string.Join(", ", type.GetGenericArguments().Select(x => FlattenGenArgs(x)));
|
||||||
|
return Regex.Replace(type.Name, "`.+", "") + "<" + t + ">";
|
||||||
|
}
|
||||||
|
//x.ReturnType.GetGenericArguments()
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return type.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async IAsyncEnumerable<int> FooAsync([EnumeratorCancellation]CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
yield return 1;
|
||||||
|
await Task.Delay(10, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MyDisposable : IDisposable
|
||||||
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Test()
|
||||||
|
{
|
||||||
|
var disp = new MyDisposable();
|
||||||
|
|
||||||
|
using var _ = new MyDisposable();
|
||||||
|
|
||||||
|
Console.WriteLine("tako");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static async UniTask FooBarAsync()
|
||||||
|
{
|
||||||
|
await using (UniTask.ReturnToCurrentSynchronizationContext())
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async UniTask FooAsync(int x, CancellationToken cancellationToken = default)
|
|
||||||
|
|
||||||
|
|
||||||
|
static async UniTask Aaa()
|
||||||
|
{
|
||||||
|
await FooBarAsync();
|
||||||
|
|
||||||
|
Console.WriteLine("FooBarAsync End");
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTask WhereSelect()
|
||||||
|
{
|
||||||
|
await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10)
|
||||||
|
.SelectAwait(async x =>
|
||||||
|
{
|
||||||
|
await UniTask.Yield();
|
||||||
|
return x;
|
||||||
|
})
|
||||||
|
.Where(x => x % 2 == 0))
|
||||||
|
{
|
||||||
|
Console.WriteLine(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//await new AllocationCheck().ViaUniTaskVoid();
|
||||||
|
//Console.ReadLine();
|
||||||
|
BenchmarkDotNet.Running.BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
|
||||||
|
|
||||||
|
//await new ComparisonBenchmarks().ViaUniTaskT();
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var e = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Start {i}");
|
||||||
|
await writer.YieldAsync(i);
|
||||||
|
Console.WriteLine($"End {i}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ee = e.GetAsyncEnumerator();
|
||||||
|
while (await ee.MoveNextAsync())
|
||||||
|
{
|
||||||
|
Console.WriteLine("ForEach " + ee.Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTask YieldCore()
|
||||||
{
|
{
|
||||||
await UniTask.Yield();
|
await UniTask.Yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998
|
||||||
|
|
||||||
|
|
||||||
|
static async UniTask<int> AsyncTest()
|
||||||
|
{
|
||||||
|
// empty
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(true, UniTaskStatus.Succeeded);
|
||||||
|
await new TestAwaiter(false, UniTaskStatus.Succeeded);
|
||||||
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma warning restore CS1998
|
||||||
|
|
||||||
|
void Foo()
|
||||||
|
{
|
||||||
|
|
||||||
|
// AsyncEnumerable.Range(1,10).Do(
|
||||||
|
|
||||||
|
// AsyncEnumerable.t
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine(@"using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
{
|
||||||
|
");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var chako = typeof(AsyncEnumerable).GetMethods()
|
||||||
|
.OrderBy(x => x.Name)
|
||||||
|
.Select(x =>
|
||||||
|
{
|
||||||
|
var ret = FlattenGenArgs(x.ReturnType);
|
||||||
|
|
||||||
|
|
||||||
|
var generics = string.Join(", ", x.GetGenericArguments().Select(x => x.Name));
|
||||||
|
|
||||||
|
if (x.GetParameters().Length == 0) return "";
|
||||||
|
|
||||||
|
var self = x.GetParameters().First();
|
||||||
|
if (x.GetCustomAttributes(typeof(ExtensionAttribute), true).Length == 0)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
var arg1Type = FlattenGenArgs(x.GetParameters().First().ParameterType);
|
||||||
|
|
||||||
|
var others = string.Join(", ", x.GetParameters().Skip(1).Select(y => FlattenGenArgs(y.ParameterType) + " " + y.Name));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(others))
|
||||||
|
{
|
||||||
|
others = ", " + others;
|
||||||
|
}
|
||||||
|
|
||||||
|
var template = $"public static {ret} {x.Name}<{generics}>(this {arg1Type} {self.Name}{others})";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return template.Replace("ValueTask", "UniTask").Replace("IAsyncEnumerable", "IUniTaskAsyncEnumerable").Replace("<>", "");
|
||||||
|
})
|
||||||
|
.Where(x => x != "")
|
||||||
|
.Select(x => x + "\r\n{\r\n throw new NotImplementedException();\r\n}")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var huga = string.Join("\r\n\r\n", chako);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var item in typeof(AsyncEnumerable).GetMethods().Select(x => x.Name).Distinct())
|
||||||
|
{
|
||||||
|
if (item.EndsWith("AwaitAsync") || item.EndsWith("AwaitWithCancellationAsync") || item.EndsWith("WithCancellation"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item2 = item.Replace("Async", "");
|
||||||
|
item2 = item2.Replace("Await", "");
|
||||||
|
|
||||||
|
var format = @"
|
||||||
|
internal sealed class {0}
|
||||||
|
{{
|
||||||
|
}}
|
||||||
|
";
|
||||||
|
|
||||||
|
sb.Append(string.Format(format, item2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append("}");
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine(sb.ToString());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static async IAsyncEnumerable<int> AsyncGen()
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
yield return 10;
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
yield return 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyEnumerable : IEnumerable<int>
|
||||||
|
{
|
||||||
|
public IEnumerator<int> GetEnumerator()
|
||||||
|
{
|
||||||
|
return new MyEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyEnumerator : IEnumerator<int>
|
||||||
|
{
|
||||||
|
public int Current => throw new NotImplementedException();
|
||||||
|
|
||||||
|
object IEnumerator.Current => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Called Dispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class MyClass<T>
|
||||||
|
{
|
||||||
|
public CustomAsyncEnumerator<T> GetAsyncEnumerator()
|
||||||
|
{
|
||||||
|
//IAsyncEnumerable
|
||||||
|
return new CustomAsyncEnumerator<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public struct CustomAsyncEnumerator<T>
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
public T Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
if (count++ == 3)
|
||||||
|
{
|
||||||
|
return UniTask.FromResult(false);
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
return UniTask.FromResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
[Config(typeof(BenchmarkConfig))]
|
||||||
|
public class QueueCheck
|
||||||
|
{
|
||||||
|
Node node1 = new Node();
|
||||||
|
Node node2 = new Node();
|
||||||
|
Queue<Node> q1 = new Queue<Node>();
|
||||||
|
Stack<Node> s1 = new Stack<Node>();
|
||||||
|
ConcurrentQueue<Node> cq = new ConcurrentQueue<Node>();
|
||||||
|
ConcurrentStack<Node> cs = new ConcurrentStack<Node>();
|
||||||
|
static TaskPool<Node> pool;
|
||||||
|
static TaskPoolEqualNull<Node> poolEqualNull;
|
||||||
|
static TaskPoolClass<Node> poolClass = new TaskPoolClass<Node>();
|
||||||
|
static TaskPoolWithoutSize<Node> poolWithoutSize;
|
||||||
|
static TaskPoolWithoutLock<Node> poolWithoutLock;
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Queue()
|
||||||
|
{
|
||||||
|
q1.Enqueue(node1);
|
||||||
|
q1.Enqueue(node1);
|
||||||
|
q1.TryDequeue(out _);
|
||||||
|
q1.TryDequeue(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void QueueLock()
|
||||||
|
{
|
||||||
|
lock (q1) { q1.Enqueue(node1); }
|
||||||
|
lock (q1) { q1.Enqueue(node1); }
|
||||||
|
lock (q1) { q1.TryDequeue(out _); }
|
||||||
|
lock (q1) { q1.TryDequeue(out _); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Stack()
|
||||||
|
{
|
||||||
|
s1.Push(node1);
|
||||||
|
s1.Push(node2);
|
||||||
|
s1.TryPop(out _);
|
||||||
|
s1.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void StackLock()
|
||||||
|
{
|
||||||
|
lock (s1) { s1.Push(node1); }
|
||||||
|
lock (s1) { s1.Push(node2); }
|
||||||
|
lock (s1) { s1.TryPop(out _); }
|
||||||
|
lock (s1) { s1.TryPop(out _); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void ConcurrentQueue()
|
||||||
|
{
|
||||||
|
cq.Enqueue(node1);
|
||||||
|
cq.Enqueue(node1);
|
||||||
|
cq.TryDequeue(out _);
|
||||||
|
cq.TryDequeue(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void ConcurrentStack()
|
||||||
|
{
|
||||||
|
cs.Push(node1);
|
||||||
|
cs.Push(node2);
|
||||||
|
cs.TryPop(out _);
|
||||||
|
cs.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskPool()
|
||||||
|
{
|
||||||
|
pool.TryPush(node1);
|
||||||
|
pool.TryPush(node2);
|
||||||
|
pool.TryPop(out _);
|
||||||
|
pool.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskPoolEqualNull()
|
||||||
|
{
|
||||||
|
poolEqualNull.TryPush(node1);
|
||||||
|
poolEqualNull.TryPush(node2);
|
||||||
|
poolEqualNull.TryPop(out _);
|
||||||
|
poolEqualNull.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskPoolClass()
|
||||||
|
{
|
||||||
|
poolClass.TryPush(node1);
|
||||||
|
poolClass.TryPush(node2);
|
||||||
|
poolClass.TryPop(out _);
|
||||||
|
poolClass.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskPoolWithoutSize()
|
||||||
|
{
|
||||||
|
poolWithoutSize.TryPush(node1);
|
||||||
|
poolWithoutSize.TryPush(node2);
|
||||||
|
poolWithoutSize.TryPop(out _);
|
||||||
|
poolWithoutSize.TryPop(out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskPoolWithoutLock()
|
||||||
|
{
|
||||||
|
poolWithoutLock.TryPush(node1);
|
||||||
|
poolWithoutLock.TryPush(node2);
|
||||||
|
poolWithoutLock.TryPop(out _);
|
||||||
|
poolWithoutLock.TryPop(out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Node : ITaskPoolNode<Node>
|
||||||
|
{
|
||||||
|
public Node NextNode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
T NextNode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutable struct, don't mark readonly.
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
public struct TaskPoolWithoutLock<T>
|
||||||
|
where T : class, ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
T root;
|
||||||
|
|
||||||
|
public int Size => size;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPop(out T result)
|
||||||
|
{
|
||||||
|
//if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
var v = root;
|
||||||
|
if (!(v is null))
|
||||||
|
{
|
||||||
|
root = v.NextNode;
|
||||||
|
v.NextNode = null;
|
||||||
|
size--;
|
||||||
|
result = v;
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPush(T item)
|
||||||
|
{
|
||||||
|
//if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
//if (size < TaskPool.MaxPoolSize)
|
||||||
|
{
|
||||||
|
item.NextNode = root;
|
||||||
|
root = item;
|
||||||
|
size++;
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
public struct TaskPool<T>
|
||||||
|
where T : class, ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
int gate;
|
||||||
|
int size;
|
||||||
|
T root;
|
||||||
|
|
||||||
|
public int Size => size;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPop(out T result)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
var v = root;
|
||||||
|
if (!(v is null))
|
||||||
|
{
|
||||||
|
root = v.NextNode;
|
||||||
|
v.NextNode = null;
|
||||||
|
size--;
|
||||||
|
result = v;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPush(T item)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
//if (size < TaskPool.MaxPoolSize)
|
||||||
|
{
|
||||||
|
item.NextNode = root;
|
||||||
|
root = item;
|
||||||
|
size++;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
public struct TaskPoolEqualNull<T>
|
||||||
|
where T : class, ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
int gate;
|
||||||
|
int size;
|
||||||
|
T root;
|
||||||
|
|
||||||
|
public int Size => size;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPop(out T result)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
var v = root;
|
||||||
|
if (v != null)
|
||||||
|
{
|
||||||
|
root = v.NextNode;
|
||||||
|
v.NextNode = null;
|
||||||
|
size--;
|
||||||
|
result = v;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPush(T item)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
//if (size < TaskPool.MaxPoolSize)
|
||||||
|
{
|
||||||
|
item.NextNode = root;
|
||||||
|
root = item;
|
||||||
|
size++;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TaskPoolClass<T>
|
||||||
|
where T : class, ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
int gate;
|
||||||
|
int size;
|
||||||
|
T root;
|
||||||
|
|
||||||
|
public int Size => size;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPop(out T result)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
var v = root;
|
||||||
|
if (!(v is null))
|
||||||
|
{
|
||||||
|
root = v.NextNode;
|
||||||
|
v.NextNode = null;
|
||||||
|
size--;
|
||||||
|
result = v;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPush(T item)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
//if (size < TaskPool.MaxPoolSize)
|
||||||
|
{
|
||||||
|
item.NextNode = root;
|
||||||
|
root = item;
|
||||||
|
size++;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
public struct TaskPoolWithoutSize<T>
|
||||||
|
where T : class, ITaskPoolNode<T>
|
||||||
|
{
|
||||||
|
int gate;
|
||||||
|
T root;
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPop(out T result)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
var v = root;
|
||||||
|
if (!(v is null))
|
||||||
|
{
|
||||||
|
root = v.NextNode;
|
||||||
|
v.NextNode = null;
|
||||||
|
result = v;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
result = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryPush(T item)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
//if (size < TaskPool.MaxPoolSize)
|
||||||
|
{
|
||||||
|
item.NextNode = root;
|
||||||
|
root = item;
|
||||||
|
Volatile.Write(ref gate, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// Volatile.Write(ref gate, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<RootNamespace>NetCoreSandbox</RootNamespace>
|
<RootNamespace>NetCoreSandbox</RootNamespace>
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -16,12 +15,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\UniTask.NetCore\UniTask.NetCore.csproj" />
|
<ProjectReference Include="..\UniTask.NetCore\UniTask.NetCore.csproj" />
|
||||||
|
|
||||||
|
|
||||||
<ProjectReference Include="..\UniTask.Analyzer\UniTask.Analyzer.csproj">
|
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
||||||
<OutputItemType>Analyzer</OutputItemType>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace NetCoreTests
|
||||||
|
|
||||||
var ar = await array;
|
var ar = await array;
|
||||||
|
|
||||||
ar.Should().Equal(new[] { 99, 100, 100, 100, 131 });
|
ar.Should().BeEquivalentTo(new[] { 99, 100, 100, 100, 131 });
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -49,7 +49,7 @@ namespace NetCoreTests
|
||||||
|
|
||||||
var ar = await array;
|
var ar = await array;
|
||||||
|
|
||||||
ar.Should().Equal(new[] { 100, 100, 100, 131, 191 });
|
ar.Should().BeEquivalentTo(new[] { 100, 100, 100, 131, 191 });
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
//[Fact]
|
||||||
|
@ -70,7 +70,7 @@ namespace NetCoreTests
|
||||||
|
|
||||||
// var ar = await array;
|
// var ar = await array;
|
||||||
|
|
||||||
// ar.Should().Equal(new[] { 99, 100, 100, 100, 131 });
|
// ar.Should().BeEquivalentTo(new[] { 99, 100, 100, 100, 131 });
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//[Fact]
|
//[Fact]
|
||||||
|
@ -88,7 +88,7 @@ namespace NetCoreTests
|
||||||
|
|
||||||
// var ar = await array;
|
// var ar = await array;
|
||||||
|
|
||||||
// ar.Should().Equal(new[] { 100, 100, 100, 131, 191 });
|
// ar.Should().BeEquivalentTo(new[] { 100, 100, 100, 131, 191 });
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -276,8 +276,8 @@ namespace NetCoreTests
|
||||||
reference.Writer.TryComplete();
|
reference.Writer.TryComplete();
|
||||||
channel.Writer.TryComplete();
|
channel.Writer.TryComplete();
|
||||||
|
|
||||||
(await ta1).Should().Equal(new[] { 10, 20, 30 });
|
(await ta1).Should().BeEquivalentTo(new[] { 10, 20, 30 });
|
||||||
(await ta2).Should().Equal(new[] { 10, 20, 30 });
|
(await ta2).Should().BeEquivalentTo(new[] { 10, 20, 30 });
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -481,7 +481,7 @@ namespace NetCoreTests.Linq
|
||||||
list.Add(x);
|
list.Add(x);
|
||||||
});
|
});
|
||||||
|
|
||||||
list.Should().Equal(Enumerable.Range(1, 10));
|
list.Should().BeEquivalentTo(Enumerable.Range(1, 10));
|
||||||
|
|
||||||
var list2 = new List<(int, int)>();
|
var list2 = new List<(int, int)>();
|
||||||
await Enumerable.Range(5, 10).ToUniTaskAsyncEnumerable().ForEachAsync((index, x) =>
|
await Enumerable.Range(5, 10).ToUniTaskAsyncEnumerable().ForEachAsync((index, x) =>
|
||||||
|
@ -490,7 +490,7 @@ namespace NetCoreTests.Linq
|
||||||
});
|
});
|
||||||
|
|
||||||
var list3 = Enumerable.Range(5, 10).Select((index, x) => (index, x)).ToArray();
|
var list3 = Enumerable.Range(5, 10).Select((index, x) => (index, x)).ToArray();
|
||||||
list2.Should().Equal(list3);
|
list2.Should().BeEquivalentTo(list3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Append(99).ToArrayAsync();
|
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Append(99).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(start, count).Append(99).ToArray();
|
var ys = Enumerable.Range(start, count).Append(99).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -50,7 +50,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Prepend(99).ToArrayAsync();
|
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Prepend(99).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(start, count).Prepend(99).ToArray();
|
var ys = Enumerable.Range(start, count).Prepend(99).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -85,7 +85,7 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
var xs = await l.ToUniTaskAsyncEnumerable().Concat(r.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
var xs = await l.ToUniTaskAsyncEnumerable().Concat(r.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
||||||
var ys = l.Concat(r).ToArray();
|
var ys = l.Concat(r).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -119,17 +119,17 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, 0).DefaultIfEmpty(99).ToArray();
|
var ys = Enumerable.Range(1, 0).DefaultIfEmpty(99).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
var xs = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, 1).DefaultIfEmpty(99).ToArray();
|
var ys = Enumerable.Range(1, 1).DefaultIfEmpty(99).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
var xs = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, 10).DefaultIfEmpty(99).ToArray();
|
var ys = Enumerable.Range(1, 10).DefaultIfEmpty(99).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
// Throw
|
// Throw
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,11 +34,11 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, 10).ToObservable().ToArray();
|
var xs = await UniTaskAsyncEnumerable.Range(1, 10).ToObservable().ToArray();
|
||||||
xs.Should().Equal(Enumerable.Range(1, 10));
|
xs.Should().BeEquivalentTo(Enumerable.Range(1, 10));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, 0).ToObservable().ToArray();
|
var xs = await UniTaskAsyncEnumerable.Range(1, 0).ToObservable().ToArray();
|
||||||
xs.Should().Equal(Enumerable.Range(1, 0));
|
xs.Should().BeEquivalentTo(Enumerable.Range(1, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,21 +70,21 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Observable.Range(1, 100).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
var xs = await Observable.Range(1, 100).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
||||||
var ys = await Observable.Range(1, 100).ToArray();
|
var ys = await Observable.Range(1, 100).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var xs = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
var xs = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
||||||
var ys = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToArray();
|
var ys = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var xs = await Observable.Empty<int>(ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
var xs = await Observable.Empty<int>(ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync();
|
||||||
var ys = await Observable.Empty<int>(ThreadPoolScheduler.Instance).ToArray();
|
var ys = await Observable.Empty<int>(ThreadPoolScheduler.Instance).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,25 +95,25 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x);
|
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x);
|
||||||
var ys = Enumerable.Range(1, 100).ToDictionary(x => x);
|
var ys = Enumerable.Range(1, 100).ToDictionary(x => x);
|
||||||
|
|
||||||
xs.OrderBy(x => x.Key).Should().Equal(ys.OrderBy(x => x.Key));
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x);
|
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x);
|
||||||
var ys = Enumerable.Range(1, 0).ToDictionary(x => x);
|
var ys = Enumerable.Range(1, 0).ToDictionary(x => x);
|
||||||
|
|
||||||
xs.OrderBy(x => x.Key).Should().Equal(ys.OrderBy(x => x.Key));
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2);
|
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2);
|
||||||
var ys = Enumerable.Range(1, 100).ToDictionary(x => x, x => x * 2);
|
var ys = Enumerable.Range(1, 100).ToDictionary(x => x, x => x * 2);
|
||||||
|
|
||||||
xs.OrderBy(x => x.Key).Should().Equal(ys.OrderBy(x => x.Key));
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2);
|
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2);
|
||||||
var ys = Enumerable.Range(1, 0).ToDictionary(x => x, x => x * 2);
|
var ys = Enumerable.Range(1, 0).ToDictionary(x => x, x => x * 2);
|
||||||
|
|
||||||
xs.OrderBy(x => x.Key).Should().Equal(ys.OrderBy(x => x.Key));
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,34 +126,34 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.ToLookup(x => x);
|
var ys = arr.ToLookup(x => x);
|
||||||
|
|
||||||
xs.Count.Should().Be(ys.Count);
|
xs.Count.Should().Be(ys.Count);
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
foreach (var key in xs.Select(x => x.Key))
|
foreach (var key in xs.Select(x => x.Key))
|
||||||
{
|
{
|
||||||
xs[key].Should().Equal(ys[key]);
|
xs[key].Should().BeEquivalentTo(ys[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x);
|
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x);
|
||||||
var ys = Enumerable.Range(1, 0).ToLookup(x => x);
|
var ys = Enumerable.Range(1, 0).ToLookup(x => x);
|
||||||
|
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await arr.ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2);
|
var xs = await arr.ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2);
|
||||||
var ys = arr.ToLookup(x => x, x => x * 2);
|
var ys = arr.ToLookup(x => x, x => x * 2);
|
||||||
|
|
||||||
xs.Count.Should().Be(ys.Count);
|
xs.Count.Should().Be(ys.Count);
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
foreach (var key in xs.Select(x => x.Key))
|
foreach (var key in xs.Select(x => x.Key))
|
||||||
{
|
{
|
||||||
xs[key].Should().Equal(ys[key]);
|
xs[key].Should().BeEquivalentTo(ys[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2);
|
var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2);
|
||||||
var ys = Enumerable.Range(1, 0).ToLookup(x => x, x => x * 2);
|
var ys = Enumerable.Range(1, 0).ToLookup(x => x, x => x * 2);
|
||||||
|
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,13 +164,13 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToListAsync();
|
var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToListAsync();
|
||||||
var ys = Enumerable.Range(1, 100).ToList();
|
var ys = Enumerable.Range(1, 100).ToList();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Empty<int>().ToUniTaskAsyncEnumerable().ToListAsync();
|
var xs = await Enumerable.Empty<int>().ToUniTaskAsyncEnumerable().ToListAsync();
|
||||||
var ys = Enumerable.Empty<int>().ToList();
|
var ys = Enumerable.Empty<int>().ToList();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,13 +181,13 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await new[] { 1, 20, 4, 5, 20, 4, 6 }.ToUniTaskAsyncEnumerable().ToHashSetAsync();
|
var xs = await new[] { 1, 20, 4, 5, 20, 4, 6 }.ToUniTaskAsyncEnumerable().ToHashSetAsync();
|
||||||
var ys = new[] { 1, 20, 4, 5, 20, 4, 6 }.ToHashSet();
|
var ys = new[] { 1, 20, 4, 5, 20, 4, 6 }.ToHashSet();
|
||||||
|
|
||||||
xs.OrderBy(x => x).Should().Equal(ys.OrderBy(x => x));
|
xs.OrderBy(x => x).Should().BeEquivalentTo(ys.OrderBy(x => x));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await Enumerable.Empty<int>().ToUniTaskAsyncEnumerable().ToHashSetAsync();
|
var xs = await Enumerable.Empty<int>().ToUniTaskAsyncEnumerable().ToHashSetAsync();
|
||||||
var ys = Enumerable.Empty<int>().ToHashSet();
|
var ys = Enumerable.Empty<int>().ToHashSet();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
var ys = await Range(from, count).AsUniTaskAsyncEnumerable().ToArrayAsync();
|
var ys = await Range(from, count).AsUniTaskAsyncEnumerable().ToArrayAsync();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -57,19 +57,19 @@ namespace NetCoreTests.Linq
|
||||||
list.Should().BeEmpty();
|
list.Should().BeEmpty();
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100);
|
list.Should().BeEquivalentTo(100);
|
||||||
e.Current.Should().Be(10);
|
e.Current.Should().Be(10);
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100, 200);
|
list.Should().BeEquivalentTo(100, 200);
|
||||||
e.Current.Should().Be(20);
|
e.Current.Should().Be(20);
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100, 200, 300);
|
list.Should().BeEquivalentTo(100, 200, 300);
|
||||||
e.Current.Should().Be(30);
|
e.Current.Should().Be(30);
|
||||||
|
|
||||||
(await e.MoveNextAsync()).Should().BeFalse();
|
(await e.MoveNextAsync()).Should().BeFalse();
|
||||||
list.Should().Equal(100, 200, 300, 400);
|
list.Should().BeEquivalentTo(100, 200, 300, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -144,43 +144,19 @@ namespace NetCoreTests.Linq
|
||||||
list.Should().BeEmpty();
|
list.Should().BeEmpty();
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100);
|
list.Should().BeEquivalentTo(100);
|
||||||
e.Current.Should().Be(10);
|
e.Current.Should().Be(10);
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100, 200);
|
list.Should().BeEquivalentTo(100, 200);
|
||||||
e.Current.Should().Be(20);
|
e.Current.Should().Be(20);
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
await e.MoveNextAsync();
|
||||||
list.Should().Equal(100, 200, 300);
|
list.Should().BeEquivalentTo(100, 200, 300);
|
||||||
e.Current.Should().Be(30);
|
e.Current.Should().Be(30);
|
||||||
|
|
||||||
(await e.MoveNextAsync()).Should().BeFalse();
|
(await e.MoveNextAsync()).Should().BeFalse();
|
||||||
list.Should().Equal(100, 200, 300, 400);
|
list.Should().BeEquivalentTo(100, 200, 300, 400);
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task AwaitForeachBreak()
|
|
||||||
{
|
|
||||||
var finallyCalled = false;
|
|
||||||
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await writer.YieldAsync(1);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
finallyCalled = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await foreach (var x in enumerable)
|
|
||||||
{
|
|
||||||
x.Should().Be(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
finallyCalled.Should().BeTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async IAsyncEnumerable<int> Range(int from, int count)
|
async IAsyncEnumerable<int> Range(int from, int count)
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(start, count).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(start, count).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(start, count).ToArray();
|
var ys = Enumerable.Range(start, count).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
@ -36,7 +36,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Repeat(value, count).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Repeat(value, count).ToArrayAsync();
|
||||||
var ys = Enumerable.Repeat(value, count).ToArray();
|
var ys = Enumerable.Repeat(value, count).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -45,7 +45,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Empty<int>().ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Empty<int>().ToArrayAsync();
|
||||||
var ys = Enumerable.Empty<int>().ToArray();
|
var ys = Enumerable.Empty<int>().ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
|
@ -23,26 +23,26 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var a = await src.Where(x => x % 2 == 0).ToArrayAsync();
|
var a = await src.Where(x => x % 2 == 0).ToArrayAsync();
|
||||||
var expected = range.Where(x => x % 2 == 0).ToArray();
|
var expected = range.Where(x => x % 2 == 0).ToArray();
|
||||||
a.Should().Equal(expected);
|
a.Should().BeEquivalentTo(expected);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var a = await src.Where((x, i) => (x + i) % 2 == 0).ToArrayAsync();
|
var a = await src.Where((x, i) => (x + i) % 2 == 0).ToArrayAsync();
|
||||||
var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray();
|
var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray();
|
||||||
a.Should().Equal(expected);
|
a.Should().BeEquivalentTo(expected);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var a = await src.WhereAwait(x => UniTask.Run(() => x % 2 == 0)).ToArrayAsync();
|
var a = await src.WhereAwait(x => UniTask.Run(() => x % 2 == 0)).ToArrayAsync();
|
||||||
var b = await src.WhereAwait(x => UniTask.FromResult(x % 2 == 0)).ToArrayAsync();
|
var b = await src.WhereAwait(x => UniTask.FromResult(x % 2 == 0)).ToArrayAsync();
|
||||||
var expected = range.Where(x => x % 2 == 0).ToArray();
|
var expected = range.Where(x => x % 2 == 0).ToArray();
|
||||||
a.Should().Equal(expected);
|
a.Should().BeEquivalentTo(expected);
|
||||||
b.Should().Equal(expected);
|
b.Should().BeEquivalentTo(expected);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var a = await src.WhereAwait((x, i) => UniTask.Run(() => (x + i) % 2 == 0)).ToArrayAsync();
|
var a = await src.WhereAwait((x, i) => UniTask.Run(() => (x + i) % 2 == 0)).ToArrayAsync();
|
||||||
var b = await src.WhereAwait((x, i) => UniTask.FromResult((x + i) % 2 == 0)).ToArrayAsync();
|
var b = await src.WhereAwait((x, i) => UniTask.FromResult((x + i) % 2 == 0)).ToArrayAsync();
|
||||||
var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray();
|
var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray();
|
||||||
a.Should().Equal(expected);
|
a.Should().BeEquivalentTo(expected);
|
||||||
b.Should().Equal(expected);
|
b.Should().BeEquivalentTo(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace NetCoreTests.Linq
|
||||||
var a = await data.ToUniTaskAsyncEnumerable().OfType<int>().ToArrayAsync();
|
var a = await data.ToUniTaskAsyncEnumerable().OfType<int>().ToArrayAsync();
|
||||||
var b = data.OfType<int>().ToArray();
|
var b = data.OfType<int>().ToArray();
|
||||||
|
|
||||||
a.Should().Equal(b);
|
a.Should().BeEquivalentTo(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ namespace NetCoreTests.Linq
|
||||||
var a = await data.ToUniTaskAsyncEnumerable().Cast<int>().ToArrayAsync();
|
var a = await data.ToUniTaskAsyncEnumerable().Cast<int>().ToArrayAsync();
|
||||||
var b = data.Cast<int>().ToArray();
|
var b = data.Cast<int>().ToArray();
|
||||||
|
|
||||||
a.Should().Equal(b);
|
a.Should().BeEquivalentTo(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await outer.ToUniTaskAsyncEnumerable().Join(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => (x, y)).ToArrayAsync();
|
var xs = await outer.ToUniTaskAsyncEnumerable().Join(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => (x, y)).ToArrayAsync();
|
||||||
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, y))).ToArrayAsync();
|
var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, y))).ToArrayAsync();
|
||||||
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, y))).ToArrayAsync();
|
var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, y))).ToArrayAsync();
|
||||||
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x).ToArray();
|
var ys = arr.GroupBy(x => x).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -131,7 +131,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().Equal(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -139,7 +139,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x).ToArray();
|
var ys = arr.GroupBy(x => x).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().Equal(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -155,7 +155,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x).ToArray();
|
var ys = arr.GroupBy(x => x).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().BeEquivalentTo(ys);
|
xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ namespace NetCoreTests.Linq
|
||||||
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().Equal(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,21 +199,21 @@ namespace NetCoreTests.Linq
|
||||||
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync();
|
var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync();
|
||||||
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync();
|
var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync();
|
||||||
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray();
|
||||||
|
|
||||||
xs.Length.Should().Be(ys.Length);
|
xs.Length.Should().Be(ys.Length);
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
#pragma warning disable CS1998
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests.Linq
|
|
||||||
{
|
|
||||||
public class MergeTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task TwoSource()
|
|
||||||
{
|
|
||||||
var semaphore = new SemaphoreSlim(1, 1);
|
|
||||||
|
|
||||||
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await UniTask.SwitchToThreadPool();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("A1");
|
|
||||||
semaphore.Release();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("A2");
|
|
||||||
semaphore.Release();
|
|
||||||
});
|
|
||||||
|
|
||||||
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await UniTask.SwitchToThreadPool();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("B1");
|
|
||||||
await writer.YieldAsync("B2");
|
|
||||||
semaphore.Release();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("B3");
|
|
||||||
semaphore.Release();
|
|
||||||
});
|
|
||||||
|
|
||||||
var result = await a.Merge(b).ToArrayAsync();
|
|
||||||
result.Should().Equal("A1", "B1", "B2", "A2", "B3");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ThreeSource()
|
|
||||||
{
|
|
||||||
var semaphore = new SemaphoreSlim(0, 1);
|
|
||||||
|
|
||||||
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await UniTask.SwitchToThreadPool();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("A1");
|
|
||||||
semaphore.Release();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("A2");
|
|
||||||
semaphore.Release();
|
|
||||||
});
|
|
||||||
|
|
||||||
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await UniTask.SwitchToThreadPool();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("B1");
|
|
||||||
await writer.YieldAsync("B2");
|
|
||||||
semaphore.Release();
|
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
|
||||||
await writer.YieldAsync("B3");
|
|
||||||
semaphore.Release();
|
|
||||||
});
|
|
||||||
|
|
||||||
var c = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await UniTask.SwitchToThreadPool();
|
|
||||||
|
|
||||||
await writer.YieldAsync("C1");
|
|
||||||
semaphore.Release();
|
|
||||||
});
|
|
||||||
|
|
||||||
var result = await a.Merge(b, c).ToArrayAsync();
|
|
||||||
result.Should().Equal("C1", "A1", "B1", "B2", "A2", "B3");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Throw()
|
|
||||||
{
|
|
||||||
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await writer.YieldAsync("A1");
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
throw new UniTaskTestException();
|
|
||||||
});
|
|
||||||
|
|
||||||
var enumerator = a.Merge(b).GetAsyncEnumerator();
|
|
||||||
(await enumerator.MoveNextAsync()).Should().Be(true);
|
|
||||||
enumerator.Current.Should().Be("A1");
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await enumerator.MoveNextAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Cancel()
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await writer.YieldAsync("A1");
|
|
||||||
});
|
|
||||||
|
|
||||||
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
await writer.YieldAsync("B1");
|
|
||||||
});
|
|
||||||
|
|
||||||
var enumerator = a.Merge(b).GetAsyncEnumerator(cts.Token);
|
|
||||||
(await enumerator.MoveNextAsync()).Should().Be(true);
|
|
||||||
enumerator.Current.Should().Be("A1");
|
|
||||||
|
|
||||||
cts.Cancel();
|
|
||||||
await Assert.ThrowsAsync<OperationCanceledException>(async () => await enumerator.MoveNextAsync());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).Skip(skipCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).Skip(skipCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).Skip(skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).Skip(skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -52,7 +52,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipLast(skipCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipLast(skipCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipLast(skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipLast(skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -77,7 +77,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeLast(takeCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeLast(takeCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeLast(takeCount).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeLast(takeCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -103,7 +103,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).Take(takeCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).Take(takeCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).Take(takeCount).ToArray();
|
var ys = Enumerable.Range(1, collection).Take(takeCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -130,37 +130,37 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,37 +213,37 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Reverse().ToArrayAsync();
|
var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Reverse().ToArrayAsync();
|
||||||
var ys = Enumerable.Range(start, count).Reverse().ToArray();
|
var ys = Enumerable.Range(start, count).Reverse().ToArray();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -46,18 +46,18 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select(x => x * x).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select(x => x * x).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, count).Select(x => x * x).ToArray();
|
var ys = Enumerable.Range(1, count).Select(x => x * x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
|
|
||||||
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x) => UniTask.Run(() => x * x)).ToArrayAsync();
|
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x) => UniTask.Run(() => x * x)).ToArrayAsync();
|
||||||
zs.Should().Equal(ys);
|
zs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select((x, i) => x * x * i).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select((x, i) => x * x * i).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, count).Select((x, i) => x * x * i).ToArray();
|
var ys = Enumerable.Range(1, count).Select((x, i) => x * x * i).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
|
|
||||||
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x, i) => UniTask.Run(() => x * x * i)).ToArrayAsync();
|
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x, i) => UniTask.Run(() => x * x * i)).ToArrayAsync();
|
||||||
zs.Should().Equal(ys);
|
zs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,22 +98,22 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// await
|
// await
|
||||||
|
@ -121,22 +121,22 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// with cancel
|
// with cancel
|
||||||
|
@ -144,22 +144,22 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,17 +219,17 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).Zip(UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).Zip(UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwait(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwait(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y, _) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y, _) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -288,7 +288,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
||||||
var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
@ -305,7 +305,7 @@ namespace NetCoreTests.Linq
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
||||||
var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync();
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -402,7 +402,7 @@ namespace NetCoreTests.Linq
|
||||||
public async Task PariwiseImmediate()
|
public async Task PariwiseImmediate()
|
||||||
{
|
{
|
||||||
var xs = await UniTaskAsyncEnumerable.Range(1, 5).Pairwise().ToArrayAsync();
|
var xs = await UniTaskAsyncEnumerable.Range(1, 5).Pairwise().ToArrayAsync();
|
||||||
xs.Should().Equal((1, 2), (2, 3), (3, 4), (4, 5));
|
xs.Should().BeEquivalentTo((1, 2), (2, 3), (3, 4), (4, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -426,7 +426,7 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
await complete;
|
await complete;
|
||||||
|
|
||||||
list.Should().Equal((10, 20), (20, 30), (30, 40), (40, 50));
|
list.Should().BeEquivalentTo((10, 20), (20, 30), (30, 40), (40, 50));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyException : Exception
|
class MyException : Exception
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
rp.Value = 2;
|
rp.Value = 2;
|
||||||
|
|
||||||
(await b).Should().Equal(1, 2);
|
(await b).Should().BeEquivalentTo(1, 2);
|
||||||
|
|
||||||
var c = multicast.ToArrayAsync();
|
var c = multicast.ToArrayAsync();
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
rp.Dispose();
|
rp.Dispose();
|
||||||
|
|
||||||
(await a).Should().Equal(1, 2, 3, 4, 5);
|
(await a).Should().BeEquivalentTo(1, 2, 3, 4, 5);
|
||||||
(await c).Should().Equal(3, 4, 5);
|
(await c).Should().BeEquivalentTo(3, 4, 5);
|
||||||
|
|
||||||
disp.Dispose();
|
disp.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace NetCoreTests.Linq
|
||||||
|
|
||||||
rp.Value = 2;
|
rp.Value = 2;
|
||||||
|
|
||||||
(await b).Should().Equal(1, 2);
|
(await b).Should().BeEquivalentTo(1, 2);
|
||||||
|
|
||||||
var c = multicast.ToArrayAsync();
|
var c = multicast.ToArrayAsync();
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace NetCoreTests.Linq
|
||||||
l.Add(x);
|
l.Add(x);
|
||||||
});
|
});
|
||||||
|
|
||||||
l.Should().Equal(100, 110, 120, 130, 140, 150, 160, 170, 180, 190);
|
l.Should().BeEquivalentTo(100, 110, 120, 130, 140, 150, 160, 170, 180, 190);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var ys = array.Distinct().ToArray();
|
var ys = array.Distinct().ToArray();
|
||||||
{
|
{
|
||||||
(await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().Distinct(x => x).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().Distinct(x => x).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,10 +71,10 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var ys = await array.ToAsyncEnumerable().DistinctUntilChanged().ToArrayAsync();
|
var ys = await array.ToAsyncEnumerable().DistinctUntilChanged().ToArrayAsync();
|
||||||
{
|
{
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged().ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged().ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged(x => x).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged(x => x).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().Equal(ys);
|
(await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await a1.ToUniTaskAsyncEnumerable().Except(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
var xs = await a1.ToUniTaskAsyncEnumerable().Except(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
||||||
var ys = a1.Except(a2).ToArray();
|
var ys = a1.Except(a2).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await a1.ToUniTaskAsyncEnumerable().Intersect(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
var xs = await a1.ToUniTaskAsyncEnumerable().Intersect(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
||||||
var ys = a1.Intersect(a2).ToArray();
|
var ys = a1.Intersect(a2).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await a1.ToUniTaskAsyncEnumerable().Union(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
var xs = await a1.ToUniTaskAsyncEnumerable().Union(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync();
|
||||||
var ys = a1.Union(a2).ToArray();
|
var ys = a1.Union(a2).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,32 +59,32 @@ namespace NetCoreTests.Linq
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x).ToArrayAsync();
|
||||||
var ys = array.OrderBy(x => x).ToArray();
|
var ys = array.OrderBy(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x).ToArrayAsync();
|
||||||
var ys = array.OrderByDescending(x => x).ToArray();
|
var ys = array.OrderByDescending(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwait(RandomRun).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwait(RandomRun).ToArrayAsync();
|
||||||
var ys = array.OrderBy(x => x).ToArray();
|
var ys = array.OrderBy(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(RandomRun).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(RandomRun).ToArrayAsync();
|
||||||
var ys = array.OrderByDescending(x => x).ToArray();
|
var ys = array.OrderByDescending(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation(RandomRun).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation(RandomRun).ToArrayAsync();
|
||||||
var ys = array.OrderBy(x => x).ToArray();
|
var ys = array.OrderBy(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation(RandomRun).ToArrayAsync();
|
var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation(RandomRun).ToArrayAsync();
|
||||||
var ys = array.OrderByDescending(x => x).ToArray();
|
var ys = array.OrderByDescending(x => x).ToArray();
|
||||||
xs.Should().Equal(ys);
|
xs.Should().BeEquivalentTo(ys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,14 +125,14 @@ namespace NetCoreTests.Linq
|
||||||
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync();
|
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync();
|
||||||
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync();
|
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync();
|
||||||
|
|
||||||
a.Should().Equal(a2);
|
a.Should().BeEquivalentTo(a2);
|
||||||
b.Should().Equal(b2);
|
b.Should().BeEquivalentTo(b2);
|
||||||
c.Should().Equal(c2);
|
c.Should().BeEquivalentTo(c2);
|
||||||
d.Should().Equal(d2);
|
d.Should().BeEquivalentTo(d2);
|
||||||
e.Should().Equal(e2);
|
e.Should().BeEquivalentTo(e2);
|
||||||
f.Should().Equal(f2);
|
f.Should().BeEquivalentTo(f2);
|
||||||
g.Should().Equal(g2);
|
g.Should().BeEquivalentTo(g2);
|
||||||
h.Should().Equal(h2);
|
h.Should().BeEquivalentTo(h2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
|
@ -144,14 +144,14 @@ namespace NetCoreTests.Linq
|
||||||
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
|
|
||||||
a.Should().Equal(a2);
|
a.Should().BeEquivalentTo(a2);
|
||||||
b.Should().Equal(b2);
|
b.Should().BeEquivalentTo(b2);
|
||||||
c.Should().Equal(c2);
|
c.Should().BeEquivalentTo(c2);
|
||||||
d.Should().Equal(d2);
|
d.Should().BeEquivalentTo(d2);
|
||||||
e.Should().Equal(e2);
|
e.Should().BeEquivalentTo(e2);
|
||||||
f.Should().Equal(f2);
|
f.Should().BeEquivalentTo(f2);
|
||||||
g.Should().Equal(g2);
|
g.Should().BeEquivalentTo(g2);
|
||||||
h.Should().Equal(h2);
|
h.Should().BeEquivalentTo(h2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
|
@ -163,14 +163,14 @@ namespace NetCoreTests.Linq
|
||||||
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync();
|
||||||
|
|
||||||
a.Should().Equal(a2);
|
a.Should().BeEquivalentTo(a2);
|
||||||
b.Should().Equal(b2);
|
b.Should().BeEquivalentTo(b2);
|
||||||
c.Should().Equal(c2);
|
c.Should().BeEquivalentTo(c2);
|
||||||
d.Should().Equal(d2);
|
d.Should().BeEquivalentTo(d2);
|
||||||
e.Should().Equal(e2);
|
e.Should().BeEquivalentTo(e2);
|
||||||
f.Should().Equal(f2);
|
f.Should().BeEquivalentTo(f2);
|
||||||
g.Should().Equal(g2);
|
g.Should().BeEquivalentTo(g2);
|
||||||
h.Should().Equal(h2);
|
h.Should().BeEquivalentTo(h2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace NetCoreTests.Linq
|
||||||
rp.Value = 4;
|
rp.Value = 4;
|
||||||
rp.Value = 5;
|
rp.Value = 5;
|
||||||
|
|
||||||
(await xs).Should().Equal(1, 2, 3, 4, 5);
|
(await xs).Should().BeEquivalentTo(1, 2, 3, 4, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -39,7 +39,7 @@ namespace NetCoreTests.Linq
|
||||||
rp.Value = 4;
|
rp.Value = 4;
|
||||||
rp.Value = 5;
|
rp.Value = 5;
|
||||||
|
|
||||||
(await xs).Should().Equal(1, 2, 3, 4);
|
(await xs).Should().BeEquivalentTo(1, 2, 3, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -56,7 +56,7 @@ namespace NetCoreTests.Linq
|
||||||
await c;
|
await c;
|
||||||
var foo = await xs;
|
var foo = await xs;
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 1, 10, 20 });
|
foo.Should().BeEquivalentTo(new[] { 1, 10, 20 });
|
||||||
|
|
||||||
async Task CancelAsync()
|
async Task CancelAsync()
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,7 @@ namespace NetCoreTests.Linq
|
||||||
await c;
|
await c;
|
||||||
var foo = await xs;
|
var foo = await xs;
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 20, 30, 40 });
|
foo.Should().BeEquivalentTo(new[] { 20, 30, 40 });
|
||||||
|
|
||||||
async Task CancelAsync()
|
async Task CancelAsync()
|
||||||
{
|
{
|
||||||
|
@ -116,7 +116,7 @@ namespace NetCoreTests.Linq
|
||||||
await c;
|
await c;
|
||||||
var foo = await xs;
|
var foo = await xs;
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 1, 10, 20 });
|
foo.Should().BeEquivalentTo(new[] { 1, 10, 20 });
|
||||||
|
|
||||||
async Task CancelAsync()
|
async Task CancelAsync()
|
||||||
{
|
{
|
||||||
|
@ -145,7 +145,7 @@ namespace NetCoreTests.Linq
|
||||||
await c;
|
await c;
|
||||||
var foo = await xs;
|
var foo = await xs;
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 20, 30, 40 });
|
foo.Should().BeEquivalentTo(new[] { 20, 30, 40 });
|
||||||
|
|
||||||
async Task CancelAsync()
|
async Task CancelAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
#pragma warning disable CS1998
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class TaskExtensionsTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task PropagateException()
|
|
||||||
{
|
|
||||||
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
|
||||||
{
|
|
||||||
await ThrowAsync().AsUniTask();
|
|
||||||
});
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
|
||||||
{
|
|
||||||
await ThrowOrValueAsync().AsUniTask();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PropagateExceptionWhenAll()
|
|
||||||
{
|
|
||||||
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
|
||||||
{
|
|
||||||
await Task.WhenAll(ThrowAsync(), ThrowAsync()).AsUniTask();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task ThrowAsync()
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<int> ThrowOrValueAsync()
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,7 +34,7 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ namespace NetCoreTests
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
ev.SetCanceled(default);
|
ev.SetCanceled(default);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
one.CompletedCalled.Count.Should().Be(1);
|
one.CompletedCalled.Count.Should().Be(1);
|
||||||
}
|
}
|
||||||
// after removed, onemore
|
// after removed, onemore
|
||||||
|
@ -59,7 +59,7 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ namespace NetCoreTests
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
ev.SetCanceled(default);
|
ev.SetCanceled(default);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
one.CompletedCalled.Count.Should().Be(1);
|
one.CompletedCalled.Count.Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,10 +102,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
four.NextCalled.Should().Equal(10, 20, 30);
|
four.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
|
|
||||||
|
@ -120,11 +120,11 @@ namespace NetCoreTests
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
ev.SetCanceled(default);
|
ev.SetCanceled(default);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
one.CompletedCalled.Count.Should().Be(1);
|
one.CompletedCalled.Count.Should().Be(1);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.CompletedCalled.Count.Should().Be(1);
|
three.CompletedCalled.Count.Should().Be(1);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.CompletedCalled.Count.Should().Be(1);
|
three.CompletedCalled.Count.Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,10 +145,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
ev.Add(four);
|
ev.Add(four);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
four.NextCalled.Should().Equal(10, 20, 30);
|
four.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
|
|
||||||
|
@ -163,11 +163,11 @@ namespace NetCoreTests
|
||||||
ev.SetCompleted();
|
ev.SetCompleted();
|
||||||
ev.SetCanceled(default);
|
ev.SetCanceled(default);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
one.CompletedCalled.Count.Should().Be(1);
|
one.CompletedCalled.Count.Should().Be(1);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.CompletedCalled.Count.Should().Be(1);
|
three.CompletedCalled.Count.Should().Be(1);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.CompletedCalled.Count.Should().Be(1);
|
three.CompletedCalled.Count.Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,9 +190,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.Remove(one);
|
ev.Remove(one);
|
||||||
|
|
||||||
|
@ -200,9 +200,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(50);
|
ev.SetResult(50);
|
||||||
ev.SetResult(60);
|
ev.SetResult(60);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -222,9 +222,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.Remove(two);
|
ev.Remove(two);
|
||||||
|
|
||||||
|
@ -232,9 +232,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(50);
|
ev.SetResult(50);
|
||||||
ev.SetResult(60);
|
ev.SetResult(60);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -254,9 +254,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
|
|
||||||
ev.Remove(three);
|
ev.Remove(three);
|
||||||
|
|
||||||
|
@ -264,9 +264,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(50);
|
ev.SetResult(50);
|
||||||
ev.SetResult(60);
|
ev.SetResult(60);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30, 40, 50, 60);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40, 50, 60);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,9 +321,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10);
|
one.NextCalled.Should().BeEquivalentTo(10);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run2()
|
public void Run2()
|
||||||
|
@ -342,9 +342,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10);
|
one.NextCalled.Should().BeEquivalentTo(10);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run3()
|
public void Run3()
|
||||||
|
@ -363,9 +363,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10);
|
one.NextCalled.Should().BeEquivalentTo(10);
|
||||||
two.NextCalled.Should().Equal(10, 20, 30);
|
two.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,9 +390,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Count.Should().Be(0);
|
two.NextCalled.Count.Should().Be(0);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run2()
|
public void Run2()
|
||||||
|
@ -412,9 +412,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10);
|
two.NextCalled.Should().BeEquivalentTo(10);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run3()
|
public void Run3()
|
||||||
|
@ -434,9 +434,9 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Should().Equal(10);
|
two.NextCalled.Should().BeEquivalentTo(10);
|
||||||
three.NextCalled.Should().Equal(10, 20, 30);
|
three.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,10 +464,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
two.NextCalled.Count.Should().Be(0);
|
two.NextCalled.Count.Should().Be(0);
|
||||||
three.NextCalled.Count.Should().Be(0);
|
three.NextCalled.Count.Should().Be(0);
|
||||||
four.NextCalled.Should().Equal(10, 20, 30);
|
four.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run2()
|
public void Run2()
|
||||||
|
@ -490,10 +490,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(20);
|
ev.SetResult(20);
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10);
|
one.NextCalled.Should().BeEquivalentTo(10);
|
||||||
two.NextCalled.Count.Should().Be(0);
|
two.NextCalled.Count.Should().Be(0);
|
||||||
three.NextCalled.Count.Should().Be(0);
|
three.NextCalled.Count.Should().Be(0);
|
||||||
four.NextCalled.Should().Equal(10, 20, 30);
|
four.NextCalled.Should().BeEquivalentTo(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -533,10 +533,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
ev.SetResult(40);
|
ev.SetResult(40);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30, 40);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40);
|
||||||
two.NextCalled.Should().Equal(20, 30, 40);
|
two.NextCalled.Should().BeEquivalentTo(20, 30, 40);
|
||||||
three.NextCalled.Should().Equal(30, 40);
|
three.NextCalled.Should().BeEquivalentTo(30, 40);
|
||||||
four.NextCalled.Should().Equal(40);
|
four.NextCalled.Should().BeEquivalentTo(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run2()
|
public void Run2()
|
||||||
|
@ -573,10 +573,10 @@ namespace NetCoreTests
|
||||||
ev.SetResult(30);
|
ev.SetResult(30);
|
||||||
ev.SetResult(40);
|
ev.SetResult(40);
|
||||||
|
|
||||||
one.NextCalled.Should().Equal(10, 20, 30, 40);
|
one.NextCalled.Should().BeEquivalentTo(10, 20, 30, 40);
|
||||||
two.NextCalled.Should().Equal(20, 30, 40);
|
two.NextCalled.Should().BeEquivalentTo(20, 30, 40);
|
||||||
three.NextCalled.Should().Equal(30, 40);
|
three.NextCalled.Should().BeEquivalentTo(30, 40);
|
||||||
four.NextCalled.Should().Equal(40);
|
four.NextCalled.Should().BeEquivalentTo(40);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NetCoreTests.Linq;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class AutoResetUniTaskCompletionSourceTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task SetResultAfterReturn()
|
|
||||||
{
|
|
||||||
var source1 = AutoResetUniTaskCompletionSource.Create();
|
|
||||||
source1.TrySetResult();
|
|
||||||
await source1.Task;
|
|
||||||
|
|
||||||
source1.TrySetResult().Should().BeFalse();
|
|
||||||
|
|
||||||
var source2 = AutoResetUniTaskCompletionSource.Create();
|
|
||||||
source2.TrySetResult();
|
|
||||||
await source2.Task;
|
|
||||||
|
|
||||||
source2.TrySetResult().Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SetCancelAfterReturn()
|
|
||||||
{
|
|
||||||
var source = AutoResetUniTaskCompletionSource.Create();
|
|
||||||
source.TrySetResult();
|
|
||||||
await source.Task;
|
|
||||||
|
|
||||||
source.TrySetCanceled().Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SetExceptionAfterReturn()
|
|
||||||
{
|
|
||||||
var source = AutoResetUniTaskCompletionSource.Create();
|
|
||||||
source.TrySetResult();
|
|
||||||
await source.Task;
|
|
||||||
|
|
||||||
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SetResultWithValueAfterReturn()
|
|
||||||
{
|
|
||||||
var source1 = AutoResetUniTaskCompletionSource<int>.Create();
|
|
||||||
source1.TrySetResult(100);
|
|
||||||
(await source1.Task).Should().Be(100);
|
|
||||||
|
|
||||||
source1.TrySetResult(100).Should().BeFalse();
|
|
||||||
|
|
||||||
var source2 = AutoResetUniTaskCompletionSource.Create();
|
|
||||||
source2.TrySetResult();
|
|
||||||
await source2.Task;
|
|
||||||
source2.TrySetResult().Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SetCancelWithValueAfterReturn()
|
|
||||||
{
|
|
||||||
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
|
||||||
source.TrySetResult(100);
|
|
||||||
(await source.Task).Should().Be(100);
|
|
||||||
source.TrySetCanceled().Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SetExceptionWithValueAfterReturn()
|
|
||||||
{
|
|
||||||
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
|
||||||
source.TrySetResult(100);
|
|
||||||
(await source.Task).Should().Be(100);
|
|
||||||
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class WhenEachTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task Each()
|
|
||||||
{
|
|
||||||
var a = Delay(1, 3000);
|
|
||||||
var b = Delay(2, 1000);
|
|
||||||
var c = Delay(3, 2000);
|
|
||||||
|
|
||||||
var l = new List<int>();
|
|
||||||
await foreach (var item in UniTask.WhenEach(a, b, c))
|
|
||||||
{
|
|
||||||
l.Add(item.Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Should().Equal(2, 3, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Error()
|
|
||||||
{
|
|
||||||
var a = Delay2(1, 3000);
|
|
||||||
var b = Delay2(2, 1000);
|
|
||||||
var c = Delay2(3, 2000);
|
|
||||||
|
|
||||||
var l = new List<WhenEachResult<int>>();
|
|
||||||
await foreach (var item in UniTask.WhenEach(a, b, c))
|
|
||||||
{
|
|
||||||
l.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
l[0].IsCompletedSuccessfully.Should().BeTrue();
|
|
||||||
l[0].IsFaulted.Should().BeFalse();
|
|
||||||
l[0].Result.Should().Be(2);
|
|
||||||
|
|
||||||
l[1].IsCompletedSuccessfully.Should().BeFalse();
|
|
||||||
l[1].IsFaulted.Should().BeTrue();
|
|
||||||
l[1].Exception.Message.Should().Be("ERROR");
|
|
||||||
|
|
||||||
l[2].IsCompletedSuccessfully.Should().BeTrue();
|
|
||||||
l[2].IsFaulted.Should().BeFalse();
|
|
||||||
l[2].Result.Should().Be(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTask<int> Delay(int id, int sleep)
|
|
||||||
{
|
|
||||||
await Task.Delay(sleep);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTask<int> Delay2(int id, int sleep)
|
|
||||||
{
|
|
||||||
await Task.Delay(sleep);
|
|
||||||
if (id == 3) throw new Exception("ERROR");
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ namespace NetCoreTests
|
||||||
{
|
{
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
|
||||||
var v = await UniTask.Run(() => 10).AttachExternalCancellation(cts.Token);
|
var v = await UniTask.Run(() => 10).WithCancellation(cts.Token);
|
||||||
|
|
||||||
v.Should().Be(10);
|
v.Should().Be(10);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace NetCoreTests
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
return 10;
|
return 10;
|
||||||
}).AttachExternalCancellation(cts.Token);
|
}).WithCancellation(cts.Token);
|
||||||
|
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,8 @@ public static class EditorRunnerChecker
|
||||||
{
|
{
|
||||||
Debug.Log("Start");
|
Debug.Log("Start");
|
||||||
|
|
||||||
//var r = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().ToUniTask();
|
var r = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().ToUniTask();
|
||||||
//Debug.Log(r.downloadHandler.text.Substring(0, 100));
|
Debug.Log(r.downloadHandler.text.Substring(0, 100));
|
||||||
//await UniTask.Yield();
|
|
||||||
|
|
||||||
await UniTask.DelayFrame(30);
|
|
||||||
|
|
||||||
Debug.Log("End");
|
Debug.Log("End");
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
static Action<object> cancellationCallback = CancellationCallback;
|
static Action<object> cancellationCallback = CancellationCallback;
|
||||||
|
|
||||||
static TaskPool<WaitAsyncSource> pool;
|
static TaskPool<WaitAsyncSource> pool;
|
||||||
WaitAsyncSource nextNode;
|
WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode { get; set; }
|
||||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitAsyncSource()
|
static WaitAsyncSource()
|
||||||
{
|
{
|
||||||
|
@ -405,8 +404,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
static Action<object> cancellationCallback = CancellationCallback;
|
static Action<object> cancellationCallback = CancellationCallback;
|
||||||
|
|
||||||
static TaskPool<WaitAsyncSource> pool;
|
static TaskPool<WaitAsyncSource> pool;
|
||||||
WaitAsyncSource nextNode;
|
WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode { get; set; }
|
||||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitAsyncSource()
|
static WaitAsyncSource()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,29 +4,31 @@ using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Cysharp.Threading.Tasks.Triggers;
|
using Cysharp.Threading.Tasks.Triggers;
|
||||||
using System;
|
using System;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
|
public static class CancellationTokenSourceExtensions
|
||||||
public static partial class CancellationTokenSourceExtensions
|
|
||||||
{
|
{
|
||||||
readonly static Action<object> CancelCancellationTokenSourceStateDelegate = new Action<object>(CancelCancellationTokenSourceState);
|
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||||
|
{
|
||||||
static void CancelCancellationTokenSourceState(object state)
|
var delay = UniTask.Delay(millisecondsDelay, delayType, delayTiming, cts.Token);
|
||||||
|
CancelAfterCore(cts, delay).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||||
|
{
|
||||||
|
var delay = UniTask.Delay(delayTimeSpan, delayType, delayTiming, cts.Token);
|
||||||
|
CancelAfterCore(cts, delay).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTaskVoid CancelAfterCore(CancellationTokenSource cts, UniTask delayTask)
|
||||||
|
{
|
||||||
|
var alreadyCanceled = await delayTask.SuppressCancellationThrow();
|
||||||
|
if (!alreadyCanceled)
|
||||||
{
|
{
|
||||||
var cts = (CancellationTokenSource)state;
|
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
|
cts.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
|
||||||
{
|
|
||||||
return CancelAfterSlim(cts, TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
|
||||||
{
|
|
||||||
return PlayerLoopTimer.StartNew(delayTimeSpan, false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
|
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
|
||||||
|
@ -37,7 +39,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
|
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
|
||||||
{
|
{
|
||||||
var trigger = gameObject.GetAsyncDestroyTrigger();
|
var trigger = gameObject.GetAsyncDestroyTrigger();
|
||||||
trigger.CancellationToken.RegisterWithoutCaptureExecutionContext(CancelCancellationTokenSourceStateDelegate, cts);
|
trigger.CancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var cts2 = (CancellationTokenSource)state;
|
||||||
|
cts2.Cancel();
|
||||||
|
}, cts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncUniTaskVoid<TStateMachine> nextNode;
|
public AsyncUniTaskVoid<TStateMachine> NextNode { get; set; }
|
||||||
public ref AsyncUniTaskVoid<TStateMachine> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
public void Return()
|
public void Return()
|
||||||
{
|
{
|
||||||
|
@ -158,8 +157,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncUniTask<TStateMachine> nextNode;
|
public AsyncUniTask<TStateMachine> NextNode { get; set; }
|
||||||
public ref AsyncUniTask<TStateMachine> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncUniTask()
|
static AsyncUniTask()
|
||||||
{
|
{
|
||||||
|
@ -281,8 +279,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncUniTask<TStateMachine, T> nextNode;
|
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
||||||
public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncUniTask()
|
static AsyncUniTask()
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,24 +32,10 @@ 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;
|
||||||
EnumeratorPromise nextNode;
|
public EnumeratorPromise NextNode { get; set; }
|
||||||
public ref EnumeratorPromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static EnumeratorPromise()
|
static EnumeratorPromise()
|
||||||
{
|
{
|
||||||
|
@ -59,8 +45,6 @@ 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;
|
||||||
|
|
||||||
|
@ -83,18 +67,13 @@ 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);
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
|
|
||||||
// run immediately.
|
result.MoveNext(); // run immediately.
|
||||||
if (result.MoveNext())
|
|
||||||
{
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,17 +81,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
calledGetResult = true;
|
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!loopRunning)
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
@ -131,21 +106,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -172,12 +134,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +148,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
innerEnumerator = default;
|
innerEnumerator = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,10 +162,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
else if (current is CustomYieldInstruction cyi)
|
else if (current is CustomYieldInstruction)
|
||||||
{
|
{
|
||||||
// WWW, WaitForSecondsRealtime
|
// WWW, WaitForSecondsRealtime
|
||||||
while (cyi.keepWaiting)
|
var e2 = UnwrapWaitCustomYieldInstruction((CustomYieldInstruction)current);
|
||||||
|
while (e2.MoveNext())
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +192,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto WARN;
|
yield return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (current is IEnumerator e3)
|
else if (current is IEnumerator e3)
|
||||||
|
@ -245,14 +205,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto WARN;
|
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
// WWW and others as CustomYieldInstruction.
|
||||||
|
static IEnumerator UnwrapWaitCustomYieldInstruction(CustomYieldInstruction yieldInstruction)
|
||||||
WARN:
|
{
|
||||||
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
while (yieldInstruction.keepWaiting)
|
||||||
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;
|
yield return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,3 +248,4 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine.AddressableAssets;
|
|
||||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
|
@ -21,19 +20,18 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
return ToUniTask(handle, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||||
|
|
||||||
if (!handle.IsValid())
|
if (!handle.IsValid())
|
||||||
{
|
{
|
||||||
// autoReleaseHandle:true handle is invalid(immediately internal handle == null) so return completed.
|
throw new Exception("Attempting to use an invalid operation handle");
|
||||||
return UniTask.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle.IsDone)
|
if (handle.IsDone)
|
||||||
|
@ -45,7 +43,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -96,31 +94,27 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||||
AsyncOperationHandleConfiguredSource nextNode;
|
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
|
||||||
public ref AsyncOperationHandleConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncOperationHandleConfiguredSource()
|
static AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle> completedCallback;
|
readonly Action<AsyncOperationHandle> continuationAction;
|
||||||
AsyncOperationHandle handle;
|
AsyncOperationHandle handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
bool autoReleaseWhenCanceled;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
completedCallback = HandleCompleted;
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -135,52 +129,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.handle = handle;
|
result.handle = handle;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
|
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (AsyncOperationHandleConfiguredSource)state;
|
|
||||||
if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(promise.handle);
|
|
||||||
}
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.completedCallback;
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleCompleted(AsyncOperationHandle _)
|
void Continuation(AsyncOperationHandle _)
|
||||||
{
|
{
|
||||||
if (handle.IsValid())
|
handle.Completed -= continuationAction;
|
||||||
{
|
|
||||||
handle.Completed -= completedCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
return;
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (handle.Status == AsyncOperationStatus.Failed)
|
else if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
@ -192,25 +165,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
@ -231,23 +191,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
|
TryReturn();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
if (progress != null && handle.IsValid())
|
||||||
{
|
{
|
||||||
progress.Report(handle.GetDownloadStatus().Percent);
|
progress.Report(handle.PercentComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -260,7 +217,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,12 +230,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
return ToUniTask(handle, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
||||||
|
|
||||||
|
@ -297,37 +253,33 @@ namespace Cysharp.Threading.Tasks
|
||||||
return UniTask.FromResult(handle.Result);
|
return UniTask.FromResult(handle.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
AsyncOperationHandleConfiguredSource<T> nextNode;
|
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
|
||||||
public ref AsyncOperationHandleConfiguredSource<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncOperationHandleConfiguredSource()
|
static AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle<T>> completedCallback;
|
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
||||||
AsyncOperationHandle<T> handle;
|
AsyncOperationHandle<T> handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
bool autoReleaseWhenCanceled;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
completedCallback = HandleCompleted;
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -343,50 +295,30 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (AsyncOperationHandleConfiguredSource<T>)state;
|
|
||||||
if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(promise.handle);
|
|
||||||
}
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.completedCallback;
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleCompleted(AsyncOperationHandle<T> argHandle)
|
void Continuation(AsyncOperationHandle<T> argHandle)
|
||||||
{
|
{
|
||||||
if (handle.IsValid())
|
handle.Completed -= continuationAction;
|
||||||
{
|
|
||||||
handle.Completed -= completedCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
return;
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
||||||
|
@ -398,25 +330,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.TrySetResult(argHandle.Result);
|
core.TrySetResult(argHandle.Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public T GetResult(short token)
|
public T GetResult(short token)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
{
|
{
|
||||||
|
@ -442,23 +361,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
|
TryReturn();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
if (progress != null && handle.IsValid())
|
||||||
{
|
{
|
||||||
progress.Report(handle.GetDownloadStatus().Percent);
|
progress.Report(handle.PercentComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -471,7 +387,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
"name": "UniTask.Addressables",
|
"name": "UniTask.Addressables",
|
||||||
"references": [
|
"references": [
|
||||||
"UniTask",
|
"UniTask",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager"
|
||||||
"Unity.Addressables"
|
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
@ -17,11 +16,6 @@
|
||||||
"name": "com.unity.addressables",
|
"name": "com.unity.addressables",
|
||||||
"expression": "",
|
"expression": "",
|
||||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.addressables.cn",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|
|
@ -16,14 +16,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
Kill,
|
Kill,
|
||||||
KillWithCompleteCallback,
|
KillWithCompleteCallback,
|
||||||
Complete,
|
Complete,
|
||||||
CompleteWithSequenceCallback,
|
CompleteWithSeqeunceCallback,
|
||||||
CancelAwait,
|
CancelAwait,
|
||||||
|
|
||||||
// AndCancelAwait
|
// AndCancelAwait
|
||||||
KillAndCancelAwait,
|
KillAndCancelAwait,
|
||||||
KillWithCompleteCallbackAndCancelAwait,
|
KillWithCompleteCallbackAndCancelAwait,
|
||||||
CompleteAndCancelAwait,
|
CompleteAndCancelAwait,
|
||||||
CompleteWithSequenceCallbackAndCancelAwait
|
CompleteWithSeqeunceCallbackAndCancelAwait
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DOTweenAsyncExtensions
|
public static class DOTweenAsyncExtensions
|
||||||
|
@ -135,29 +135,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
|
sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<TweenConfiguredSource> pool;
|
static TaskPool<TweenConfiguredSource> pool;
|
||||||
TweenConfiguredSource nextNode;
|
public TweenConfiguredSource NextNode { get; set; }
|
||||||
public ref TweenConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static TweenConfiguredSource()
|
static TweenConfiguredSource()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static readonly TweenCallback EmptyTweenCallback = () => { };
|
||||||
|
|
||||||
readonly TweenCallback onCompleteCallbackDelegate;
|
readonly TweenCallback onCompleteCallbackDelegate;
|
||||||
|
readonly TweenCallback onUpdateDelegate;
|
||||||
|
|
||||||
Tween tween;
|
Tween tween;
|
||||||
TweenCancelBehaviour cancelBehaviour;
|
TweenCancelBehaviour cancelBehaviour;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationRegistration;
|
|
||||||
CallbackType callbackType;
|
CallbackType callbackType;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
|
||||||
TweenCallback originalCompleteAction;
|
TweenCallback originalUpdateAction;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
TweenConfiguredSource()
|
TweenConfiguredSource()
|
||||||
{
|
{
|
||||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
||||||
|
onUpdateDelegate = OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
||||||
|
@ -177,87 +179,41 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.cancelBehaviour = cancelBehaviour;
|
result.cancelBehaviour = cancelBehaviour;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.callbackType = callbackType;
|
result.callbackType = callbackType;
|
||||||
|
|
||||||
|
result.originalUpdateAction = tween.onUpdate;
|
||||||
result.canceled = false;
|
result.canceled = false;
|
||||||
|
|
||||||
|
if (result.originalUpdateAction == result.onUpdateDelegate)
|
||||||
|
{
|
||||||
|
result.originalUpdateAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
tween.onUpdate = result.onUpdateDelegate;
|
||||||
|
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
result.originalCompleteAction = tween.onKill;
|
|
||||||
tween.onKill = result.onCompleteCallbackDelegate;
|
tween.onKill = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Complete:
|
case CallbackType.Complete:
|
||||||
result.originalCompleteAction = tween.onComplete;
|
|
||||||
tween.onComplete = result.onCompleteCallbackDelegate;
|
tween.onComplete = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Pause:
|
case CallbackType.Pause:
|
||||||
result.originalCompleteAction = tween.onPause;
|
|
||||||
tween.onPause = result.onCompleteCallbackDelegate;
|
tween.onPause = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Play:
|
case CallbackType.Play:
|
||||||
result.originalCompleteAction = tween.onPlay;
|
|
||||||
tween.onPlay = result.onCompleteCallbackDelegate;
|
tween.onPlay = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Rewind:
|
case CallbackType.Rewind:
|
||||||
result.originalCompleteAction = tween.onRewind;
|
|
||||||
tween.onRewind = result.onCompleteCallbackDelegate;
|
tween.onRewind = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
case CallbackType.StepComplete:
|
case CallbackType.StepComplete:
|
||||||
result.originalCompleteAction = tween.onStepComplete;
|
|
||||||
tween.onStepComplete = result.onCompleteCallbackDelegate;
|
tween.onStepComplete = result.onCompleteCallbackDelegate;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.originalCompleteAction == result.onCompleteCallbackDelegate)
|
|
||||||
{
|
|
||||||
result.originalCompleteAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
|
|
||||||
{
|
|
||||||
var source = (TweenConfiguredSource)x;
|
|
||||||
switch (source.cancelBehaviour)
|
|
||||||
{
|
|
||||||
case TweenCancelBehaviour.Kill:
|
|
||||||
default:
|
|
||||||
source.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillAndCancelAwait:
|
|
||||||
source.canceled = true;
|
|
||||||
source.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallback:
|
|
||||||
source.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
|
||||||
source.canceled = true;
|
|
||||||
source.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.Complete:
|
|
||||||
source.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
|
||||||
source.canceled = true;
|
|
||||||
source.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
|
||||||
source.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
|
||||||
source.canceled = true;
|
|
||||||
source.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
|
||||||
source.RestoreOriginalCallback();
|
|
||||||
source.core.TrySetCanceled(source.cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
|
@ -266,28 +222,87 @@ 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.CompleteWithSequenceCallbackAndCancelAwait
|
|
||||||
|| this.cancelBehaviour == TweenCancelBehaviour.CancelAwait)
|
|
||||||
{
|
|
||||||
canceled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (canceled)
|
if (canceled)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
originalCompleteAction?.Invoke();
|
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnUpdate()
|
||||||
|
{
|
||||||
|
originalUpdateAction?.Invoke();
|
||||||
|
|
||||||
|
if (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this.cancelBehaviour)
|
||||||
|
{
|
||||||
|
case TweenCancelBehaviour.Kill:
|
||||||
|
default:
|
||||||
|
this.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
|
this.canceled = true;
|
||||||
|
this.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
|
this.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
|
this.canceled = true;
|
||||||
|
this.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.Complete:
|
||||||
|
this.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
|
this.canceled = true;
|
||||||
|
this.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
||||||
|
this.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
||||||
|
this.canceled = true;
|
||||||
|
this.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
// replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||||
|
switch (callbackType)
|
||||||
|
{
|
||||||
|
case CallbackType.Kill:
|
||||||
|
tween.onKill = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
case CallbackType.Complete:
|
||||||
|
tween.onComplete = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
case CallbackType.Pause:
|
||||||
|
tween.onPause = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
case CallbackType.Play:
|
||||||
|
tween.onPlay = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
case CallbackType.Rewind:
|
||||||
|
tween.onRewind = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
case CallbackType.StepComplete:
|
||||||
|
tween.onStepComplete = EmptyTweenCallback;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.core.TrySetCanceled(this.cancellationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -312,10 +327,10 @@ namespace Cysharp.Threading.Tasks
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
tween.Complete(false);
|
tween.Complete(false);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
||||||
tween.Complete(true);
|
tween.Complete(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
||||||
tween.Complete(true);
|
tween.Complete(true);
|
||||||
break;
|
break;
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
@ -354,41 +369,36 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationRegistration.Dispose();
|
tween.onUpdate = originalUpdateAction;
|
||||||
|
|
||||||
RestoreOriginalCallback();
|
|
||||||
|
|
||||||
tween = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
originalCompleteAction = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreOriginalCallback()
|
|
||||||
{
|
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
tween.onKill = originalCompleteAction;
|
tween.onKill = null;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Complete:
|
case CallbackType.Complete:
|
||||||
tween.onComplete = originalCompleteAction;
|
tween.onComplete = null;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Pause:
|
case CallbackType.Pause:
|
||||||
tween.onPause = originalCompleteAction;
|
tween.onPause = null;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Play:
|
case CallbackType.Play:
|
||||||
tween.onPlay = originalCompleteAction;
|
tween.onPlay = null;
|
||||||
break;
|
break;
|
||||||
case CallbackType.Rewind:
|
case CallbackType.Rewind:
|
||||||
tween.onRewind = originalCompleteAction;
|
tween.onRewind = null;
|
||||||
break;
|
break;
|
||||||
case CallbackType.StepComplete:
|
case CallbackType.StepComplete:
|
||||||
tween.onStepComplete = originalCompleteAction;
|
tween.onStepComplete = null;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tween = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
originalUpdateAction = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
"name": "com.unity.textmeshpro",
|
"name": "com.unity.textmeshpro",
|
||||||
"expression": "",
|
"expression": "",
|
||||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.ugui",
|
|
||||||
"expression": "2.0.0",
|
|
||||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable CS0108
|
|
||||||
|
|
||||||
#if (UNITASK_NETCORE && !NETSTANDARD2_0) || UNITY_2022_3_OR_NEWER
|
|
||||||
#define SUPPORT_VALUETASK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
@ -24,8 +19,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
// similar as IValueTaskSource
|
// similar as IValueTaskSource
|
||||||
public interface IUniTaskSource
|
public interface IUniTaskSource
|
||||||
#if SUPPORT_VALUETASK
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
: System.Threading.Tasks.Sources.IValueTaskSource
|
: System.Threading.Tasks.Sources.IValueTaskSource
|
||||||
|
#pragma warning disable CS0108
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UniTaskStatus GetStatus(short token);
|
UniTaskStatus GetStatus(short token);
|
||||||
|
@ -34,7 +30,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
||||||
|
|
||||||
#if SUPPORT_VALUETASK
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
|
#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)
|
||||||
{
|
{
|
||||||
|
@ -56,13 +53,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IUniTaskSource<out T> : IUniTaskSource
|
public interface IUniTaskSource<out T> : IUniTaskSource
|
||||||
#if SUPPORT_VALUETASK
|
#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 SUPPORT_VALUETASK
|
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
||||||
|
|
||||||
new public UniTaskStatus GetStatus(short token)
|
new public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
|
|
||||||
readonly PlayerLoopTiming timing;
|
readonly PlayerLoopTiming timing;
|
||||||
|
|
||||||
SpinLock gate = new SpinLock(false);
|
SpinLock gate = new SpinLock();
|
||||||
bool dequing = false;
|
bool dequing = false;
|
||||||
|
|
||||||
int actionListCount = 0;
|
int actionListCount = 0;
|
||||||
|
@ -70,17 +70,13 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Clear()
|
public void 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.
|
||||||
|
@ -132,14 +128,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -162,10 +150,6 @@ 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()
|
||||||
|
@ -186,9 +170,9 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
|
|
||||||
for (int i = 0; i < actionListCount; i++)
|
for (int i = 0; i < actionListCount; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
var action = actionList[i];
|
var action = actionList[i];
|
||||||
actionList[i] = null;
|
actionList[i] = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
action();
|
action();
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
|
|
||||||
foreach (var candidateMethod in methods)
|
foreach (var candidateMethod in methods)
|
||||||
{
|
{
|
||||||
var attributes = candidateMethod.GetCustomAttributes<StateMachineAttribute>(false);
|
var attributes = candidateMethod.GetCustomAttributes<StateMachineAttribute>();
|
||||||
if (attributes == null)
|
if (attributes == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
public static void ThrowArgumentException(string message)
|
public static void ThrowArgumentException<T>(string message)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(message);
|
throw new ArgumentException(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,24 +48,14 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Clear()
|
public void 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,14 +108,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -148,10 +130,6 @@ 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()
|
||||||
|
@ -165,6 +143,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
{
|
{
|
||||||
var j = tail - 1;
|
var j = tail - 1;
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
|
|
@ -7,8 +7,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
{
|
{
|
||||||
static TaskPool<PooledDelegate<T>> pool;
|
static TaskPool<PooledDelegate<T>> pool;
|
||||||
|
|
||||||
PooledDelegate<T> nextNode;
|
public PooledDelegate<T> NextNode { get; set; }
|
||||||
public ref PooledDelegate<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static PooledDelegate()
|
static PooledDelegate()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,8 +7,6 @@ using UnityEngine.Networking;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Internal
|
namespace Cysharp.Threading.Tasks.Internal
|
||||||
{
|
{
|
||||||
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
|
||||||
|
|
||||||
internal static class UnityWebRequestResultExtensions
|
internal static class UnityWebRequestResultExtensions
|
||||||
{
|
{
|
||||||
public static bool IsError(this UnityWebRequest unityWebRequest)
|
public static bool IsError(this UnityWebRequest unityWebRequest)
|
||||||
|
@ -23,6 +21,4 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
|
@ -18,8 +18,6 @@ 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
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
|
||||||
return new AppendPrepend<TSource>(source, element, false);
|
return new AppendPrepend<TSource>(source, element, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
if (enumerator == null)
|
if (enumerator == null)
|
||||||
{
|
{
|
||||||
if (state == State.RequirePrepend)
|
if (state == State.RequireAppend)
|
||||||
{
|
{
|
||||||
Current = element;
|
Current = element;
|
||||||
state = State.None;
|
state = State.None;
|
||||||
|
|
|
@ -52,7 +52,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
writer.Dispose();
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +127,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
|
||||||
{
|
{
|
||||||
readonly _Create enumerator;
|
readonly _Create enumerator;
|
||||||
|
|
||||||
|
@ -139,15 +138,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.enumerator = enumerator;
|
this.enumerator = enumerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
var status = core.GetStatus(core.Version);
|
|
||||||
if (status == UniTaskStatus.Pending)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
{
|
{
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
|
|
|
@ -1,234 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
|
||||||
{
|
|
||||||
public static partial class UniTaskAsyncEnumerable
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(first, nameof(first));
|
|
||||||
Error.ThrowArgumentNullException(second, nameof(second));
|
|
||||||
|
|
||||||
return new Merge<T>(new [] { first, second });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second, IUniTaskAsyncEnumerable<T> third)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(first, nameof(first));
|
|
||||||
Error.ThrowArgumentNullException(second, nameof(second));
|
|
||||||
Error.ThrowArgumentNullException(third, nameof(third));
|
|
||||||
|
|
||||||
return new Merge<T>(new[] { first, second, third });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IEnumerable<IUniTaskAsyncEnumerable<T>> sources)
|
|
||||||
{
|
|
||||||
return sources is IUniTaskAsyncEnumerable<T>[] array
|
|
||||||
? new Merge<T>(array)
|
|
||||||
: new Merge<T>(sources.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(params IUniTaskAsyncEnumerable<T>[] sources)
|
|
||||||
{
|
|
||||||
return new Merge<T>(sources);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class Merge<T> : IUniTaskAsyncEnumerable<T>
|
|
||||||
{
|
|
||||||
readonly IUniTaskAsyncEnumerable<T>[] sources;
|
|
||||||
|
|
||||||
public Merge(IUniTaskAsyncEnumerable<T>[] sources)
|
|
||||||
{
|
|
||||||
if (sources.Length <= 0)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentException("No source async enumerable to merge");
|
|
||||||
}
|
|
||||||
this.sources = sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
=> new _Merge(sources, cancellationToken);
|
|
||||||
|
|
||||||
enum MergeSourceState
|
|
||||||
{
|
|
||||||
Pending,
|
|
||||||
Running,
|
|
||||||
Completed,
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _Merge : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
|
||||||
{
|
|
||||||
static readonly Action<object> GetResultAtAction = GetResultAt;
|
|
||||||
|
|
||||||
readonly int length;
|
|
||||||
readonly IUniTaskAsyncEnumerator<T>[] enumerators;
|
|
||||||
readonly MergeSourceState[] states;
|
|
||||||
readonly Queue<(T, Exception, bool)> queuedResult = new Queue<(T, Exception, bool)>();
|
|
||||||
readonly CancellationToken cancellationToken;
|
|
||||||
|
|
||||||
int moveNextCompleted;
|
|
||||||
|
|
||||||
public T Current { get; private set; }
|
|
||||||
|
|
||||||
public _Merge(IUniTaskAsyncEnumerable<T>[] sources, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
length = sources.Length;
|
|
||||||
states = ArrayPool<MergeSourceState>.Shared.Rent(length);
|
|
||||||
enumerators = ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Rent(length);
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
enumerators[i] = sources[i].GetAsyncEnumerator(cancellationToken);
|
|
||||||
states[i] = (int)MergeSourceState.Pending;;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
completionSource.Reset();
|
|
||||||
Interlocked.Exchange(ref moveNextCompleted, 0);
|
|
||||||
|
|
||||||
if (HasQueuedResult() && Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
|
||||||
{
|
|
||||||
(T, Exception, bool) value;
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
value = queuedResult.Dequeue();
|
|
||||||
}
|
|
||||||
var resultValue = value.Item1;
|
|
||||||
var exception = value.Item2;
|
|
||||||
var hasNext = value.Item3;
|
|
||||||
if (exception != null)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(exception);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Current = resultValue;
|
|
||||||
completionSource.TrySetResult(hasNext);
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
if (states[i] == MergeSourceState.Pending)
|
|
||||||
{
|
|
||||||
states[i] = MergeSourceState.Running;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var awaiter = enumerators[i].MoveNextAsync().GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
GetResultAt(i, awaiter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(GetResultAtAction, StateTuple.Create(this, i, awaiter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
await enumerators[i].DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayPool<MergeSourceState>.Shared.Return(states, true);
|
|
||||||
ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Return(enumerators, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GetResultAt(object state)
|
|
||||||
{
|
|
||||||
using (var tuple = (StateTuple<_Merge, int, UniTask<bool>.Awaiter>)state)
|
|
||||||
{
|
|
||||||
tuple.Item1.GetResultAt(tuple.Item2, tuple.Item3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetResultAt(int index, UniTask<bool>.Awaiter awaiter)
|
|
||||||
{
|
|
||||||
bool hasNext;
|
|
||||||
bool completedAll;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
hasNext = awaiter.GetResult();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
queuedResult.Enqueue((default, ex, default));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
states[index] = hasNext ? MergeSourceState.Pending : MergeSourceState.Completed;
|
|
||||||
completedAll = !hasNext && IsCompletedAll();
|
|
||||||
}
|
|
||||||
if (hasNext || completedAll)
|
|
||||||
{
|
|
||||||
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
|
||||||
{
|
|
||||||
Current = enumerators[index].Current;
|
|
||||||
completionSource.TrySetResult(!completedAll);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
queuedResult.Enqueue((enumerators[index].Current, null, !completedAll));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasQueuedResult()
|
|
||||||
{
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
return queuedResult.Count > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsCompletedAll()
|
|
||||||
{
|
|
||||||
lock (states)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
if (states[i] != MergeSourceState.Completed)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: ca56812f160c45d0bacb4339819edf1a
|
|
||||||
timeCreated: 1694133666
|
|
|
@ -4,50 +4,38 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
return new EveryUpdate(updateTiming, cancelImmediately);
|
return new EveryUpdate(updateTiming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly bool cancelImmediately;
|
|
||||||
|
|
||||||
public EveryUpdate(PlayerLoopTiming updateTiming, bool cancelImmediately)
|
public EveryUpdate(PlayerLoopTiming updateTiming)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.cancelImmediately = cancelImmediately;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryUpdate(updateTiming, cancellationToken, cancelImmediately);
|
return new _EveryUpdate(updateTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (_EveryUpdate)state;
|
|
||||||
source.completionSource.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -56,14 +44,10 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed) return CompletedTasks.False;
|
// return false instead of throw
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +55,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -80,13 +63,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (disposed || cancellationToken.IsCancellationRequested)
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disposed)
|
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null)
|
||||||
where TTarget : class
|
where TTarget : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
|
@ -15,11 +15,11 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
if (isUnityObject)
|
if (isUnityObject)
|
||||||
{
|
{
|
||||||
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
readonly bool cancelImmediately;
|
|
||||||
|
|
||||||
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
this.cancelImmediately = cancelImmediately;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
|
@ -52,14 +50,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly UnityEngine.Object targetAsUnityObject;
|
readonly UnityEngine.Object targetAsUnityObject;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.targetAsUnityObject = target as UnityEngine.Object;
|
this.targetAsUnityObject = target as UnityEngine.Object;
|
||||||
|
@ -67,16 +64,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (_EveryValueChanged)state;
|
|
||||||
source.completionSource.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -85,15 +72,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed) return CompletedTasks.False;
|
// return false instead of throw
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
||||||
completionSource.Reset();
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +86,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +94,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -122,18 +102,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || targetAsUnityObject == null)
|
if (disposed || cancellationToken.IsCancellationRequested || targetAsUnityObject == null) // destroyed = cancel.
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -164,20 +139,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
readonly bool cancelImmediately;
|
|
||||||
|
|
||||||
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
||||||
{
|
{
|
||||||
this.target = new WeakReference<TTarget>(target, false);
|
this.target = new WeakReference<TTarget>(target, false);
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
this.cancelImmediately = cancelImmediately;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
|
@ -185,30 +158,19 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly WeakReference<TTarget> target;
|
readonly WeakReference<TTarget> target;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (_EveryValueChanged)state;
|
|
||||||
source.completionSource.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -217,15 +179,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed) return CompletedTasks.False;
|
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
@ -238,6 +192,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +200,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -254,19 +208,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || !target.TryGetTarget(out var t))
|
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,32 +6,32 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, null, updateTiming, ignoreTimeScale, cancelImmediately);
|
return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
||||||
{
|
{
|
||||||
return new Timer(period, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
return new Timer(period, period, updateTiming, ignoreTimeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, null, updateTiming, cancelImmediately);
|
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
|
@ -42,16 +42,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancelImmediately);
|
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
if (intervalFrameCount < 0)
|
if (intervalFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
||||||
}
|
}
|
||||||
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming, cancelImmediately);
|
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,20 +61,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly TimeSpan dueTime;
|
readonly TimeSpan dueTime;
|
||||||
readonly TimeSpan? period;
|
readonly TimeSpan? period;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
readonly bool cancelImmediately;
|
|
||||||
|
|
||||||
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, bool cancelImmediately)
|
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTime = dueTime;
|
this.dueTime = dueTime;
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
this.cancelImmediately = cancelImmediately;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken, cancelImmediately);
|
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
|
@ -83,8 +81,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly float? period;
|
readonly float? period;
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
readonly CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
|
@ -92,7 +89,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken, bool cancelImmediately)
|
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.dueTime = (float)dueTime.TotalSeconds;
|
this.dueTime = (float)dueTime.TotalSeconds;
|
||||||
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
||||||
|
@ -108,16 +105,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (_Timer)state;
|
|
||||||
source.completionSource.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -127,16 +114,12 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
// return false instead of throw
|
||||||
if (disposed || completed) return CompletedTasks.False;
|
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.elapsed = 0;
|
this.elapsed = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +127,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -153,16 +135,11 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed)
|
if (disposed || cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
|
@ -210,27 +187,24 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
readonly bool cancelImmediately;
|
|
||||||
|
|
||||||
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, bool cancelImmediately)
|
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
this.cancelImmediately = cancelImmediately;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken, cancelImmediately);
|
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
readonly CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
int currentFrame;
|
int currentFrame;
|
||||||
|
@ -238,7 +212,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
||||||
if (periodFrameCount != null)
|
if (periodFrameCount != null)
|
||||||
|
@ -252,15 +226,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (_TimerFrame)state;
|
|
||||||
source.completionSource.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -269,15 +234,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed || completed) return CompletedTasks.False;
|
// return false instead of throw
|
||||||
|
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.currentFrame = 0;
|
this.currentFrame = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +249,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -295,12 +257,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (disposed || cancellationToken.IsCancellationRequested)
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (disposed)
|
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -8,10 +8,8 @@ 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
|
||||||
|
@ -59,13 +57,6 @@ 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
|
||||||
|
@ -89,86 +80,7 @@ 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
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum InjectPlayerLoopTimings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Preset: All loops(default).
|
|
||||||
/// </summary>
|
|
||||||
All =
|
|
||||||
Initialization | LastInitialization |
|
|
||||||
EarlyUpdate | LastEarlyUpdate |
|
|
||||||
FixedUpdate | LastFixedUpdate |
|
|
||||||
PreUpdate | LastPreUpdate |
|
|
||||||
Update | LastUpdate |
|
|
||||||
PreLateUpdate | LastPreLateUpdate |
|
|
||||||
PostLateUpdate | LastPostLateUpdate
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
| TimeUpdate | LastTimeUpdate,
|
|
||||||
#else
|
|
||||||
,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preset: All without last except LastPostLateUpdate.
|
|
||||||
/// </summary>
|
|
||||||
Standard =
|
|
||||||
Initialization |
|
|
||||||
EarlyUpdate |
|
|
||||||
FixedUpdate |
|
|
||||||
PreUpdate |
|
|
||||||
Update |
|
|
||||||
PreLateUpdate |
|
|
||||||
PostLateUpdate | LastPostLateUpdate
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
| TimeUpdate
|
|
||||||
#endif
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preset: Minimum pattern, Update | FixedUpdate | LastPostLateUpdate
|
|
||||||
/// </summary>
|
|
||||||
Minimum =
|
|
||||||
Update | FixedUpdate | LastPostLateUpdate,
|
|
||||||
|
|
||||||
// PlayerLoopTiming
|
|
||||||
|
|
||||||
Initialization = 1,
|
|
||||||
LastInitialization = 2,
|
|
||||||
|
|
||||||
EarlyUpdate = 4,
|
|
||||||
LastEarlyUpdate = 8,
|
|
||||||
|
|
||||||
FixedUpdate = 16,
|
|
||||||
LastFixedUpdate = 32,
|
|
||||||
|
|
||||||
PreUpdate = 64,
|
|
||||||
LastPreUpdate = 128,
|
|
||||||
|
|
||||||
Update = 256,
|
|
||||||
LastUpdate = 512,
|
|
||||||
|
|
||||||
PreLateUpdate = 1024,
|
|
||||||
LastPreLateUpdate = 2048,
|
|
||||||
|
|
||||||
PostLateUpdate = 4096,
|
|
||||||
LastPostLateUpdate = 8192
|
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
,
|
|
||||||
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html
|
|
||||||
TimeUpdate = 16384,
|
|
||||||
LastTimeUpdate = 32768
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IPlayerLoopItem
|
public interface IPlayerLoopItem
|
||||||
|
@ -178,10 +90,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public static class PlayerLoopHelper
|
public static class PlayerLoopHelper
|
||||||
{
|
{
|
||||||
static readonly ContinuationQueue ThrowMarkerContinuationQueue = new ContinuationQueue(PlayerLoopTiming.Initialization);
|
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
||||||
static readonly PlayerLoopRunner ThrowMarkerPlayerLoopRunner = new PlayerLoopRunner(PlayerLoopTiming.Initialization);
|
|
||||||
|
|
||||||
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContext;
|
|
||||||
public static int MainThreadId => mainThreadId;
|
public static int MainThreadId => mainThreadId;
|
||||||
internal static string ApplicationDataPath => applicationDataPath;
|
internal static string ApplicationDataPath => applicationDataPath;
|
||||||
|
|
||||||
|
@ -189,34 +98,39 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
static int mainThreadId;
|
static int mainThreadId;
|
||||||
static string applicationDataPath;
|
static string applicationDataPath;
|
||||||
static SynchronizationContext unitySynchronizationContext;
|
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,
|
||||||
bool injectOnFirst,
|
Type loopRunnerYieldType, ContinuationQueue cq, Type lastLoopRunnerYieldType, ContinuationQueue lastCq,
|
||||||
Type loopRunnerYieldType, ContinuationQueue cq,
|
Type loopRunnerType, PlayerLoopRunner runner, Type lastLoopRunnerType, PlayerLoopRunner lastRunner)
|
||||||
Type loopRunnerType, PlayerLoopRunner runner)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
EditorApplication.playModeStateChanged += (state) =>
|
EditorApplication.playModeStateChanged += (state) =>
|
||||||
{
|
{
|
||||||
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode)
|
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode)
|
||||||
{
|
{
|
||||||
IsEditorApplicationQuitting = true;
|
return;
|
||||||
// run rest action before clear.
|
}
|
||||||
|
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
{
|
{
|
||||||
runner.Run();
|
|
||||||
runner.Clear();
|
runner.Clear();
|
||||||
}
|
}
|
||||||
|
if (lastRunner != null)
|
||||||
|
{
|
||||||
|
lastRunner.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (cq != null)
|
if (cq != null)
|
||||||
{
|
{
|
||||||
cq.Run();
|
|
||||||
cq.Clear();
|
cq.Clear();
|
||||||
}
|
}
|
||||||
IsEditorApplicationQuitting = false;
|
if (lastCq != null)
|
||||||
|
{
|
||||||
|
lastCq.Clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -227,38 +141,40 @@ namespace Cysharp.Threading.Tasks
|
||||||
updateDelegate = cq.Run
|
updateDelegate = cq.Run
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var lastYieldLoop = new PlayerLoopSystem
|
||||||
|
{
|
||||||
|
type = lastLoopRunnerYieldType,
|
||||||
|
updateDelegate = lastCq.Run
|
||||||
|
};
|
||||||
|
|
||||||
var runnerLoop = new PlayerLoopSystem
|
var runnerLoop = new PlayerLoopSystem
|
||||||
{
|
{
|
||||||
type = loopRunnerType,
|
type = loopRunnerType,
|
||||||
updateDelegate = runner.Run
|
updateDelegate = runner.Run
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove items from previous initializations.
|
var lastRunnerLoop = new PlayerLoopSystem
|
||||||
var source = RemoveRunner(loopSystem, loopRunnerYieldType, loopRunnerType);
|
|
||||||
var dest = new PlayerLoopSystem[source.Length + 2];
|
|
||||||
|
|
||||||
Array.Copy(source, 0, dest, injectOnFirst ? 2 : 0, source.Length);
|
|
||||||
if (injectOnFirst)
|
|
||||||
{
|
{
|
||||||
|
type = lastLoopRunnerType,
|
||||||
|
updateDelegate = lastRunner.Run
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove items from previous initializations.
|
||||||
|
var source = loopSystem.subSystemList
|
||||||
|
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType && ls.type != lastLoopRunnerYieldType && ls.type != lastLoopRunnerType)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var dest = new PlayerLoopSystem[source.Length + 4];
|
||||||
|
|
||||||
|
Array.Copy(source, 0, dest, 2, source.Length);
|
||||||
dest[0] = yieldLoop;
|
dest[0] = yieldLoop;
|
||||||
dest[1] = runnerLoop;
|
dest[1] = runnerLoop;
|
||||||
}
|
dest[dest.Length - 2] = lastYieldLoop;
|
||||||
else
|
dest[dest.Length - 1] = lastRunnerLoop;
|
||||||
{
|
|
||||||
dest[dest.Length - 2] = yieldLoop;
|
|
||||||
dest[dest.Length - 1] = runnerLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType)
|
|
||||||
{
|
|
||||||
return loopSystem.subSystemList
|
|
||||||
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType)
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
|
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
|
||||||
{
|
{
|
||||||
var loop = new PlayerLoopSystem
|
var loop = new PlayerLoopSystem
|
||||||
|
@ -285,15 +201,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
return dest.ToArray();
|
return dest.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2020_1_OR_NEWER
|
|
||||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
|
||||||
#else
|
|
||||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
#endif
|
|
||||||
static void Init()
|
static void Init()
|
||||||
{
|
{
|
||||||
// capture default(unity) sync-context.
|
// capture default(unity) sync-context.
|
||||||
unitySynchronizationContext = SynchronizationContext.Current;
|
unitySynchronizationContetext = SynchronizationContext.Current;
|
||||||
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
mainThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -366,124 +278,51 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType)
|
public static void Initialize(ref PlayerLoopSystem playerLoop)
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InsertLoop(PlayerLoopSystem[] copyList, InjectPlayerLoopTimings injectTimings, Type loopType, InjectPlayerLoopTimings targetTimings,
|
|
||||||
int index, bool injectOnFirst, Type loopRunnerYieldType, Type loopRunnerType, PlayerLoopTiming playerLoopTiming)
|
|
||||||
{
|
|
||||||
var i = FindLoopSystemIndex(copyList, loopType);
|
|
||||||
if ((injectTimings & targetTimings) == targetTimings)
|
|
||||||
{
|
|
||||||
copyList[i].subSystemList = InsertRunner(copyList[i], injectOnFirst,
|
|
||||||
loopRunnerYieldType, yielders[index] = new ContinuationQueue(playerLoopTiming),
|
|
||||||
loopRunnerType, runners[index] = new PlayerLoopRunner(playerLoopTiming));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
copyList[i].subSystemList = RemoveRunner(copyList[i], loopRunnerYieldType, loopRunnerType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Initialize(ref PlayerLoopSystem playerLoop, InjectPlayerLoopTimings injectTimings = InjectPlayerLoopTimings.All)
|
|
||||||
{
|
|
||||||
#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
|
// Initialization
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization),
|
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(PlayerLoopTiming.Initialization),
|
||||||
InjectPlayerLoopTimings.Initialization, 0, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(PlayerLoopTiming.LastInitialization),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), PlayerLoopTiming.Initialization);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.Initialization),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.LastInitialization));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization),
|
|
||||||
InjectPlayerLoopTimings.LastInitialization, 1, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), PlayerLoopTiming.LastInitialization);
|
|
||||||
|
|
||||||
// EarlyUpdate
|
// EarlyUpdate
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate),
|
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(PlayerLoopTiming.EarlyUpdate),
|
||||||
InjectPlayerLoopTimings.EarlyUpdate, 2, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), yielders[3] = new ContinuationQueue(PlayerLoopTiming.LastEarlyUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), PlayerLoopTiming.EarlyUpdate);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[2] = new PlayerLoopRunner(PlayerLoopTiming.EarlyUpdate),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), runners[3] = new PlayerLoopRunner(PlayerLoopTiming.LastEarlyUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastEarlyUpdate, 3, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), PlayerLoopTiming.LastEarlyUpdate);
|
|
||||||
|
|
||||||
// FixedUpdate
|
// FixedUpdate
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate),
|
copyList[2].subSystemList = InsertRunner(copyList[2], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[4] = new ContinuationQueue(PlayerLoopTiming.FixedUpdate),
|
||||||
InjectPlayerLoopTimings.FixedUpdate, 4, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), yielders[5] = new ContinuationQueue(PlayerLoopTiming.LastFixedUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), PlayerLoopTiming.FixedUpdate);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[4] = new PlayerLoopRunner(PlayerLoopTiming.FixedUpdate),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), runners[5] = new PlayerLoopRunner(PlayerLoopTiming.LastFixedUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastFixedUpdate, 5, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), PlayerLoopTiming.LastFixedUpdate);
|
|
||||||
|
|
||||||
// PreUpdate
|
// PreUpdate
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate),
|
copyList[3].subSystemList = InsertRunner(copyList[3], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[6] = new ContinuationQueue(PlayerLoopTiming.PreUpdate),
|
||||||
InjectPlayerLoopTimings.PreUpdate, 6, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), yielders[7] = new ContinuationQueue(PlayerLoopTiming.LastPreUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), PlayerLoopTiming.PreUpdate);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[6] = new PlayerLoopRunner(PlayerLoopTiming.PreUpdate),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), runners[7] = new PlayerLoopRunner(PlayerLoopTiming.LastPreUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastPreUpdate, 7, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), PlayerLoopTiming.LastPreUpdate);
|
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update),
|
copyList[4].subSystemList = InsertRunner(copyList[4], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[8] = new ContinuationQueue(PlayerLoopTiming.Update),
|
||||||
InjectPlayerLoopTimings.Update, 8, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), yielders[9] = new ContinuationQueue(PlayerLoopTiming.LastUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), PlayerLoopTiming.Update);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[8] = new PlayerLoopRunner(PlayerLoopTiming.Update),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), runners[9] = new PlayerLoopRunner(PlayerLoopTiming.LastUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update),
|
|
||||||
InjectPlayerLoopTimings.LastUpdate, 9, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), PlayerLoopTiming.LastUpdate);
|
|
||||||
|
|
||||||
// PreLateUpdate
|
// PreLateUpdate
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate),
|
copyList[5].subSystemList = InsertRunner(copyList[5], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[10] = new ContinuationQueue(PlayerLoopTiming.PreLateUpdate),
|
||||||
InjectPlayerLoopTimings.PreLateUpdate, 10, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), yielders[11] = new ContinuationQueue(PlayerLoopTiming.LastPreLateUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), PlayerLoopTiming.PreLateUpdate);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[10] = new PlayerLoopRunner(PlayerLoopTiming.PreLateUpdate),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), runners[11] = new PlayerLoopRunner(PlayerLoopTiming.LastPreLateUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastPreLateUpdate, 11, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), PlayerLoopTiming.LastPreLateUpdate);
|
|
||||||
|
|
||||||
// PostLateUpdate
|
// PostLateUpdate
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate),
|
copyList[6].subSystemList = InsertRunner(copyList[6], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[12] = new ContinuationQueue(PlayerLoopTiming.PostLateUpdate),
|
||||||
InjectPlayerLoopTimings.PostLateUpdate, 12, true,
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), yielders[13] = new ContinuationQueue(PlayerLoopTiming.LastPostLateUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), PlayerLoopTiming.PostLateUpdate);
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(PlayerLoopTiming.PostLateUpdate),
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner(PlayerLoopTiming.LastPostLateUpdate));
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastPostLateUpdate, 13, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), PlayerLoopTiming.LastPostLateUpdate);
|
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
// TimeUpdate
|
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate),
|
|
||||||
InjectPlayerLoopTimings.TimeUpdate, 14, true,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), PlayerLoopTiming.TimeUpdate);
|
|
||||||
|
|
||||||
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate),
|
|
||||||
InjectPlayerLoopTimings.LastTimeUpdate, 15, false,
|
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), PlayerLoopTiming.LastTimeUpdate);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Insert UniTaskSynchronizationContext to Update loop
|
// Insert UniTaskSynchronizationContext to Update loop
|
||||||
var i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Update));
|
copyList[4].subSystemList = InsertUniTaskSynchronizationContext(copyList[4]);
|
||||||
copyList[i].subSystemList = InsertUniTaskSynchronizationContext(copyList[i]);
|
|
||||||
|
|
||||||
playerLoop.subSystemList = copyList;
|
playerLoop.subSystemList = copyList;
|
||||||
PlayerLoop.SetPlayerLoop(playerLoop);
|
PlayerLoop.SetPlayerLoop(playerLoop);
|
||||||
|
@ -491,27 +330,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
|
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
|
||||||
{
|
{
|
||||||
var runner = runners[(int)timing];
|
runners[(int)timing].AddAction(action);
|
||||||
if (runner == null)
|
|
||||||
{
|
|
||||||
ThrowInvalidLoopTiming(timing);
|
|
||||||
}
|
|
||||||
runner.AddAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Target playerLoopTiming is not injected. Please check PlayerLoopHelper.Initialize. PlayerLoopTiming:" + playerLoopTiming);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddContinuation(PlayerLoopTiming timing, Action continuation)
|
public static void AddContinuation(PlayerLoopTiming timing, Action continuation)
|
||||||
{
|
{
|
||||||
var q = yielders[(int)timing];
|
yielders[(int)timing].Enqueue(continuation);
|
||||||
if (q == null)
|
|
||||||
{
|
|
||||||
ThrowInvalidLoopTiming(timing);
|
|
||||||
}
|
|
||||||
q.Enqueue(continuation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostics helper
|
// Diagnostics helper
|
||||||
|
@ -528,14 +352,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
sb.AppendFormat("------{0}------", header.type.Name);
|
sb.AppendFormat("------{0}------", header.type.Name);
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
if (header.subSystemList is null)
|
|
||||||
{
|
|
||||||
sb.AppendFormat("{0} has no subsystems!", header.ToString());
|
|
||||||
sb.AppendLine();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var subSystem in header.subSystemList)
|
foreach (var subSystem in header.subSystemList)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("{0}", subSystem.type.Name);
|
sb.AppendFormat("{0}", subSystem.type.Name);
|
||||||
|
@ -557,11 +373,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
foreach (var header in playerLoop.subSystemList)
|
foreach (var header in playerLoop.subSystemList)
|
||||||
{
|
{
|
||||||
if (header.subSystemList is null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var subSystem in header.subSystemList)
|
foreach (var subSystem in header.subSystemList)
|
||||||
{
|
{
|
||||||
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))
|
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))
|
||||||
|
|
|
@ -1,262 +0,0 @@
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
||||||
|
|
||||||
using System.Threading;
|
|
||||||
using System;
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public abstract class PlayerLoopTimer : IDisposable, IPlayerLoopItem
|
|
||||||
{
|
|
||||||
readonly CancellationToken cancellationToken;
|
|
||||||
readonly Action<object> timerCallback;
|
|
||||||
readonly object state;
|
|
||||||
readonly PlayerLoopTiming playerLoopTiming;
|
|
||||||
readonly bool periodic;
|
|
||||||
|
|
||||||
bool isRunning;
|
|
||||||
bool tryStop;
|
|
||||||
bool isDisposed;
|
|
||||||
|
|
||||||
protected PlayerLoopTimer(bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
{
|
|
||||||
this.periodic = periodic;
|
|
||||||
this.playerLoopTiming = playerLoopTiming;
|
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
this.timerCallback = timerCallback;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PlayerLoopTimer Create(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
// force use Realtime.
|
|
||||||
if (PlayerLoopHelper.IsMainThread && !UnityEditor.EditorApplication.isPlaying)
|
|
||||||
{
|
|
||||||
delayType = DelayType.Realtime;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (delayType)
|
|
||||||
{
|
|
||||||
case DelayType.UnscaledDeltaTime:
|
|
||||||
return new IgnoreTimeScalePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state);
|
|
||||||
case DelayType.Realtime:
|
|
||||||
return new RealtimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state);
|
|
||||||
case DelayType.DeltaTime:
|
|
||||||
default:
|
|
||||||
return new DeltaTimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PlayerLoopTimer StartNew(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
{
|
|
||||||
var timer = Create(interval, periodic, delayType, playerLoopTiming, cancellationToken, timerCallback, state);
|
|
||||||
timer.Restart();
|
|
||||||
return timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restart(Reset and Start) timer.
|
|
||||||
/// </summary>
|
|
||||||
public void Restart()
|
|
||||||
{
|
|
||||||
if (isDisposed) throw new ObjectDisposedException(null);
|
|
||||||
|
|
||||||
ResetCore(null); // init state
|
|
||||||
if (!isRunning)
|
|
||||||
{
|
|
||||||
isRunning = true;
|
|
||||||
PlayerLoopHelper.AddAction(playerLoopTiming, this);
|
|
||||||
}
|
|
||||||
tryStop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restart(Reset and Start) and change interval.
|
|
||||||
/// </summary>
|
|
||||||
public void Restart(TimeSpan interval)
|
|
||||||
{
|
|
||||||
if (isDisposed) throw new ObjectDisposedException(null);
|
|
||||||
|
|
||||||
ResetCore(interval); // init state
|
|
||||||
if (!isRunning)
|
|
||||||
{
|
|
||||||
isRunning = true;
|
|
||||||
PlayerLoopHelper.AddAction(playerLoopTiming, this);
|
|
||||||
}
|
|
||||||
tryStop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stop timer.
|
|
||||||
/// </summary>
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
tryStop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void ResetCore(TimeSpan? newInterval);
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
isDisposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IPlayerLoopItem.MoveNext()
|
|
||||||
{
|
|
||||||
if (isDisposed)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (tryStop)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MoveNextCore())
|
|
||||||
{
|
|
||||||
timerCallback(state);
|
|
||||||
|
|
||||||
if (periodic)
|
|
||||||
{
|
|
||||||
ResetCore(null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract bool MoveNextCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class DeltaTimePlayerLoopTimer : PlayerLoopTimer
|
|
||||||
{
|
|
||||||
int initialFrame;
|
|
||||||
float elapsed;
|
|
||||||
float interval;
|
|
||||||
|
|
||||||
public DeltaTimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
|
|
||||||
{
|
|
||||||
ResetCore(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool MoveNextCore()
|
|
||||||
{
|
|
||||||
if (elapsed == 0.0f)
|
|
||||||
{
|
|
||||||
if (initialFrame == Time.frameCount)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elapsed += Time.deltaTime;
|
|
||||||
if (elapsed >= interval)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ResetCore(TimeSpan? interval)
|
|
||||||
{
|
|
||||||
this.elapsed = 0.0f;
|
|
||||||
this.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
|
||||||
if (interval != null)
|
|
||||||
{
|
|
||||||
this.interval = (float)interval.Value.TotalSeconds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class IgnoreTimeScalePlayerLoopTimer : PlayerLoopTimer
|
|
||||||
{
|
|
||||||
int initialFrame;
|
|
||||||
float elapsed;
|
|
||||||
float interval;
|
|
||||||
|
|
||||||
public IgnoreTimeScalePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
|
|
||||||
{
|
|
||||||
ResetCore(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool MoveNextCore()
|
|
||||||
{
|
|
||||||
if (elapsed == 0.0f)
|
|
||||||
{
|
|
||||||
if (initialFrame == Time.frameCount)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elapsed += Time.unscaledDeltaTime;
|
|
||||||
if (elapsed >= interval)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ResetCore(TimeSpan? interval)
|
|
||||||
{
|
|
||||||
this.elapsed = 0.0f;
|
|
||||||
this.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
|
||||||
if (interval != null)
|
|
||||||
{
|
|
||||||
this.interval = (float)interval.Value.TotalSeconds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class RealtimePlayerLoopTimer : PlayerLoopTimer
|
|
||||||
{
|
|
||||||
ValueStopwatch stopwatch;
|
|
||||||
long intervalTicks;
|
|
||||||
|
|
||||||
public RealtimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
|
|
||||||
: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
|
|
||||||
{
|
|
||||||
ResetCore(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool MoveNextCore()
|
|
||||||
{
|
|
||||||
if (stopwatch.ElapsedTicks >= intervalTicks)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ResetCore(TimeSpan? interval)
|
|
||||||
{
|
|
||||||
this.stopwatch = ValueStopwatch.StartNew();
|
|
||||||
if (interval != null)
|
|
||||||
{
|
|
||||||
this.intervalTicks = interval.Value.Ticks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,14 +7,12 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
// internally used but public, allow to user create custom operator with pooling.
|
// internaly used but public, allow to user create custom operator with pooling.
|
||||||
|
|
||||||
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()
|
||||||
{
|
{
|
||||||
|
@ -41,28 +39,23 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<(Type, int)> GetCacheSizeInfo()
|
public static IEnumerable<(Type, int)> GetCacheSizeInfo()
|
||||||
{
|
|
||||||
lock (sizes)
|
|
||||||
{
|
{
|
||||||
foreach (var item in sizes)
|
foreach (var item in sizes)
|
||||||
{
|
{
|
||||||
yield return (item.Key, item.Value());
|
yield return (item.Key, item.Value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void RegisterSizeGetter(Type type, Func<int> getSize)
|
public static void RegisterSizeGetter(Type type, Func<int> getSize)
|
||||||
{
|
|
||||||
lock (sizes)
|
|
||||||
{
|
{
|
||||||
sizes[type] = getSize;
|
sizes[type] = getSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public interface ITaskPoolNode<T>
|
public interface ITaskPoolNode<T>
|
||||||
{
|
{
|
||||||
ref T NextNode { get; }
|
T NextNode { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutable struct, don't mark readonly.
|
// mutable struct, don't mark readonly.
|
||||||
|
@ -84,9 +77,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
var v = root;
|
var v = root;
|
||||||
if (!(v is null))
|
if (!(v is null))
|
||||||
{
|
{
|
||||||
ref var nextNode = ref v.NextNode;
|
root = v.NextNode;
|
||||||
root = nextNode;
|
v.NextNode = null;
|
||||||
nextNode = null;
|
|
||||||
size--;
|
size--;
|
||||||
result = v;
|
result = v;
|
||||||
Volatile.Write(ref gate, 0);
|
Volatile.Write(ref gate, 0);
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
// CancellationTokenSource itself can not reuse but CancelAfter(Timeout.InfiniteTimeSpan) allows reuse if did not reach timeout.
|
|
||||||
// Similar discussion:
|
|
||||||
// https://github.com/dotnet/runtime/issues/4694
|
|
||||||
// https://github.com/dotnet/runtime/issues/48492
|
|
||||||
// This TimeoutController emulate similar implementation, using CancelAfterSlim; to achieve zero allocation timeout.
|
|
||||||
|
|
||||||
public sealed class TimeoutController : IDisposable
|
|
||||||
{
|
|
||||||
readonly static Action<object> CancelCancellationTokenSourceStateDelegate = new Action<object>(CancelCancellationTokenSourceState);
|
|
||||||
|
|
||||||
static void CancelCancellationTokenSourceState(object state)
|
|
||||||
{
|
|
||||||
var cts = (CancellationTokenSource)state;
|
|
||||||
cts.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
CancellationTokenSource timeoutSource;
|
|
||||||
CancellationTokenSource linkedSource;
|
|
||||||
PlayerLoopTimer timer;
|
|
||||||
bool isDisposed;
|
|
||||||
|
|
||||||
readonly DelayType delayType;
|
|
||||||
readonly PlayerLoopTiming delayTiming;
|
|
||||||
readonly CancellationTokenSource originalLinkCancellationTokenSource;
|
|
||||||
|
|
||||||
public TimeoutController(DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
|
||||||
{
|
|
||||||
this.timeoutSource = new CancellationTokenSource();
|
|
||||||
this.originalLinkCancellationTokenSource = null;
|
|
||||||
this.linkedSource = null;
|
|
||||||
this.delayType = delayType;
|
|
||||||
this.delayTiming = delayTiming;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeoutController(CancellationTokenSource linkCancellationTokenSource, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
|
||||||
{
|
|
||||||
this.timeoutSource = new CancellationTokenSource();
|
|
||||||
this.originalLinkCancellationTokenSource = linkCancellationTokenSource;
|
|
||||||
this.linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, linkCancellationTokenSource.Token);
|
|
||||||
this.delayType = delayType;
|
|
||||||
this.delayTiming = delayTiming;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CancellationToken Timeout(int millisecondsTimeout)
|
|
||||||
{
|
|
||||||
return Timeout(TimeSpan.FromMilliseconds(millisecondsTimeout));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CancellationToken Timeout(TimeSpan timeout)
|
|
||||||
{
|
|
||||||
if (originalLinkCancellationTokenSource != null && originalLinkCancellationTokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return originalLinkCancellationTokenSource.Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timeouted, create new source and timer.
|
|
||||||
if (timeoutSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
timeoutSource.Dispose();
|
|
||||||
timeoutSource = new CancellationTokenSource();
|
|
||||||
if (linkedSource != null)
|
|
||||||
{
|
|
||||||
this.linkedSource.Cancel();
|
|
||||||
this.linkedSource.Dispose();
|
|
||||||
this.linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, originalLinkCancellationTokenSource.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer?.Dispose();
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var useSource = (linkedSource != null) ? linkedSource : timeoutSource;
|
|
||||||
var token = useSource.Token;
|
|
||||||
if (timer == null)
|
|
||||||
{
|
|
||||||
// Timer complete => timeoutSource.Cancel() -> linkedSource will be canceled.
|
|
||||||
// (linked)token is canceled => stop timer
|
|
||||||
timer = PlayerLoopTimer.StartNew(timeout, false, delayType, delayTiming, token, CancelCancellationTokenSourceStateDelegate, timeoutSource);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timer.Restart(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsTimeout()
|
|
||||||
{
|
|
||||||
return timeoutSource.IsCancellationRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
timer?.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (isDisposed) return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// stop timer.
|
|
||||||
timer?.Dispose();
|
|
||||||
|
|
||||||
// cancel and dispose.
|
|
||||||
timeoutSource.Cancel();
|
|
||||||
timeoutSource.Dispose();
|
|
||||||
if (linkedSource != null)
|
|
||||||
{
|
|
||||||
linkedSource.Cancel();
|
|
||||||
linkedSource.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
isDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,6 +20,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
ITriggerHandler<T> head; // head.prev is last
|
ITriggerHandler<T> head; // head.prev is last
|
||||||
ITriggerHandler<T> iteratingHead;
|
ITriggerHandler<T> iteratingHead;
|
||||||
|
|
||||||
|
bool preserveRemoveSelf;
|
||||||
ITriggerHandler<T> iteratingNode;
|
ITriggerHandler<T> iteratingNode;
|
||||||
|
|
||||||
void LogError(Exception ex)
|
void LogError(Exception ex)
|
||||||
|
@ -53,9 +55,18 @@ namespace Cysharp.Threading.Tasks
|
||||||
Remove(h);
|
Remove(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If `h` itself is removed by OnNext, h.Next is null.
|
if (preserveRemoveSelf)
|
||||||
// Therefore, instead of looking at h.Next, the `iteratingNode` reference itself is replaced.
|
{
|
||||||
h = h == iteratingNode ? h.Next : iteratingNode;
|
preserveRemoveSelf = false;
|
||||||
|
iteratingNode = null;
|
||||||
|
var next = h.Next;
|
||||||
|
Remove(h);
|
||||||
|
h = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h = h.Next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
|
@ -86,8 +97,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next = h == iteratingNode ? h.Next : iteratingNode;
|
preserveRemoveSelf = false;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
|
var next = h.Next;
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -120,8 +132,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next = h == iteratingNode ? h.Next : iteratingNode;
|
preserveRemoveSelf = false;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
|
var next = h.Next;
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -154,8 +167,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next = h == iteratingNode ? h.Next : iteratingNode;
|
preserveRemoveSelf = false;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
|
var next = h.Next;
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -227,6 +241,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||||
|
|
||||||
|
if (iteratingNode != null && iteratingNode == handler)
|
||||||
|
{
|
||||||
|
// if remove self, reserve remove self after invoke completed.
|
||||||
|
preserveRemoveSelf = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var prev = handler.Prev;
|
var prev = handler.Prev;
|
||||||
var next = handler.Next;
|
var next = handler.Next;
|
||||||
|
|
||||||
|
@ -239,19 +260,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
head = next;
|
head = next;
|
||||||
}
|
}
|
||||||
|
else if (handler == iteratingHead)
|
||||||
|
{
|
||||||
|
iteratingHead = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// when handler is head, prev indicate last so don't use it.
|
// when handler is head, prev indicate last so don't use it.
|
||||||
else if (prev != null)
|
if (prev != null)
|
||||||
{
|
{
|
||||||
prev.Next = next;
|
prev.Next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler == iteratingNode)
|
|
||||||
{
|
|
||||||
iteratingNode = next;
|
|
||||||
}
|
|
||||||
if (handler == iteratingHead)
|
|
||||||
{
|
|
||||||
iteratingHead = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head != null)
|
if (head != null)
|
||||||
|
@ -289,3 +308,4 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,11 +32,13 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
if (cancellationTokenSource == null)
|
if (cancellationTokenSource == null)
|
||||||
{
|
{
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
|
||||||
if (!awakeCalled)
|
if (!awakeCalled)
|
||||||
{
|
{
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return cancellationTokenSource.Token;
|
return cancellationTokenSource.Token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +83,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (trigger.called || trigger.awakeCalled) return false;
|
if (trigger.called) return false;
|
||||||
if (trigger == null)
|
if (trigger == null)
|
||||||
{
|
{
|
||||||
trigger.OnDestroy();
|
trigger.OnDestroy();
|
||||||
|
|
|
@ -8,16 +8,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public static class UniTaskCancellationExtensions
|
public static class UniTaskCancellationExtensions
|
||||||
{
|
{
|
||||||
#if UNITY_2022_2_OR_NEWER
|
|
||||||
|
|
||||||
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
|
|
||||||
public static CancellationToken GetCancellationTokenOnDestroy(this MonoBehaviour monoBehaviour)
|
|
||||||
{
|
|
||||||
return monoBehaviour.destroyCancellationToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
|
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
|
||||||
public static CancellationToken GetCancellationTokenOnDestroy(this GameObject gameObject)
|
public static CancellationToken GetCancellationTokenOnDestroy(this GameObject gameObject)
|
||||||
{
|
{
|
||||||
|
@ -27,13 +17,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
|
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
|
||||||
public static CancellationToken GetCancellationTokenOnDestroy(this Component component)
|
public static CancellationToken GetCancellationTokenOnDestroy(this Component component)
|
||||||
{
|
{
|
||||||
#if UNITY_2022_2_OR_NEWER
|
|
||||||
if (component is MonoBehaviour mb)
|
|
||||||
{
|
|
||||||
return mb.destroyCancellationToken;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return component.GetAsyncDestroyTrigger().CancellationToken;
|
return component.GetAsyncDestroyTrigger().CancellationToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Triggers
|
namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
|
@ -717,7 +715,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionEnter
|
#region CollisionEnter
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionEnterHandler
|
public interface IAsyncOnCollisionEnterHandler
|
||||||
{
|
{
|
||||||
|
@ -774,11 +771,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionEnterHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionEnterAsync();
|
return ((IAsyncOnCollisionEnterHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionEnter2D
|
#region CollisionEnter2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionEnter2DHandler
|
public interface IAsyncOnCollisionEnter2DHandler
|
||||||
{
|
{
|
||||||
|
@ -835,11 +830,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionEnter2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionEnter2DAsync();
|
return ((IAsyncOnCollisionEnter2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionEnter2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionExit
|
#region CollisionExit
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionExitHandler
|
public interface IAsyncOnCollisionExitHandler
|
||||||
{
|
{
|
||||||
|
@ -896,11 +889,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionExitHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionExitAsync();
|
return ((IAsyncOnCollisionExitHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionExit2D
|
#region CollisionExit2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionExit2DHandler
|
public interface IAsyncOnCollisionExit2DHandler
|
||||||
{
|
{
|
||||||
|
@ -957,11 +948,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionExit2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionExit2DAsync();
|
return ((IAsyncOnCollisionExit2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionExit2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionStay
|
#region CollisionStay
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionStayHandler
|
public interface IAsyncOnCollisionStayHandler
|
||||||
{
|
{
|
||||||
|
@ -1018,11 +1007,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionStayHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionStayAsync();
|
return ((IAsyncOnCollisionStayHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionStayAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionStay2D
|
#region CollisionStay2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCollisionStay2DHandler
|
public interface IAsyncOnCollisionStay2DHandler
|
||||||
{
|
{
|
||||||
|
@ -1079,11 +1066,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCollisionStay2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionStay2DAsync();
|
return ((IAsyncOnCollisionStay2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionStay2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ControllerColliderHit
|
#region ControllerColliderHit
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnControllerColliderHitHandler
|
public interface IAsyncOnControllerColliderHitHandler
|
||||||
{
|
{
|
||||||
|
@ -1140,7 +1125,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnControllerColliderHitHandler)new AsyncTriggerHandler<ControllerColliderHit>(this, cancellationToken, true)).OnControllerColliderHitAsync();
|
return ((IAsyncOnControllerColliderHitHandler)new AsyncTriggerHandler<ControllerColliderHit>(this, cancellationToken, true)).OnControllerColliderHitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Disable
|
#region Disable
|
||||||
|
@ -1439,7 +1423,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region JointBreak
|
#region JointBreak
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnJointBreakHandler
|
public interface IAsyncOnJointBreakHandler
|
||||||
{
|
{
|
||||||
|
@ -1496,11 +1479,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnJointBreakHandler)new AsyncTriggerHandler<float>(this, cancellationToken, true)).OnJointBreakAsync();
|
return ((IAsyncOnJointBreakHandler)new AsyncTriggerHandler<float>(this, cancellationToken, true)).OnJointBreakAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region JointBreak2D
|
#region JointBreak2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnJointBreak2DHandler
|
public interface IAsyncOnJointBreak2DHandler
|
||||||
{
|
{
|
||||||
|
@ -1557,11 +1538,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnJointBreak2DHandler)new AsyncTriggerHandler<Joint2D>(this, cancellationToken, true)).OnJointBreak2DAsync();
|
return ((IAsyncOnJointBreak2DHandler)new AsyncTriggerHandler<Joint2D>(this, cancellationToken, true)).OnJointBreak2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region MouseDown
|
#region MouseDown
|
||||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
|
||||||
|
|
||||||
public interface IAsyncOnMouseDownHandler
|
public interface IAsyncOnMouseDownHandler
|
||||||
{
|
{
|
||||||
|
@ -1618,11 +1597,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1679,11 +1656,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1740,11 +1715,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1801,11 +1774,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1862,11 +1833,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1923,11 +1892,9 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -1984,7 +1951,6 @@ 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
|
||||||
|
@ -2165,7 +2131,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ParticleUpdateJobScheduled
|
#region ParticleUpdateJobScheduled
|
||||||
#if UNITY_2019_3_OR_NEWER && (!UNITY_2019_1_OR_NEWER || UNITASK_PARTICLESYSTEM_SUPPORT)
|
#if UNITY_2019_3_OR_NEWER
|
||||||
|
|
||||||
public interface IAsyncOnParticleUpdateJobScheduledHandler
|
public interface IAsyncOnParticleUpdateJobScheduledHandler
|
||||||
{
|
{
|
||||||
|
@ -2816,7 +2782,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerEnter
|
#region TriggerEnter
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerEnterHandler
|
public interface IAsyncOnTriggerEnterHandler
|
||||||
{
|
{
|
||||||
|
@ -2873,11 +2838,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerEnterHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerEnterAsync();
|
return ((IAsyncOnTriggerEnterHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerEnter2D
|
#region TriggerEnter2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerEnter2DHandler
|
public interface IAsyncOnTriggerEnter2DHandler
|
||||||
{
|
{
|
||||||
|
@ -2934,11 +2897,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerEnter2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerEnter2DAsync();
|
return ((IAsyncOnTriggerEnter2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerEnter2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerExit
|
#region TriggerExit
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerExitHandler
|
public interface IAsyncOnTriggerExitHandler
|
||||||
{
|
{
|
||||||
|
@ -2995,11 +2956,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerExitHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerExitAsync();
|
return ((IAsyncOnTriggerExitHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerExit2D
|
#region TriggerExit2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerExit2DHandler
|
public interface IAsyncOnTriggerExit2DHandler
|
||||||
{
|
{
|
||||||
|
@ -3056,11 +3015,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerExit2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerExit2DAsync();
|
return ((IAsyncOnTriggerExit2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerExit2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerStay
|
#region TriggerStay
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerStayHandler
|
public interface IAsyncOnTriggerStayHandler
|
||||||
{
|
{
|
||||||
|
@ -3117,11 +3074,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerStayHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerStayAsync();
|
return ((IAsyncOnTriggerStayHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerStayAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerStay2D
|
#region TriggerStay2D
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnTriggerStay2DHandler
|
public interface IAsyncOnTriggerStay2DHandler
|
||||||
{
|
{
|
||||||
|
@ -3178,7 +3133,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnTriggerStay2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerStay2DAsync();
|
return ((IAsyncOnTriggerStay2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerStay2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Validate
|
#region Validate
|
||||||
|
@ -3418,7 +3372,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region BeginDrag
|
#region BeginDrag
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnBeginDragHandler
|
public interface IAsyncOnBeginDragHandler
|
||||||
{
|
{
|
||||||
|
@ -3475,11 +3428,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnBeginDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnBeginDragAsync();
|
return ((IAsyncOnBeginDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnBeginDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Cancel
|
#region Cancel
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnCancelHandler
|
public interface IAsyncOnCancelHandler
|
||||||
{
|
{
|
||||||
|
@ -3536,11 +3487,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnCancelHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnCancelAsync();
|
return ((IAsyncOnCancelHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnCancelAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Deselect
|
#region Deselect
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnDeselectHandler
|
public interface IAsyncOnDeselectHandler
|
||||||
{
|
{
|
||||||
|
@ -3597,11 +3546,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnDeselectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnDeselectAsync();
|
return ((IAsyncOnDeselectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnDeselectAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Drag
|
#region Drag
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnDragHandler
|
public interface IAsyncOnDragHandler
|
||||||
{
|
{
|
||||||
|
@ -3658,11 +3605,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDragAsync();
|
return ((IAsyncOnDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Drop
|
#region Drop
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnDropHandler
|
public interface IAsyncOnDropHandler
|
||||||
{
|
{
|
||||||
|
@ -3719,11 +3664,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnDropHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDropAsync();
|
return ((IAsyncOnDropHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDropAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region EndDrag
|
#region EndDrag
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnEndDragHandler
|
public interface IAsyncOnEndDragHandler
|
||||||
{
|
{
|
||||||
|
@ -3780,11 +3723,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnEndDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnEndDragAsync();
|
return ((IAsyncOnEndDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnEndDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region InitializePotentialDrag
|
#region InitializePotentialDrag
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnInitializePotentialDragHandler
|
public interface IAsyncOnInitializePotentialDragHandler
|
||||||
{
|
{
|
||||||
|
@ -3841,11 +3782,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnInitializePotentialDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnInitializePotentialDragAsync();
|
return ((IAsyncOnInitializePotentialDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnInitializePotentialDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Move
|
#region Move
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnMoveHandler
|
public interface IAsyncOnMoveHandler
|
||||||
{
|
{
|
||||||
|
@ -3902,11 +3841,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnMoveHandler)new AsyncTriggerHandler<AxisEventData>(this, cancellationToken, true)).OnMoveAsync();
|
return ((IAsyncOnMoveHandler)new AsyncTriggerHandler<AxisEventData>(this, cancellationToken, true)).OnMoveAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerClick
|
#region PointerClick
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnPointerClickHandler
|
public interface IAsyncOnPointerClickHandler
|
||||||
{
|
{
|
||||||
|
@ -3963,11 +3900,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnPointerClickHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerClickAsync();
|
return ((IAsyncOnPointerClickHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerClickAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerDown
|
#region PointerDown
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnPointerDownHandler
|
public interface IAsyncOnPointerDownHandler
|
||||||
{
|
{
|
||||||
|
@ -4024,11 +3959,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnPointerDownHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerDownAsync();
|
return ((IAsyncOnPointerDownHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerDownAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerEnter
|
#region PointerEnter
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnPointerEnterHandler
|
public interface IAsyncOnPointerEnterHandler
|
||||||
{
|
{
|
||||||
|
@ -4085,11 +4018,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnPointerEnterHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerEnterAsync();
|
return ((IAsyncOnPointerEnterHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerExit
|
#region PointerExit
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnPointerExitHandler
|
public interface IAsyncOnPointerExitHandler
|
||||||
{
|
{
|
||||||
|
@ -4146,11 +4077,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnPointerExitHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerExitAsync();
|
return ((IAsyncOnPointerExitHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerUp
|
#region PointerUp
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnPointerUpHandler
|
public interface IAsyncOnPointerUpHandler
|
||||||
{
|
{
|
||||||
|
@ -4207,11 +4136,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnPointerUpHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerUpAsync();
|
return ((IAsyncOnPointerUpHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerUpAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Scroll
|
#region Scroll
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnScrollHandler
|
public interface IAsyncOnScrollHandler
|
||||||
{
|
{
|
||||||
|
@ -4268,11 +4195,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnScrollHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnScrollAsync();
|
return ((IAsyncOnScrollHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnScrollAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Select
|
#region Select
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnSelectHandler
|
public interface IAsyncOnSelectHandler
|
||||||
{
|
{
|
||||||
|
@ -4329,11 +4254,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnSelectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSelectAsync();
|
return ((IAsyncOnSelectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSelectAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Submit
|
#region Submit
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnSubmitHandler
|
public interface IAsyncOnSubmitHandler
|
||||||
{
|
{
|
||||||
|
@ -4390,11 +4313,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnSubmitHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSubmitAsync();
|
return ((IAsyncOnSubmitHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSubmitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UpdateSelected
|
#region UpdateSelected
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
|
|
||||||
public interface IAsyncOnUpdateSelectedHandler
|
public interface IAsyncOnUpdateSelectedHandler
|
||||||
{
|
{
|
||||||
|
@ -4451,7 +4372,6 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return ((IAsyncOnUpdateSelectedHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnUpdateSelectedAsync();
|
return ((IAsyncOnUpdateSelectedHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnUpdateSelectedAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,7 +25,13 @@
|
||||||
("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),
|
||||||
|
@ -41,15 +47,6 @@
|
||||||
("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") }),
|
||||||
|
@ -106,36 +103,20 @@
|
||||||
Func<(string argType, string argName)[], string> BuildMethodArgument = x => string.Join(", ", x.Select(y => y.argType + " " + y.argName));
|
Func<(string argType, string argName)[], string> BuildMethodArgument = x => string.Join(", ", x.Select(y => y.argType + " " + y.argName));
|
||||||
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> IsParticleSystem = x => x == "ParticleUpdateJobScheduled";
|
Func<string, bool> Is2019_3 = x => x == "ParticleUpdateJobScheduled";
|
||||||
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
|
|
||||||
Func<string, string> RequirePhysicsModule = x => (x.StartsWith("Collision") || x.StartsWith("Collider") || x.StartsWith("ControllerCollider") || x.StartsWith("Joint") || x.StartsWith("Trigger"))
|
|
||||||
? (x.Contains("2D") ? "UNITASK_PHYSICS2D_SUPPORT" : "UNITASK_PHYSICS_SUPPORT")
|
|
||||||
: null;
|
|
||||||
Func<string, bool> IsUguiSystem = x => x != null;
|
|
||||||
#>
|
#>
|
||||||
#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 System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Triggers
|
namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
<# foreach(var t in triggers) { #>
|
<# foreach(var t in triggers) { #>
|
||||||
#region <#= t.triggerName #>
|
#region <#= t.triggerName #>
|
||||||
<# if(IsUguiSystem(t.handlerInterface)) { #>
|
<# if(Is2019_3(t.triggerName)) { #>
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
#if UNITY_2019_3_OR_NEWER
|
||||||
<# } #>
|
|
||||||
<# if(IsParticleSystem(t.triggerName)) { #>
|
|
||||||
#if UNITY_2019_3_OR_NEWER && (!UNITY_2019_1_OR_NEWER || UNITASK_PARTICLESYSTEM_SUPPORT)
|
|
||||||
<# } #>
|
|
||||||
<# if(IsMouseTrigger(t.triggerName)) { #>
|
|
||||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
|
||||||
<# } #>
|
|
||||||
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
|
|
||||||
#if !UNITY_2019_1_OR_NEWER || <#= RequirePhysicsModule(t.triggerName) #>
|
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
public interface <#= ToInterfaceName(t.methodName) #>
|
public interface <#= ToInterfaceName(t.methodName) #>
|
||||||
|
@ -193,13 +174,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(IsUguiSystem(t.handlerInterface)) { #>
|
<# if(Is2019_3(t.triggerName)) { #>
|
||||||
#endif
|
|
||||||
<# } #>
|
|
||||||
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
|
|
||||||
#endif
|
|
||||||
<# } #>
|
|
||||||
<# if(IsParticleSystem(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
|
|
||||||
#endif
|
#endif
|
||||||
<# } #>
|
<# } #>
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -21,176 +20,106 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
public static YieldAwaitable Yield()
|
public static YieldAwaitable Yield(PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
||||||
{
|
|
||||||
// optimized for single continuation
|
|
||||||
return new YieldAwaitable(PlayerLoopTiming.Update);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static YieldAwaitable Yield(PlayerLoopTiming timing)
|
|
||||||
{
|
{
|
||||||
// optimized for single continuation
|
// optimized for single continuation
|
||||||
return new YieldAwaitable(timing);
|
return new YieldAwaitable(timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Yield(CancellationToken cancellationToken, bool cancelImmediately = false)
|
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame()
|
public static UniTask NextFrame(PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, false, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing)
|
|
||||||
{
|
|
||||||
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, false, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
|
||||||
/// </summary>
|
|
||||||
public static UniTask NextFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
|
||||||
/// </summary>
|
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
return new UniTask(NextFramePromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_2023_1_OR_NEWER
|
|
||||||
public static async UniTask WaitForEndOfFrame(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
await Awaitable.EndOfFrameAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
|
||||||
public static YieldAwaitable WaitForEndOfFrame()
|
public static YieldAwaitable WaitForEndOfFrame()
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
/// <summary>
|
||||||
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken).
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken, cancelImmediately);
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner)
|
|
||||||
{
|
|
||||||
var source = WaitForEndOfFramePromise.Create(coroutineRunner, CancellationToken.None, false, out var token);
|
|
||||||
return new UniTask(source, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, cancelImmediately, out var token);
|
|
||||||
return new UniTask(source, token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate).
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static YieldAwaitable WaitForFixedUpdate()
|
public static YieldAwaitable WaitForFixedUpdate()
|
||||||
{
|
{
|
||||||
// use LastFixedUpdate instead of FixedUpdate
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate);
|
||||||
// https://github.com/Cysharp/UniTask/issues/377
|
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
|
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken, bool cancelImmediately = false)
|
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken, cancelImmediately);
|
return UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
|
||||||
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
{
|
||||||
if (delayFrameCount < 0)
|
if (delayFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (delayTimeSpan < TimeSpan.Zero)
|
if (delayTimeSpan < TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayTimeSpan. delayTimeSpan:" + delayTimeSpan);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayTimeSpan. delayTimeSpan:" + delayTimeSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
// force use Realtime.
|
|
||||||
if (PlayerLoopHelper.IsMainThread && !UnityEditor.EditorApplication.isPlaying)
|
|
||||||
{
|
|
||||||
delayType = DelayType.Realtime;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (delayType)
|
switch (delayType)
|
||||||
{
|
{
|
||||||
case DelayType.UnscaledDeltaTime:
|
case DelayType.UnscaledDeltaTime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.Realtime:
|
case DelayType.Realtime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.DeltaTime:
|
case DelayType.DeltaTime:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,8 +127,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
|
sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
|
||||||
{
|
{
|
||||||
static TaskPool<YieldPromise> pool;
|
static TaskPool<YieldPromise> pool;
|
||||||
YieldPromise nextNode;
|
public YieldPromise NextNode { get; set; }
|
||||||
public ref YieldPromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static YieldPromise()
|
static YieldPromise()
|
||||||
{
|
{
|
||||||
|
@ -207,15 +135,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
YieldPromise()
|
YieldPromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -227,17 +153,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
result = new YieldPromise();
|
result = new YieldPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
result.cancellationToken = cancellationToken;
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (YieldPromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -254,16 +171,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -298,8 +208,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,8 +215,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<NextFramePromise> pool;
|
static TaskPool<NextFramePromise> pool;
|
||||||
NextFramePromise nextNode;
|
public NextFramePromise NextNode { get; set; }
|
||||||
public ref NextFramePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static NextFramePromise()
|
static NextFramePromise()
|
||||||
{
|
{
|
||||||
|
@ -316,16 +223,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameCount;
|
int frameCount;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
NextFramePromise()
|
NextFramePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -339,16 +244,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (NextFramePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -365,16 +260,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -414,143 +302,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitForEndOfFramePromise : IUniTaskSource, ITaskPoolNode<WaitForEndOfFramePromise>, System.Collections.IEnumerator
|
|
||||||
{
|
|
||||||
static TaskPool<WaitForEndOfFramePromise> pool;
|
|
||||||
WaitForEndOfFramePromise nextNode;
|
|
||||||
public ref WaitForEndOfFramePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitForEndOfFramePromise()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
WaitForEndOfFramePromise()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new WaitForEndOfFramePromise();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitForEndOfFramePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
coroutineRunner.StartCoroutine(result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
Reset(); // Reset Enumerator
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coroutine Runner implementation
|
|
||||||
|
|
||||||
static readonly WaitForEndOfFrame waitForEndOfFrameYieldInstruction = new WaitForEndOfFrame();
|
|
||||||
bool isFirst = true;
|
|
||||||
|
|
||||||
object IEnumerator.Current => waitForEndOfFrameYieldInstruction;
|
|
||||||
|
|
||||||
bool IEnumerator.MoveNext()
|
|
||||||
{
|
|
||||||
if (isFirst)
|
|
||||||
{
|
|
||||||
isFirst = false;
|
|
||||||
return true; // start WaitForEndOfFrame
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
isFirst = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayFramePromise> pool;
|
static TaskPool<DelayFramePromise> pool;
|
||||||
DelayFramePromise nextNode;
|
public DelayFramePromise NextNode { get; set; }
|
||||||
public ref DelayFramePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static DelayFramePromise()
|
static DelayFramePromise()
|
||||||
{
|
{
|
||||||
|
@ -560,8 +319,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
int delayFrameCount;
|
int delayFrameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
int currentFrameCount;
|
int currentFrameCount;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
@ -570,7 +327,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -585,16 +342,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayFrameCount = delayFrameCount;
|
result.delayFrameCount = delayFrameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (DelayFramePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -611,16 +358,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -657,20 +397,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
// skip in initial frame.
|
// skip in initial frame.
|
||||||
if (initialFrame == Time.frameCount)
|
if (initialFrame == Time.frameCount)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
|
||||||
// force use Realtime.
|
|
||||||
if (PlayerLoopHelper.IsMainThread && !UnityEditor.EditorApplication.isPlaying)
|
|
||||||
{
|
|
||||||
//goto ++currentFrameCount
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++currentFrameCount >= delayFrameCount)
|
if (++currentFrameCount >= delayFrameCount)
|
||||||
|
@ -689,8 +417,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
currentFrameCount = default;
|
currentFrameCount = default;
|
||||||
delayFrameCount = default;
|
delayFrameCount = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -698,8 +424,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
|
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayPromise> pool;
|
static TaskPool<DelayPromise> pool;
|
||||||
DelayPromise nextNode;
|
public DelayPromise NextNode { get; set; }
|
||||||
public ref DelayPromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static DelayPromise()
|
static DelayPromise()
|
||||||
{
|
{
|
||||||
|
@ -710,8 +435,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
float delayTimeSpan;
|
float delayTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -719,7 +442,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -735,16 +458,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (DelayPromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -761,16 +474,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -821,8 +527,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
delayTimeSpan = default;
|
delayTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -830,8 +534,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayIgnoreTimeScalePromise>
|
sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayIgnoreTimeScalePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayIgnoreTimeScalePromise> pool;
|
static TaskPool<DelayIgnoreTimeScalePromise> pool;
|
||||||
DelayIgnoreTimeScalePromise nextNode;
|
public DelayIgnoreTimeScalePromise NextNode { get; set; }
|
||||||
public ref DelayIgnoreTimeScalePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static DelayIgnoreTimeScalePromise()
|
static DelayIgnoreTimeScalePromise()
|
||||||
{
|
{
|
||||||
|
@ -842,8 +545,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
float elapsed;
|
float elapsed;
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -851,7 +552,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -867,16 +568,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (DelayIgnoreTimeScalePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -893,16 +584,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -953,8 +637,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
delayFrameTimeSpan = default;
|
delayFrameTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -962,8 +644,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class DelayRealtimePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayRealtimePromise>
|
sealed class DelayRealtimePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayRealtimePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<DelayRealtimePromise> pool;
|
static TaskPool<DelayRealtimePromise> pool;
|
||||||
DelayRealtimePromise nextNode;
|
public DelayRealtimePromise NextNode { get; set; }
|
||||||
public ref DelayRealtimePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static DelayRealtimePromise()
|
static DelayRealtimePromise()
|
||||||
{
|
{
|
||||||
|
@ -973,8 +654,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
long delayTimeSpanTicks;
|
long delayTimeSpanTicks;
|
||||||
ValueStopwatch stopwatch;
|
ValueStopwatch stopwatch;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
@ -982,7 +661,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -997,16 +676,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.stopwatch = ValueStopwatch.StartNew();
|
result.stopwatch = ValueStopwatch.StartNew();
|
||||||
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (DelayRealtimePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -1023,16 +692,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -1058,12 +720,6 @@ 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);
|
||||||
|
@ -1079,8 +735,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
stopwatch = default;
|
stopwatch = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,16 +81,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
return factory();
|
return factory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Create(Func<CancellationToken, UniTask> factory, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return factory(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask Create<T>(T state, Func<T, UniTask> factory)
|
|
||||||
{
|
|
||||||
return factory(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<T> Create<T>(Func<UniTask<T>> factory)
|
public static UniTask<T> Create<T>(Func<UniTask<T>> factory)
|
||||||
{
|
{
|
||||||
return factory();
|
return factory();
|
||||||
|
@ -147,19 +137,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
return () => asyncAction(cancellationToken).Forget();
|
return () => asyncAction(cancellationToken).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// helper of create add UniTaskVoid to delegate.
|
|
||||||
/// </summary>
|
|
||||||
public static Action Action<T>(T state, Func<T, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return () => asyncAction(state).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } ))
|
/// For exampe: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } ))
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction)
|
public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction)
|
||||||
{
|
{
|
||||||
|
@ -168,94 +150,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy()))
|
/// For exampe: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy()))
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return () => asyncAction(cancellationToken).Forget();
|
return () => asyncAction(cancellationToken).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, Argument))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction UnityAction<T>(T state, Func<T, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return () => asyncAction(state).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T arg) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return (arg) => asyncAction(arg).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return (arg0, arg1) => asyncAction(arg0, arg1).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, UniTaskVoid> asyncAction)
|
|
||||||
{
|
|
||||||
return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T arg, CancellationToken cancellationToken) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return (arg) => asyncAction(arg, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, CancellationToken cancellationToken) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return (arg0, arg1) => asyncAction(arg0, arg1, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, CancellationToken cancellationToken) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
|
||||||
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) => { /* */ } ))
|
|
||||||
/// </summary>
|
|
||||||
public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -274,22 +175,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defer the task creation just before call await.
|
|
||||||
/// </summary>
|
|
||||||
public static UniTask Defer<TState>(TState state, Func<TState, UniTask> factory)
|
|
||||||
{
|
|
||||||
return new UniTask(new DeferPromiseWithState<TState>(state, factory), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defer the task creation just before call await.
|
|
||||||
/// </summary>
|
|
||||||
public static UniTask<TResult> Defer<TState, TResult>(TState state, Func<TState, UniTask<TResult>> factory)
|
|
||||||
{
|
|
||||||
return new UniTask<TResult>(new DeferPromiseWithState<TState, TResult>(state, factory), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Never complete.
|
/// Never complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -309,7 +194,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class ExceptionResultSource : IUniTaskSource
|
sealed class ExceptionResultSource : IUniTaskSource
|
||||||
{
|
{
|
||||||
readonly ExceptionDispatchInfo exception;
|
readonly ExceptionDispatchInfo exception;
|
||||||
bool calledGet;
|
|
||||||
|
|
||||||
public ExceptionResultSource(Exception exception)
|
public ExceptionResultSource(Exception exception)
|
||||||
{
|
{
|
||||||
|
@ -318,11 +202,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
{
|
{
|
||||||
if (!calledGet)
|
|
||||||
{
|
|
||||||
calledGet = true;
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
exception.Throw();
|
exception.Throw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,20 +219,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
continuation(state);
|
continuation(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExceptionResultSource()
|
|
||||||
{
|
|
||||||
if (!calledGet)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class ExceptionResultSource<T> : IUniTaskSource<T>
|
sealed class ExceptionResultSource<T> : IUniTaskSource<T>
|
||||||
{
|
{
|
||||||
readonly ExceptionDispatchInfo exception;
|
readonly ExceptionDispatchInfo exception;
|
||||||
bool calledGet;
|
|
||||||
|
|
||||||
public ExceptionResultSource(Exception exception)
|
public ExceptionResultSource(Exception exception)
|
||||||
{
|
{
|
||||||
|
@ -362,22 +232,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public T GetResult(short token)
|
public T GetResult(short token)
|
||||||
{
|
{
|
||||||
if (!calledGet)
|
|
||||||
{
|
|
||||||
calledGet = true;
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
exception.Throw();
|
exception.Throw();
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
{
|
{
|
||||||
if (!calledGet)
|
|
||||||
{
|
|
||||||
calledGet = true;
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
exception.Throw();
|
exception.Throw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,14 +255,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
continuation(state);
|
continuation(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExceptionResultSource()
|
|
||||||
{
|
|
||||||
if (!calledGet)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class CanceledResultSource : IUniTaskSource
|
sealed class CanceledResultSource : IUniTaskSource
|
||||||
|
@ -489,12 +341,10 @@ 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)
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
{
|
|
||||||
task = f();
|
task = f();
|
||||||
awaiter = task.GetAwaiter();
|
awaiter = task.GetAwaiter();
|
||||||
}
|
|
||||||
|
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,99 +383,10 @@ 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)
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
{
|
|
||||||
task = f();
|
task = f();
|
||||||
awaiter = task.GetAwaiter();
|
awaiter = task.GetAwaiter();
|
||||||
}
|
|
||||||
|
|
||||||
return task.Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(continuation, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return task.Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class DeferPromiseWithState<TState> : IUniTaskSource
|
|
||||||
{
|
|
||||||
Func<TState, UniTask> factory;
|
|
||||||
TState argument;
|
|
||||||
UniTask task;
|
|
||||||
UniTask.Awaiter awaiter;
|
|
||||||
|
|
||||||
public DeferPromiseWithState(TState argument, Func<TState, UniTask> factory)
|
|
||||||
{
|
|
||||||
this.argument = argument;
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
awaiter.GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
var f = Interlocked.Exchange(ref factory, null);
|
|
||||||
if (f != null)
|
|
||||||
{
|
|
||||||
task = f(argument);
|
|
||||||
awaiter = task.GetAwaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
return task.Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(continuation, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return task.Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class DeferPromiseWithState<TState, TResult> : IUniTaskSource<TResult>
|
|
||||||
{
|
|
||||||
Func<TState, UniTask<TResult>> factory;
|
|
||||||
TState argument;
|
|
||||||
UniTask<TResult> task;
|
|
||||||
UniTask<TResult>.Awaiter awaiter;
|
|
||||||
|
|
||||||
public DeferPromiseWithState(TState argument, Func<TState, UniTask<TResult>> factory)
|
|
||||||
{
|
|
||||||
this.argument = argument;
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TResult GetResult(short token)
|
|
||||||
{
|
|
||||||
return awaiter.GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
|
||||||
{
|
|
||||||
awaiter.GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
var f = Interlocked.Exchange(ref factory, null);
|
|
||||||
if (f != null)
|
|
||||||
{
|
|
||||||
task = f(argument);
|
|
||||||
awaiter = task.GetAwaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,60 +7,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
#region OBSOLETE_RUN
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask Run(Action action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(action, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask Run(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(action, state, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask Run(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(action, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask Run(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(action, state, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask<T> Run<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(func, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask<T> Run<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(func, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(func, state, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("UniTask.Run is similar as Task.Run, it uses ThreadPool. For equivalent behaviour, use UniTask.RunOnThreadPool instead. If you don't want to use ThreadPool, you can use UniTask.Void(async void) or UniTask.Create(async UniTask) too.")]
|
|
||||||
public static UniTask<T> Run<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return RunOnThreadPool(func, state, configureAwait, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask RunOnThreadPool(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();
|
||||||
|
|
||||||
|
@ -88,7 +36,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask RunOnThreadPool(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();
|
||||||
|
|
||||||
|
@ -116,7 +64,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask RunOnThreadPool(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();
|
||||||
|
|
||||||
|
@ -144,7 +92,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask RunOnThreadPool(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();
|
||||||
|
|
||||||
|
@ -172,7 +120,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask<T> RunOnThreadPool<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();
|
||||||
|
|
||||||
|
@ -199,7 +147,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask<T> RunOnThreadPool<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();
|
||||||
|
|
||||||
|
@ -229,7 +177,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask<T> RunOnThreadPool<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();
|
||||||
|
|
||||||
|
@ -256,7 +204,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||||
public static async UniTask<T> RunOnThreadPool<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();
|
||||||
|
|
||||||
|
|
|
@ -224,8 +224,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
||||||
{
|
{
|
||||||
static TaskPool<ThreadPoolWorkItem> pool;
|
static TaskPool<ThreadPoolWorkItem> pool;
|
||||||
ThreadPoolWorkItem nextNode;
|
public ThreadPoolWorkItem NextNode { get; set; }
|
||||||
public ref ThreadPoolWorkItem NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static ThreadPoolWorkItem()
|
static ThreadPoolWorkItem()
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Tracing;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
|
||||||
|
@ -10,47 +9,36 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitUntil<T>(T state, Func<T, bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilPromise<T>.Create(state, predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitWhile<T>(T state, Func<T, bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
|
||||||
return new UniTask(WaitWhilePromise<T>.Create(state, predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update, bool completeImmediately = false)
|
|
||||||
{
|
|
||||||
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, completeImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
||||||
|
|
||||||
return new UniTask<U>(isUnityObject
|
return new UniTask<U>(isUnityObject
|
||||||
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out var token)
|
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out var token)
|
||||||
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out token), token);
|
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitUntilPromise> pool;
|
static TaskPool<WaitUntilPromise> pool;
|
||||||
WaitUntilPromise nextNode;
|
public WaitUntilPromise NextNode { get; set; }
|
||||||
public ref WaitUntilPromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitUntilPromise()
|
static WaitUntilPromise()
|
||||||
{
|
{
|
||||||
|
@ -59,8 +47,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
Func<bool> predicate;
|
Func<bool> predicate;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -68,7 +54,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -82,16 +68,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitUntilPromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -108,16 +84,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -166,137 +135,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class WaitUntilPromise<T> : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise<T>>
|
|
||||||
{
|
|
||||||
static TaskPool<WaitUntilPromise<T>> pool;
|
|
||||||
WaitUntilPromise<T> nextNode;
|
|
||||||
public ref WaitUntilPromise<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitUntilPromise()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitUntilPromise<T>), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Func<T, bool> predicate;
|
|
||||||
T argument;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
|
||||||
|
|
||||||
WaitUntilPromise()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(T argument, Func<T, bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new WaitUntilPromise<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.predicate = predicate;
|
|
||||||
result.argument = argument;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitUntilPromise<T>)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!predicate(argument))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
core.TrySetException(ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
predicate = default;
|
|
||||||
argument = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,8 +142,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitWhilePromise> pool;
|
static TaskPool<WaitWhilePromise> pool;
|
||||||
WaitWhilePromise nextNode;
|
public WaitWhilePromise NextNode { get; set; }
|
||||||
public ref WaitWhilePromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitWhilePromise()
|
static WaitWhilePromise()
|
||||||
{
|
{
|
||||||
|
@ -314,8 +151,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
Func<bool> predicate;
|
Func<bool> predicate;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -323,7 +158,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -337,16 +172,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitWhilePromise)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -363,16 +188,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -421,137 +239,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class WaitWhilePromise<T> : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise<T>>
|
|
||||||
{
|
|
||||||
static TaskPool<WaitWhilePromise<T>> pool;
|
|
||||||
WaitWhilePromise<T> nextNode;
|
|
||||||
public ref WaitWhilePromise<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitWhilePromise()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitWhilePromise<T>), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Func<T, bool> predicate;
|
|
||||||
T argument;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
|
||||||
|
|
||||||
WaitWhilePromise()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(T argument, Func<T, bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new WaitWhilePromise<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.predicate = predicate;
|
|
||||||
result.argument = argument;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitWhilePromise<T>)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (predicate(argument))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
core.TrySetException(ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
predicate = default;
|
|
||||||
argument = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,8 +246,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitUntilCanceledPromise> pool;
|
static TaskPool<WaitUntilCanceledPromise> pool;
|
||||||
WaitUntilCanceledPromise nextNode;
|
public WaitUntilCanceledPromise NextNode { get; set; }
|
||||||
public ref WaitUntilCanceledPromise NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitUntilCanceledPromise()
|
static WaitUntilCanceledPromise()
|
||||||
{
|
{
|
||||||
|
@ -568,8 +254,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -577,7 +261,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, bool cancelImmediately, out short token)
|
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -590,16 +274,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitUntilCanceledPromise)state;
|
|
||||||
promise.core.TrySetResult(null);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -616,16 +290,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -659,8 +326,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,8 +334,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
sealed class WaitUntilValueChangedUnityObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, ITaskPoolNode<WaitUntilValueChangedUnityObjectPromise<T, U>>
|
sealed class WaitUntilValueChangedUnityObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, ITaskPoolNode<WaitUntilValueChangedUnityObjectPromise<T, U>>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitUntilValueChangedUnityObjectPromise<T, U>> pool;
|
static TaskPool<WaitUntilValueChangedUnityObjectPromise<T, U>> pool;
|
||||||
WaitUntilValueChangedUnityObjectPromise<T, U> nextNode;
|
public WaitUntilValueChangedUnityObjectPromise<T, U> NextNode { get; set; }
|
||||||
public ref WaitUntilValueChangedUnityObjectPromise<T, U> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitUntilValueChangedUnityObjectPromise()
|
static WaitUntilValueChangedUnityObjectPromise()
|
||||||
{
|
{
|
||||||
|
@ -683,8 +347,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
|
@ -692,7 +354,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -710,16 +372,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitUntilValueChangedUnityObjectPromise<T, U>)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -736,16 +388,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -804,8 +449,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -814,8 +457,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
static TaskPool<WaitUntilValueChangedStandardObjectPromise<T, U>> pool;
|
static TaskPool<WaitUntilValueChangedStandardObjectPromise<T, U>> pool;
|
||||||
WaitUntilValueChangedStandardObjectPromise<T, U> nextNode;
|
public WaitUntilValueChangedStandardObjectPromise<T, U> NextNode { get; set; }
|
||||||
public ref WaitUntilValueChangedStandardObjectPromise<T, U> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitUntilValueChangedStandardObjectPromise()
|
static WaitUntilValueChangedStandardObjectPromise()
|
||||||
{
|
{
|
||||||
|
@ -827,8 +469,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
|
@ -836,7 +476,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -853,16 +493,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (WaitUntilValueChangedStandardObjectPromise<T, U>)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -879,16 +509,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -947,8 +570,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,183 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public partial struct UniTask
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<WhenEachResult<T>> WhenEach<T>(IEnumerable<UniTask<T>> tasks)
|
|
||||||
{
|
|
||||||
return new WhenEachEnumerable<T>(tasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<WhenEachResult<T>> WhenEach<T>(params UniTask<T>[] tasks)
|
|
||||||
{
|
|
||||||
return new WhenEachEnumerable<T>(tasks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly struct WhenEachResult<T>
|
|
||||||
{
|
|
||||||
public T Result { get; }
|
|
||||||
public Exception Exception { get; }
|
|
||||||
|
|
||||||
//[MemberNotNullWhen(false, nameof(Exception))]
|
|
||||||
public bool IsCompletedSuccessfully => Exception == null;
|
|
||||||
|
|
||||||
//[MemberNotNullWhen(true, nameof(Exception))]
|
|
||||||
public bool IsFaulted => Exception != null;
|
|
||||||
|
|
||||||
public WhenEachResult(T result)
|
|
||||||
{
|
|
||||||
this.Result = result;
|
|
||||||
this.Exception = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WhenEachResult(Exception exception)
|
|
||||||
{
|
|
||||||
if (exception == null) throw new ArgumentNullException(nameof(exception));
|
|
||||||
this.Result = default;
|
|
||||||
this.Exception = exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TryThrow()
|
|
||||||
{
|
|
||||||
if (IsFaulted)
|
|
||||||
{
|
|
||||||
ExceptionDispatchInfo.Capture(Exception).Throw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetResult()
|
|
||||||
{
|
|
||||||
if (IsFaulted)
|
|
||||||
{
|
|
||||||
ExceptionDispatchInfo.Capture(Exception).Throw();
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (IsCompletedSuccessfully)
|
|
||||||
{
|
|
||||||
return Result?.ToString() ?? "";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $"Exception{{{Exception.Message}}}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum WhenEachState : byte
|
|
||||||
{
|
|
||||||
NotRunning,
|
|
||||||
Running,
|
|
||||||
Completed
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class WhenEachEnumerable<T> : IUniTaskAsyncEnumerable<WhenEachResult<T>>
|
|
||||||
{
|
|
||||||
IEnumerable<UniTask<T>> source;
|
|
||||||
|
|
||||||
public WhenEachEnumerable(IEnumerable<UniTask<T>> source)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<WhenEachResult<T>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new Enumerator(source, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Enumerator : IUniTaskAsyncEnumerator<WhenEachResult<T>>
|
|
||||||
{
|
|
||||||
readonly IEnumerable<UniTask<T>> source;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
|
|
||||||
Channel<WhenEachResult<T>> channel;
|
|
||||||
IUniTaskAsyncEnumerator<WhenEachResult<T>> channelEnumerator;
|
|
||||||
int completeCount;
|
|
||||||
WhenEachState state;
|
|
||||||
|
|
||||||
public Enumerator(IEnumerable<UniTask<T>> source, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WhenEachResult<T> Current => channelEnumerator.Current;
|
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
if (state == WhenEachState.NotRunning)
|
|
||||||
{
|
|
||||||
state = WhenEachState.Running;
|
|
||||||
channel = Channel.CreateSingleConsumerUnbounded<WhenEachResult<T>>();
|
|
||||||
channelEnumerator = channel.Reader.ReadAllAsync().GetAsyncEnumerator(cancellationToken);
|
|
||||||
|
|
||||||
if (source is UniTask<T>[] array)
|
|
||||||
{
|
|
||||||
ConsumeAll(this, array, array.Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var rentArray = ArrayPoolUtil.Materialize(source))
|
|
||||||
{
|
|
||||||
ConsumeAll(this, rentArray.Array, rentArray.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return channelEnumerator.MoveNextAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ConsumeAll(Enumerator self, UniTask<T>[] array, int length)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
RunWhenEachTask(self, array[i], length).Forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTaskVoid RunWhenEachTask(Enumerator self, UniTask<T> task, int length)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = await task;
|
|
||||||
self.channel.Writer.TryWrite(new WhenEachResult<T>(result));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
self.channel.Writer.TryWrite(new WhenEachResult<T>(ex));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Interlocked.Increment(ref self.completeCount) == length)
|
|
||||||
{
|
|
||||||
self.state = WhenEachState.Completed;
|
|
||||||
self.channel.Writer.TryComplete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
if (channelEnumerator != null)
|
|
||||||
{
|
|
||||||
await channelEnumerator.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state != WhenEachState.Completed)
|
|
||||||
{
|
|
||||||
state = WhenEachState.Completed;
|
|
||||||
channel.Writer.TryComplete(new OperationCanceledException());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "UniTask",
|
"name": "UniTask",
|
||||||
"rootNamespace": "",
|
"references": [
|
||||||
"references": [],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
|
@ -14,31 +14,6 @@
|
||||||
"name": "com.unity.modules.assetbundle",
|
"name": "com.unity.modules.assetbundle",
|
||||||
"expression": "",
|
"expression": "",
|
||||||
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.modules.physics",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_PHYSICS_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.modules.physics2d",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_PHYSICS2D_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.modules.particlesystem",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_PARTICLESYSTEM_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.ugui",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_UGUI_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.modules.unitywebrequest",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_WEBREQUEST_SUPPORT"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|
|
@ -1,10 +1,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
|
||||||
#pragma warning disable CS0436
|
#pragma warning disable CS0436
|
||||||
|
|
||||||
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
|
||||||
#define SUPPORT_VALUETASK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.CompilerServices;
|
using Cysharp.Threading.Tasks.CompilerServices;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -73,7 +69,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new UniTask<bool>(new IsCanceledSource(source), token);
|
return new UniTask<bool>(new IsCanceledSource(source), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SUPPORT_VALUETASK
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +78,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
||||||
|
@ -119,13 +115,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -431,7 +422,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +434,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return self.AsUniTask();
|
return self.AsUniTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SUPPORT_VALUETASK
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
||||||
{
|
{
|
||||||
|
@ -453,7 +443,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
||||||
|
|
|
@ -137,9 +137,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -184,9 +184,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -319,8 +319,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode<AutoResetUniTaskCompletionSource>, IPromise
|
public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode<AutoResetUniTaskCompletionSource>, IPromise
|
||||||
{
|
{
|
||||||
static TaskPool<AutoResetUniTaskCompletionSource> pool;
|
static TaskPool<AutoResetUniTaskCompletionSource> pool;
|
||||||
AutoResetUniTaskCompletionSource nextNode;
|
public AutoResetUniTaskCompletionSource NextNode { get; set; }
|
||||||
public ref AutoResetUniTaskCompletionSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AutoResetUniTaskCompletionSource()
|
static AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -328,7 +327,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
short version;
|
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -341,7 +339,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource();
|
result = new AutoResetUniTaskCompletionSource();
|
||||||
}
|
}
|
||||||
result.version = result.core.Version;
|
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -385,19 +382,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult()
|
public bool TrySetResult()
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetResult(AsyncUnit.Default);
|
return core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
return core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetException(exception);
|
return core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -411,6 +408,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -443,8 +441,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<AutoResetUniTaskCompletionSource<T>>, IPromise<T>
|
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<AutoResetUniTaskCompletionSource<T>>, IPromise<T>
|
||||||
{
|
{
|
||||||
static TaskPool<AutoResetUniTaskCompletionSource<T>> pool;
|
static TaskPool<AutoResetUniTaskCompletionSource<T>> pool;
|
||||||
AutoResetUniTaskCompletionSource<T> nextNode;
|
public AutoResetUniTaskCompletionSource<T> NextNode { get; set; }
|
||||||
public ref AutoResetUniTaskCompletionSource<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AutoResetUniTaskCompletionSource()
|
static AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -452,7 +449,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
short version;
|
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -465,7 +461,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource<T>();
|
result = new AutoResetUniTaskCompletionSource<T>();
|
||||||
}
|
}
|
||||||
result.version = result.core.Version;
|
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -509,19 +504,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult(T result)
|
public bool TrySetResult(T result)
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetResult(result);
|
return core.TrySetResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
return core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return version == core.Version && core.TrySetException(exception);
|
return core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
p.TrySetException(x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult(x.Result);
|
p.TrySetResult(x.Result);
|
||||||
|
@ -58,7 +58,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
p.TrySetException(x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult();
|
p.TrySetResult();
|
||||||
|
@ -192,7 +192,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignore task result when cancel raised first.
|
/// Ignore task result when cancel raised first.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask AttachExternalCancellation(this UniTask task, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this UniTask task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!cancellationToken.CanBeCanceled)
|
if (!cancellationToken.CanBeCanceled)
|
||||||
{
|
{
|
||||||
|
@ -201,7 +201,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
task.Forget();
|
|
||||||
return UniTask.FromCanceled(cancellationToken);
|
return UniTask.FromCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,13 +209,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(new AttachExternalCancellationSource(task, cancellationToken), 0);
|
return new UniTask(new WithCancellationSource(task, cancellationToken), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignore task result when cancel raised first.
|
/// Ignore task result when cancel raised first.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask<T> AttachExternalCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
public static UniTask<T> WithCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!cancellationToken.CanBeCanceled)
|
if (!cancellationToken.CanBeCanceled)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +224,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
task.Forget();
|
|
||||||
return UniTask.FromCanceled<T>(cancellationToken);
|
return UniTask.FromCanceled<T>(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,10 +232,10 @@ namespace Cysharp.Threading.Tasks
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask<T>(new AttachExternalCancellationSource<T>(task, cancellationToken), 0);
|
return new UniTask<T>(new WithCancellationSource<T>(task, cancellationToken), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AttachExternalCancellationSource : IUniTaskSource
|
sealed class WithCancellationSource : IUniTaskSource
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||||
|
|
||||||
|
@ -245,7 +243,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
CancellationTokenRegistration tokenRegistration;
|
CancellationTokenRegistration tokenRegistration;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
public AttachExternalCancellationSource(UniTask task, CancellationToken cancellationToken)
|
public WithCancellationSource(UniTask task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||||
|
@ -271,7 +269,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
static void CancellationCallback(object state)
|
||||||
{
|
{
|
||||||
var self = (AttachExternalCancellationSource)state;
|
var self = (WithCancellationSource)state;
|
||||||
self.core.TrySetCanceled(self.cancellationToken);
|
self.core.TrySetCanceled(self.cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +294,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AttachExternalCancellationSource<T> : IUniTaskSource<T>
|
sealed class WithCancellationSource<T> : IUniTaskSource<T>
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||||
|
|
||||||
|
@ -304,7 +302,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
CancellationTokenRegistration tokenRegistration;
|
CancellationTokenRegistration tokenRegistration;
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
public AttachExternalCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
public WithCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||||
|
@ -329,7 +327,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
static void CancellationCallback(object state)
|
||||||
{
|
{
|
||||||
var self = (AttachExternalCancellationSource<T>)state;
|
var self = (WithCancellationSource<T>)state;
|
||||||
self.core.TrySetCanceled(self.cancellationToken);
|
self.core.TrySetCanceled(self.cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +454,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCanceled).
|
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCacneled).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||||
{
|
{
|
||||||
|
@ -563,8 +561,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(state =>
|
awaiter.SourceOnCompleted(state =>
|
||||||
{
|
{
|
||||||
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
||||||
|
@ -580,7 +577,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}, StateTuple.Create(awaiter));
|
}, 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)
|
||||||
{
|
{
|
||||||
|
@ -633,8 +629,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(state =>
|
awaiter.SourceOnCompleted(state =>
|
||||||
{
|
{
|
||||||
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
||||||
|
@ -650,7 +645,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}, StateTuple.Create(awaiter));
|
}, 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)
|
||||||
{
|
{
|
||||||
|
@ -738,51 +732,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
return await await task;
|
return await await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask Unwrap(this UniTask<UniTask> task)
|
public static async UniTask Unwrap<T>(this UniTask<UniTask> task)
|
||||||
{
|
{
|
||||||
await await task;
|
await await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
|
|
||||||
{
|
|
||||||
return await await 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return await await 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -58,7 +58,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
task.GetAwaiter().GetResult();
|
|
||||||
return new ReturnObservable<AsyncUnit>(AsyncUnit.Default);
|
return new ReturnObservable<AsyncUnit>(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -74,19 +73,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
static async UniTaskVoid Fire<T>(AsyncSubject<T> subject, UniTask<T> task)
|
static async UniTaskVoid Fire<T>(AsyncSubject<T> subject, UniTask<T> task)
|
||||||
{
|
{
|
||||||
T value;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
value = await task;
|
var value = await task;
|
||||||
|
subject.OnNext(value);
|
||||||
|
subject.OnCompleted();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
subject.OnError(ex);
|
subject.OnError(ex);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subject.OnNext(value);
|
|
||||||
subject.OnCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async UniTaskVoid Fire(AsyncSubject<AsyncUnit> subject, UniTask task)
|
static async UniTaskVoid Fire(AsyncSubject<AsyncUnit> subject, UniTask task)
|
||||||
|
@ -94,15 +90,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await task;
|
await task;
|
||||||
|
subject.OnNext(AsyncUnit.Default);
|
||||||
|
subject.OnCompleted();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
subject.OnError(ex);
|
subject.OnError(ex);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subject.OnNext(AsyncUnit.Default);
|
|
||||||
subject.OnCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToUniTaskObserver<T> : IObserver<T>
|
class ToUniTaskObserver<T> : IObserver<T>
|
||||||
|
@ -133,7 +127,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
var self = (ToUniTaskObserver<T>)state;
|
var self = (ToUniTaskObserver<T>)state;
|
||||||
self.disposable.Dispose();
|
self.disposable.Dispose();
|
||||||
self.promise.TrySetCanceled(self.cancellationToken);
|
self.promise.TrySetCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnNext(T value)
|
public void OnNext(T value)
|
||||||
|
@ -203,7 +197,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
var self = (FirstValueToUniTaskObserver<T>)state;
|
var self = (FirstValueToUniTaskObserver<T>)state;
|
||||||
self.disposable.Dispose();
|
self.disposable.Dispose();
|
||||||
self.promise.TrySetCanceled(self.cancellationToken);
|
self.promise.TrySetCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnNext(T value)
|
public void OnNext(T value)
|
||||||
|
|
|
@ -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(false);
|
static SpinLock gate = new SpinLock();
|
||||||
static bool dequing = false;
|
static bool dequing = false;
|
||||||
|
|
||||||
static int actionListCount = 0;
|
static int actionListCount = 0;
|
||||||
|
|
|
@ -21,20 +21,18 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||||
|
if (asyncOperation.isDone) return UniTask.FromResult<UnityEngine.Object[]>(asyncOperation.allAssets);
|
||||||
|
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
|
||||||
return AwaitForAllAssets(asyncOperation, progress: null, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
||||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -48,11 +46,6 @@ 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()
|
||||||
|
@ -86,11 +79,132 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AssetBundleRequestAllAssetsWithCancellationSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AssetBundleRequestAllAssetsWithCancellationSource> pool;
|
||||||
|
public AssetBundleRequestAllAssetsWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AssetBundleRequestAllAssetsWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestAllAssetsWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperation> continuationAction;
|
||||||
|
AssetBundleRequest asyncOperation;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||||
|
|
||||||
|
AssetBundleRequestAllAssetsWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AssetBundleRequestAllAssetsWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.TrySetResult(asyncOperation.allAssets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object[] GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
||||||
AssetBundleRequestAllAssetsConfiguredSource nextNode;
|
public AssetBundleRequestAllAssetsConfiguredSource NextNode { get; set; }
|
||||||
public ref AssetBundleRequestAllAssetsConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AssetBundleRequestAllAssetsConfiguredSource()
|
static AssetBundleRequestAllAssetsConfiguredSource()
|
||||||
{
|
{
|
||||||
|
@ -100,20 +214,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
AssetBundleRequest asyncOperation;
|
AssetBundleRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||||
|
|
||||||
Action<AsyncOperation> continuationAction;
|
|
||||||
|
|
||||||
AssetBundleRequestAllAssetsConfiguredSource()
|
AssetBundleRequestAllAssetsConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -128,19 +237,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (AssetBundleRequestAllAssetsConfiguredSource)state;
|
|
||||||
source.core.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -157,16 +253,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -191,12 +280,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
// Already completed
|
|
||||||
if (completed || asyncOperation == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -224,28 +307,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.allAssets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,22 +20,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
{
|
||||||
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
||||||
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, cancelImmediately, out var token), token);
|
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
||||||
AsyncGPUReadbackRequestAwaiterConfiguredSource nextNode;
|
public AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode { get; set; }
|
||||||
public ref AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
static AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||||
{
|
{
|
||||||
|
@ -44,15 +38,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
AsyncGPUReadbackRequest asyncOperation;
|
AsyncGPUReadbackRequest asyncOperation;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
||||||
|
|
||||||
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -66,16 +60,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var promise = (AsyncGPUReadbackRequestAwaiterConfiguredSource)state;
|
|
||||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -92,16 +76,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -153,8 +130,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,386 +0,0 @@
|
||||||
// AsyncInstantiateOperation was added since Unity 2022.3.20 / 2023.3.0b7
|
|
||||||
#if UNITY_2022_3 && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10 || UNITY_2022_3_11 || UNITY_2022_3_12 || UNITY_2022_3_13 || UNITY_2022_3_14 || UNITY_2022_3_15 || UNITY_2022_3_16 || UNITY_2022_3_17 || UNITY_2022_3_18 || UNITY_2022_3_19)
|
|
||||||
#define UNITY_2022_SUPPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if UNITY_2022_SUPPORT || UNITY_2023_3_OR_NEWER
|
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static class AsyncInstantiateOperationExtensions
|
|
||||||
{
|
|
||||||
// AsyncInstantiateOperation<T> has GetAwaiter so no need to impl
|
|
||||||
// public static UniTask<T[]>.Awaiter GetAwaiter<T>(this AsyncInstantiateOperation<T> operation) where T : Object
|
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> WithCancellation<T>(this AsyncInstantiateOperation asyncOperation, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> WithCancellation<T>(this AsyncInstantiateOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> ToUniTask(this AsyncInstantiateOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.Result);
|
|
||||||
return new UniTask<UnityEngine.Object[]>(AsyncInstantiateOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<T[]> WithCancellation<T>(this AsyncInstantiateOperation<T> asyncOperation, CancellationToken cancellationToken)
|
|
||||||
where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<T[]> WithCancellation<T>(this AsyncInstantiateOperation<T> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
|
||||||
where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<T[]> ToUniTask<T>(this AsyncInstantiateOperation<T> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T[]>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.Result);
|
|
||||||
return new UniTask<T[]>(AsyncInstantiateOperationConfiguredSource<T>.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncInstantiateOperationConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AsyncInstantiateOperationConfiguredSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AsyncInstantiateOperationConfiguredSource> pool;
|
|
||||||
AsyncInstantiateOperationConfiguredSource nextNode;
|
|
||||||
public ref AsyncInstantiateOperationConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncInstantiateOperationConfiguredSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncInstantiateOperationConfiguredSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncInstantiateOperation asyncOperation;
|
|
||||||
IProgress<float> progress;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
|
||||||
|
|
||||||
Action<AsyncOperation> continuationAction;
|
|
||||||
|
|
||||||
AsyncInstantiateOperationConfiguredSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AsyncInstantiateOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AsyncInstantiateOperationConfiguredSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.progress = progress;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (AsyncInstantiateOperationConfiguredSource)state;
|
|
||||||
source.core.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityEngine.Object[] GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
// Already completed
|
|
||||||
if (completed || asyncOperation == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress != null)
|
|
||||||
{
|
|
||||||
progress.Report(asyncOperation.progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asyncOperation.isDone)
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.Result);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
asyncOperation = default;
|
|
||||||
progress = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncInstantiateOperationConfiguredSource<T> : IUniTaskSource<T[]>, IPlayerLoopItem, ITaskPoolNode<AsyncInstantiateOperationConfiguredSource<T>>
|
|
||||||
where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
static TaskPool<AsyncInstantiateOperationConfiguredSource<T>> pool;
|
|
||||||
AsyncInstantiateOperationConfiguredSource<T> nextNode;
|
|
||||||
public ref AsyncInstantiateOperationConfiguredSource<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncInstantiateOperationConfiguredSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncInstantiateOperationConfiguredSource<T>), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncInstantiateOperation<T> asyncOperation;
|
|
||||||
IProgress<float> progress;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T[]> core;
|
|
||||||
|
|
||||||
Action<AsyncOperation> continuationAction;
|
|
||||||
|
|
||||||
AsyncInstantiateOperationConfiguredSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<T[]> Create(AsyncInstantiateOperation<T> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<T[]>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AsyncInstantiateOperationConfiguredSource<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.progress = progress;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (AsyncInstantiateOperationConfiguredSource<T>)state;
|
|
||||||
source.core.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T[] GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
// Already completed
|
|
||||||
if (completed || asyncOperation == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress != null)
|
|
||||||
{
|
|
||||||
progress.Report(asyncOperation.progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asyncOperation.isDone)
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.Result);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
asyncOperation = default;
|
|
||||||
progress = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 8321f4244edfdcd4798b4fcc92a736c9
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -4,7 +4,6 @@
|
||||||
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
|
||||||
{
|
{
|
||||||
|
@ -86,7 +85,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (jobHandle.IsCompleted | PlayerLoopHelper.IsEditorApplicationQuitting)
|
if (jobHandle.IsCompleted)
|
||||||
{
|
{
|
||||||
jobHandle.Complete();
|
jobHandle.Complete();
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,12 +11,11 @@
|
||||||
("ResourceRequest", "UnityEngine.Object", "asset"),
|
("ResourceRequest", "UnityEngine.Object", "asset"),
|
||||||
("AssetBundleRequest", "UnityEngine.Object", "asset"), // allAssets?
|
("AssetBundleRequest", "UnityEngine.Object", "asset"), // allAssets?
|
||||||
("AssetBundleCreateRequest", "AssetBundle", "assetBundle"),
|
("AssetBundleCreateRequest", "AssetBundle", "assetBundle"),
|
||||||
("UnityWebRequestAsyncOperation", "UnityWebRequest", "webRequest") // -> #if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
("UnityWebRequestAsyncOperation", "UnityWebRequest", "webRequest") // -> #if ENABLE_UNITYWEBREQUEST
|
||||||
};
|
};
|
||||||
|
|
||||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||||
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsAsyncOperationBase = x => x.typeName == "AsyncOperation";
|
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
||||||
|
@ -28,7 +27,7 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
#if ENABLE_UNITYWEBREQUEST
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -38,36 +37,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
<# foreach(var t in types) { #>
|
<# foreach(var t in types) { #>
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
#if ENABLE_UNITYWEBREQUEST
|
||||||
<# } else if(IsAssetBundleModule(t)) { #>
|
<# } else if(IsAssetBundleModule(t)) { #>
|
||||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||||
<# } #>
|
<# } #>
|
||||||
#region <#= t.typeName #>
|
#region <#= t.typeName #>
|
||||||
|
|
||||||
<# if (IsAsyncOperationBase(t)) { #>
|
|
||||||
#if !UNITY_2023_1_OR_NEWER
|
|
||||||
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
|
||||||
<# } #>
|
|
||||||
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
return new <#= t.typeName #>Awaiter(asyncOperation);
|
return new <#= t.typeName #>Awaiter(asyncOperation);
|
||||||
}
|
}
|
||||||
<# if (IsAsyncOperationBase(t)) { #>
|
|
||||||
#endif
|
|
||||||
<# } #>
|
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
|
||||||
{
|
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||||
|
@ -83,7 +65,26 @@ namespace Cysharp.Threading.Tasks
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
<# } #>
|
<# } #>
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>WithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
if (asyncOperation.isDone)
|
||||||
|
{
|
||||||
|
if (asyncOperation.webRequest.IsError())
|
||||||
|
{
|
||||||
|
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
return UniTask.FromResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
|
<# } #>
|
||||||
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
||||||
|
@ -150,11 +151,153 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class <#= t.typeName #>WithCancellationSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>WithCancellationSource>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
var result = asyncOperation.webRequest;
|
||||||
|
if (result.IsError())
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(result);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(IsUnityWebRequest(t)) { #>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
||||||
<#= t.typeName #>ConfiguredSource nextNode;
|
public <#= t.typeName #>ConfiguredSource NextNode { get; set; }
|
||||||
public ref <#= t.typeName #>ConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static <#= t.typeName #>ConfiguredSource()
|
static <#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
|
@ -164,20 +307,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
<#= t.typeName #> asyncOperation;
|
<#= t.typeName #> asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
||||||
|
|
||||||
Action<AsyncOperation> continuationAction;
|
|
||||||
|
|
||||||
<#= t.typeName #>ConfiguredSource()
|
<#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -192,22 +330,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
|
||||||
{
|
|
||||||
var source = (<#= t.typeName #>ConfiguredSource)state;
|
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
|
||||||
source.asyncOperation.webRequest.Abort();
|
|
||||||
<# } #>
|
|
||||||
source.core.TrySetCanceled(source.cancellationToken);
|
|
||||||
}, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -228,13 +350,10 @@ namespace Cysharp.Threading.Tasks
|
||||||
<# } #>
|
<# } #>
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -260,12 +379,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
// Already completed
|
|
||||||
if (completed || asyncOperation == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
@ -304,42 +417,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancelImmediately = default;
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
|
||||||
else if (asyncOperation.webRequest.IsError())
|
|
||||||
{
|
|
||||||
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(asyncOperation.webRequest);
|
|
||||||
}
|
|
||||||
<# } else { #>
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
|
||||||
}
|
|
||||||
<# } #>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#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
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -339,7 +339,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
void InvokeCore(string item1, int item2, int item3)
|
void InvokeCore(string item1, int item2, int item3)
|
||||||
{
|
{
|
||||||
Invoke((item1, item2, item3));
|
innerEvent.Invoke(item1, item2, item3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -364,7 +364,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public AsyncUnityEventHandler(UnityEvent unityEvent, CancellationToken cancellationToken, bool callOnce)
|
public AsyncUnityEventHandler(UnityEvent unityEvent, CancellationToken cancellationToken, bool callOnce)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
|
@ -373,6 +372,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
this.action = Invoke;
|
this.action = Invoke;
|
||||||
this.unityEvent = unityEvent;
|
this.unityEvent = unityEvent;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
this.callOnce = callOnce;
|
this.callOnce = callOnce;
|
||||||
|
|
||||||
unityEvent.AddListener(action);
|
unityEvent.AddListener(action);
|
||||||
|
@ -388,10 +388,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
public UniTask OnInvokeAsync()
|
public UniTask OnInvokeAsync()
|
||||||
{
|
{
|
||||||
core.Reset();
|
core.Reset();
|
||||||
if (isDisposed)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(this.cancellationToken);
|
|
||||||
}
|
|
||||||
return new UniTask(this, core.Version);
|
return new UniTask(this, core.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +470,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public AsyncUnityEventHandler(UnityEvent<T> unityEvent, CancellationToken cancellationToken, bool callOnce)
|
public AsyncUnityEventHandler(UnityEvent<T> unityEvent, CancellationToken cancellationToken, bool callOnce)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
|
@ -483,6 +478,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
this.action = Invoke;
|
this.action = Invoke;
|
||||||
this.unityEvent = unityEvent;
|
this.unityEvent = unityEvent;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
this.callOnce = callOnce;
|
this.callOnce = callOnce;
|
||||||
|
|
||||||
unityEvent.AddListener(action);
|
unityEvent.AddListener(action);
|
||||||
|
@ -498,10 +494,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
public UniTask<T> OnInvokeAsync()
|
public UniTask<T> OnInvokeAsync()
|
||||||
{
|
{
|
||||||
core.Reset();
|
core.Reset();
|
||||||
if (isDisposed)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(this.cancellationToken);
|
|
||||||
}
|
|
||||||
return new UniTask<T>(this, core.Version);
|
return new UniTask<T>(this, core.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +665,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
if (cancellationToken2.CanBeCanceled)
|
if (cancellationToken2.CanBeCanceled)
|
||||||
{
|
{
|
||||||
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,28 +680,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
static void OnCanceled1(object state)
|
static void OnCanceled1(object state)
|
||||||
{
|
{
|
||||||
var self = (UnityEventHandlerAsyncEnumerator)state;
|
var self = (UnityEventHandlerAsyncEnumerator)state;
|
||||||
try
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.DisposeAsync().Forget();
|
self.DisposeAsync().Forget();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void OnCanceled2(object state)
|
static void OnCanceled2(object state)
|
||||||
{
|
{
|
||||||
var self = (UnityEventHandlerAsyncEnumerator)state;
|
var self = (UnityEventHandlerAsyncEnumerator)state;
|
||||||
try
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken2);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.DisposeAsync().Forget();
|
self.DisposeAsync().Forget();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
|
@ -720,8 +698,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
registration1.Dispose();
|
registration1.Dispose();
|
||||||
registration2.Dispose();
|
registration2.Dispose();
|
||||||
unityEvent.RemoveListener(unityAction);
|
unityEvent.RemoveListener(unityAction);
|
||||||
|
|
||||||
completionSource.TrySetCanceled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
|
@ -793,7 +769,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
if (cancellationToken2.CanBeCanceled)
|
if (cancellationToken2.CanBeCanceled)
|
||||||
{
|
{
|
||||||
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,28 +785,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
static void OnCanceled1(object state)
|
static void OnCanceled1(object state)
|
||||||
{
|
{
|
||||||
var self = (UnityEventHandlerAsyncEnumerator)state;
|
var self = (UnityEventHandlerAsyncEnumerator)state;
|
||||||
try
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.DisposeAsync().Forget();
|
self.DisposeAsync().Forget();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void OnCanceled2(object state)
|
static void OnCanceled2(object state)
|
||||||
{
|
{
|
||||||
var self = (UnityEventHandlerAsyncEnumerator)state;
|
var self = (UnityEventHandlerAsyncEnumerator)state;
|
||||||
try
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken2);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.DisposeAsync().Forget();
|
self.DisposeAsync().Forget();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
|
@ -845,8 +807,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
disp.Dispose();
|
disp.Dispose();
|
||||||
}
|
}
|
||||||
unityEvent.RemoveListener(unityAction);
|
unityEvent.RemoveListener(unityAction);
|
||||||
|
|
||||||
completionSource.TrySetCanceled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
|
@ -854,5 +814,3 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue