mirror of https://github.com/Cysharp/UniTask
Compare commits
No commits in common. "master" and "2.0.15" 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,71 @@ 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]' }}
|
|
||||||
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
|
# create unity activation file and store to artifacts.
|
||||||
|
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logFile -createManualActivationFile || exit 0
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
export-env: false
|
name: Unity_v${{ matrix.unity }}.alf
|
||||||
|
path: ./Unity_v${{ matrix.unity }}.alf
|
||||||
|
# activate Unity from manual license file(ulf)
|
||||||
|
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
||||||
env:
|
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
|
# Store artifacts.
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend IL2CPP /BuildTarget StandaloneLinux64
|
- uses: actions/upload-artifact@v2
|
||||||
- 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:
|
with:
|
||||||
projectPath: src/UniTask
|
name: UniTask.unitypackage.zip
|
||||||
unityVersion: ${{ matrix.unity }}
|
path: ./src/UniTask/*.unitypackage
|
||||||
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.
|
|
||||||
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
|
||||||
if: ${{ startsWith(matrix.unity, '2021') }} # only execute 2021
|
|
||||||
with:
|
|
||||||
name: UniTask.unitypackage-${{ matrix.unity }}.zip
|
|
||||||
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
|
# Store artifacts.
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
directory: src/UniTask
|
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
|
||||||
# Store artifacts.
|
|
||||||
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
|
||||||
with:
|
|
||||||
name: UniTask.${{ inputs.tag }}.unitypackage
|
|
||||||
path: ./src/UniTask/UniTask.${{ inputs.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
|
||||||
with:
|
env:
|
||||||
commit-id: ${{ needs.update-packagejson.outputs.sha }}
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
dry-run: ${{ inputs.dry-run }}
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
tag: ${{ inputs.tag }}
|
NUGET_XMLDOC_MODE: skip
|
||||||
nuget-push: true
|
steps:
|
||||||
release-upload: true
|
# setup dotnet for nuget push
|
||||||
release-asset-path: ./UniTask.${{ inputs.tag }}.unitypackage/UniTask.${{ inputs.tag }}.unitypackage
|
- uses: actions/setup-dotnet@v1
|
||||||
secrets: inherit
|
with:
|
||||||
|
dotnet-version: 3.1.101
|
||||||
|
# set release tag(*.*.*) to env.GIT_TAG
|
||||||
|
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
||||||
|
|
||||||
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:
|
||||||
with:
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
branch: ${{ needs.update-packagejson.outputs.branch-name }}
|
with:
|
||||||
|
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
|
||||||
with:
|
steps:
|
||||||
TOC_TITLE: "## Table of Contents"
|
- uses: technote-space/toc-generator@v2.4.0
|
||||||
secrets: inherit
|
with:
|
||||||
|
TOC_TITLE: "## Table of Contents"
|
|
@ -80,7 +80,7 @@ _ReSharper*
|
||||||
*.ncrunch*
|
*.ncrunch*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
|
|
||||||
# Installshield output folder
|
# Installshield output folder
|
||||||
[Ee]xpress
|
[Ee]xpress
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
# DocProject is a documentation generator add-in
|
||||||
|
@ -130,15 +130,78 @@ 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
|
||||||
|
|
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,101 +0,0 @@
|
||||||
#if !NETSTANDARD2_0
|
|
||||||
|
|
||||||
#pragma warning disable 0649
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading.Tasks.Sources;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static class AsyncEnumerableExtensions
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<T> AsUniTaskAsyncEnumerable<T>(this IAsyncEnumerable<T> source)
|
|
||||||
{
|
|
||||||
return new AsyncEnumerableToUniTaskAsyncEnumerable<T>(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IUniTaskAsyncEnumerable<T> source)
|
|
||||||
{
|
|
||||||
return new UniTaskAsyncEnumerableToAsyncEnumerable<T>(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncEnumerableToUniTaskAsyncEnumerable<T> : IUniTaskAsyncEnumerable<T>
|
|
||||||
{
|
|
||||||
readonly IAsyncEnumerable<T> source;
|
|
||||||
|
|
||||||
public AsyncEnumerableToUniTaskAsyncEnumerable(IAsyncEnumerable<T> source)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Enumerator : IUniTaskAsyncEnumerator<T>
|
|
||||||
{
|
|
||||||
readonly IAsyncEnumerator<T> enumerator;
|
|
||||||
|
|
||||||
public Enumerator(IAsyncEnumerator<T> enumerator)
|
|
||||||
{
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Current => enumerator.Current;
|
|
||||||
|
|
||||||
public async UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
await enumerator.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
return await enumerator.MoveNextAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class UniTaskAsyncEnumerableToAsyncEnumerable<T> : IAsyncEnumerable<T>
|
|
||||||
{
|
|
||||||
readonly IUniTaskAsyncEnumerable<T> source;
|
|
||||||
|
|
||||||
public UniTaskAsyncEnumerableToAsyncEnumerable(IUniTaskAsyncEnumerable<T> source)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Enumerator : IAsyncEnumerator<T>
|
|
||||||
{
|
|
||||||
readonly IUniTaskAsyncEnumerator<T> enumerator;
|
|
||||||
|
|
||||||
public Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
|
|
||||||
{
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Current => enumerator.Current;
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
return enumerator.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
return enumerator.MoveNextAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -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,24 +19,25 @@ 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;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> AsUniTask<T>(this ValueTask<T> task)
|
public static UniTask<T> AsUniTask<T>(this ValueTask<T> task, bool useCurrentSynchronizationContext = true)
|
||||||
{
|
{
|
||||||
return await task;
|
// NOTE: get _obj and _token directly for low overhead conversion but not yet implemented.
|
||||||
|
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask AsUniTask(this ValueTask task)
|
public static UniTask AsUniTask(this ValueTask task, bool useCurrentSynchronizationContext = true)
|
||||||
{
|
{
|
||||||
await task;
|
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
#if NETSTANDARD2_0
|
||||||
|
|
||||||
class UniTaskValueTaskSource : IValueTaskSource
|
class UniTaskValueTaskSource : IValueTaskSource
|
||||||
{
|
{
|
||||||
|
@ -101,4 +96,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,43 +1,58 @@
|
||||||
<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>
|
||||||
<PackageVersion>$(Version)</PackageVersion>
|
<PackageVersion>$(Version)</PackageVersion>
|
||||||
<Company>Cysharp</Company>
|
<Company>Cysharp</Company>
|
||||||
<Authors>Cysharp</Authors>
|
<Authors>Cysharp</Authors>
|
||||||
<Copyright>© Cysharp, Inc.</Copyright>
|
<Copyright>© Cysharp, Inc.</Copyright>
|
||||||
<PackageTags>task;async</PackageTags>
|
<PackageTags>task;async</PackageTags>
|
||||||
<Description>Provides an efficient async/await integration to Unity and .NET Core.</Description>
|
<Description>Provides an efficient async/await integration to Unity and .NET Core.</Description>
|
||||||
<PackageProjectUrl>https://github.com/Cysharp/UniTask</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Cysharp/UniTask</PackageProjectUrl>
|
||||||
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
|
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Icon.png</PackageIcon>
|
<PackageIcon>Icon.png</PackageIcon>
|
||||||
<SignAssembly>true</SignAssembly>
|
</PropertyGroup>
|
||||||
<AssemblyOriginatorKeyFile>opensource.snk</AssemblyOriginatorKeyFile>
|
|
||||||
<IsPackable>true</IsPackable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Icon.png" Pack="true" PackagePath="/" />
|
<None Include="Icon.png" Pack="true" PackagePath="/" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs" Exclude="
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Triggers\*.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Linq\UnityExtensions\*.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityEqualityComparer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\DiagnosticsExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\PlayerLoopRunner.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\ContinuationQueue.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\Internal\UnityWebRequestExtensions.cs;
 
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\TimeoutController.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopTimer.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Bridge.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.WaitUntil.cs;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.*;
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
" />
|
<Compile Include="..\UniTask\Assets\Plugins\UniTask\Runtime\**\*.cs"
|
||||||
<Compile Remove="..\UniTask\Assets\Plugins\UniTask\Runtime\_InternalVisibleTo.cs" />
|
Exclude="
|
||||||
</ItemGroup>
|
..\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\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.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.uGUI.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityAsyncExtensions.MonoBehaviour.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UnityBindingExtensions.cs;
|
||||||
|
" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
#pragma warning disable CS1998
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System;
|
using System;
|
||||||
|
@ -17,34 +15,509 @@ 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();
|
|
||||||
|
|
||||||
|
|
||||||
// OK.
|
|
||||||
await FooAsync(10, cts.Token);
|
|
||||||
|
|
||||||
// NG(Compiler Error)
|
|
||||||
// await FooAsync(10);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async UniTask FooAsync(int x, CancellationToken cancellationToken = default)
|
public override void Post(SendOrPostCallback d, object state)
|
||||||
{
|
{
|
||||||
await UniTask.Yield();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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.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 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
|
||||||
|
// await new AllocationCheck().ViaUniTaskVoid();
|
||||||
|
|
||||||
|
// AsyncTest().Forge
|
||||||
|
|
||||||
|
Console.WriteLine("A?");
|
||||||
|
var a = await new ZeroAllocAsyncAwaitInDotNetCore().NanikaAsync(1, 2);
|
||||||
|
Console.WriteLine("RET:" + a);
|
||||||
|
await WhereSelect();
|
||||||
|
|
||||||
|
SynchronizationContext.SetSynchronizationContext(new MySyncContext());
|
||||||
|
|
||||||
|
await Aaa();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//AsyncTest().Forget();
|
||||||
|
|
||||||
|
// AsyncTest().Forget();
|
||||||
|
|
||||||
|
ThreadPool.SetMinThreads(100, 100);
|
||||||
|
|
||||||
|
//List<UniTask<int>> list = new List<UniTask<int>>();
|
||||||
|
for (int i = 0; i < short.MaxValue; i++)
|
||||||
|
{
|
||||||
|
//// list.Add(AsyncTest());
|
||||||
|
await YieldCore();
|
||||||
|
}
|
||||||
|
//await UniTask.WhenAll(list);
|
||||||
|
|
||||||
|
//Console.WriteLine("TOGO");
|
||||||
|
|
||||||
|
//var a = await AsyncTest();
|
||||||
|
//var b = AsyncTest();
|
||||||
|
//var c = AsyncTest();
|
||||||
|
await YieldCore();
|
||||||
|
|
||||||
|
//await b;
|
||||||
|
//await c;
|
||||||
|
|
||||||
|
|
||||||
|
//foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPool.GetCacheSizeInfo())
|
||||||
|
//{
|
||||||
|
// Console.WriteLine(item);
|
||||||
|
//}
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTask YieldCore()
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Channels;
|
|
||||||
using Cysharp.Threading.Tasks.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class AsyncLazyTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task LazyLazy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => After());
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await a;
|
|
||||||
await b;
|
|
||||||
await c;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => AfterException());
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task LazyImmediate()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => UniTask.FromResult(1).AsUniTask());
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await a;
|
|
||||||
await b;
|
|
||||||
await c;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => UniTask.FromException(new TaskTestException()));
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTask AwaitAwait(UniTask t)
|
|
||||||
{
|
|
||||||
await t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async UniTask After()
|
|
||||||
{
|
|
||||||
await UniTask.Yield();
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
|
||||||
await UniTask.Yield();
|
|
||||||
await UniTask.Yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTask AfterException()
|
|
||||||
{
|
|
||||||
await UniTask.Yield();
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
|
||||||
await UniTask.Yield();
|
|
||||||
throw new TaskTestException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AsyncLazyTest2
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task LazyLazy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => After());
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
var a2 = await a;
|
|
||||||
var b2 = await b;
|
|
||||||
var c2 = await c;
|
|
||||||
(a2, b2, c2).Should().Be((10, 10, 10));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => AfterException());
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task LazyImmediate()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => UniTask.FromResult(1));
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
var a2 = await a;
|
|
||||||
var b2 = await b;
|
|
||||||
var c2 = await c;
|
|
||||||
(a2, b2, c2).Should().Be((1, 1, 1));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var l = UniTask.Lazy(() => UniTask.FromException<int>(new TaskTestException()));
|
|
||||||
var a = AwaitAwait(l.Task);
|
|
||||||
var b = AwaitAwait(l.Task);
|
|
||||||
var c = AwaitAwait(l.Task);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TaskTestException>(async () => await c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTask<int> AwaitAwait(UniTask<int> t)
|
|
||||||
{
|
|
||||||
return await t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async UniTask<int> After()
|
|
||||||
{
|
|
||||||
await UniTask.Yield();
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
|
||||||
await UniTask.Yield();
|
|
||||||
await UniTask.Yield();
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTask<int> AfterException()
|
|
||||||
{
|
|
||||||
await UniTask.Yield();
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
|
||||||
await UniTask.Yield();
|
|
||||||
throw new TaskTestException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 });
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,85 +112,6 @@ namespace NetCoreTests
|
||||||
state.Value.Should().Be(20);
|
state.Value.Should().Be(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task WaitAsyncTest()
|
|
||||||
{
|
|
||||||
var rp = new AsyncReactiveProperty<int>(128);
|
|
||||||
|
|
||||||
var f = await rp.FirstAsync();
|
|
||||||
f.Should().Be(128);
|
|
||||||
|
|
||||||
{
|
|
||||||
var t = rp.WaitAsync();
|
|
||||||
rp.Value = 99;
|
|
||||||
rp.Value = 100;
|
|
||||||
var v = await t;
|
|
||||||
|
|
||||||
v.Should().Be(99);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var t = rp.WaitAsync();
|
|
||||||
rp.Value = 99;
|
|
||||||
rp.Value = 100;
|
|
||||||
var v = await t;
|
|
||||||
|
|
||||||
v.Should().Be(99);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task WaitAsyncCancellationTest()
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var rp = new AsyncReactiveProperty<int>(128);
|
|
||||||
|
|
||||||
var t = rp.WaitAsync(cts.Token);
|
|
||||||
|
|
||||||
cts.Cancel();
|
|
||||||
|
|
||||||
rp.Value = 99;
|
|
||||||
rp.Value = 100;
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<OperationCanceledException>(async () => { await t; });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ReadOnlyWaitAsyncTest()
|
|
||||||
{
|
|
||||||
var rp = new AsyncReactiveProperty<int>(128);
|
|
||||||
var rrp = rp.ToReadOnlyAsyncReactiveProperty(CancellationToken.None);
|
|
||||||
|
|
||||||
var t = rrp.WaitAsync();
|
|
||||||
rp.Value = 99;
|
|
||||||
rp.Value = 100;
|
|
||||||
var v = await t;
|
|
||||||
|
|
||||||
v.Should().Be(99);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ReadOnlyWaitAsyncCancellationTest()
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var rp = new AsyncReactiveProperty<int>(128);
|
|
||||||
var rrp = rp.ToReadOnlyAsyncReactiveProperty(CancellationToken.None);
|
|
||||||
|
|
||||||
var t = rrp.WaitAsync(cts.Token);
|
|
||||||
|
|
||||||
cts.Cancel();
|
|
||||||
|
|
||||||
rp.Value = 99;
|
|
||||||
rp.Value = 100;
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<OperationCanceledException>(async () => { await t; });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -1,590 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Channels;
|
|
||||||
using Cysharp.Threading.Tasks.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class CompletionSourceTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task SetFirst()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
tcs.TrySetResult();
|
|
||||||
await tcs.Task; // ok.
|
|
||||||
await tcs.Task; // ok.
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SingleOnFirst()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetResult();
|
|
||||||
await a;
|
|
||||||
await tcs.Task; // ok.
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task MultiOne()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
tcs.TrySetResult();
|
|
||||||
await a;
|
|
||||||
await b;
|
|
||||||
await tcs.Task; // ok.
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task MultiTwo()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
tcs.TrySetResult();
|
|
||||||
await a;
|
|
||||||
await b;
|
|
||||||
await c;
|
|
||||||
await tcs.Task; // ok.
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await c);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource();
|
|
||||||
|
|
||||||
async UniTask Await()
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestException : Exception
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompletionSourceTest2
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task SetFirst()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
tcs.TrySetResult(10);
|
|
||||||
var a = await tcs.Task; // ok.
|
|
||||||
var b = await tcs.Task; // ok.
|
|
||||||
a.Should().Be(10);
|
|
||||||
b.Should().Be(10);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SingleOnFirst()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetResult(10);
|
|
||||||
var r1 = await a;
|
|
||||||
var r2 = await tcs.Task; // ok.
|
|
||||||
r1.Should().Be(10);
|
|
||||||
r2.Should().Be(10);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task MultiOne()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
tcs.TrySetResult(10);
|
|
||||||
var r1 = await a;
|
|
||||||
var r2 = await b;
|
|
||||||
var r3 = await tcs.Task; // ok.
|
|
||||||
(r1, r2, r3).Should().Be((10, 10, 10));
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task MultiTwo()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
tcs.TrySetResult(10);
|
|
||||||
var r1 = await a;
|
|
||||||
var r2 = await b;
|
|
||||||
var r3 = await c;
|
|
||||||
var r4 = await tcs.Task; // ok.
|
|
||||||
(r1, r2, r3, r4).Should().Be((10, 10, 10, 10));
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Succeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new TestException());
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await a);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await b);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await c);
|
|
||||||
await Assert.ThrowsAsync<TestException>(async () => await tcs.Task);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Faulted);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetException(new OperationCanceledException(cts.Token));
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<int>();
|
|
||||||
|
|
||||||
async UniTask<int> Await()
|
|
||||||
{
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = Await();
|
|
||||||
var b = Await();
|
|
||||||
var c = Await();
|
|
||||||
|
|
||||||
tcs.TrySetCanceled(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await a)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await b)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await c)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await tcs.Task)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
tcs.Task.Status.Should().Be(UniTaskStatus.Canceled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestException : Exception
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
#pragma warning disable CS1998
|
|
||||||
#pragma warning disable CS0162
|
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests.Linq
|
|
||||||
{
|
|
||||||
public class CreateTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task SyncCreation()
|
|
||||||
{
|
|
||||||
var from = 10;
|
|
||||||
var count = 100;
|
|
||||||
|
|
||||||
var xs = await UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
await writer.YieldAsync(from + i);
|
|
||||||
}
|
|
||||||
}).ToArrayAsync();
|
|
||||||
|
|
||||||
var ys = await Range(from, count).AsUniTaskAsyncEnumerable().ToArrayAsync();
|
|
||||||
|
|
||||||
xs.Should().Equal(ys);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SyncManually()
|
|
||||||
{
|
|
||||||
var list = new List<int>();
|
|
||||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
|
||||||
{
|
|
||||||
list.Add(100);
|
|
||||||
await writer.YieldAsync(10);
|
|
||||||
|
|
||||||
list.Add(200);
|
|
||||||
await writer.YieldAsync(20);
|
|
||||||
|
|
||||||
list.Add(300);
|
|
||||||
await writer.YieldAsync(30);
|
|
||||||
|
|
||||||
list.Add(400);
|
|
||||||
});
|
|
||||||
|
|
||||||
list.Should().BeEmpty();
|
|
||||||
var e = xs.GetAsyncEnumerator();
|
|
||||||
|
|
||||||
list.Should().BeEmpty();
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100);
|
|
||||||
e.Current.Should().Be(10);
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100, 200);
|
|
||||||
e.Current.Should().Be(20);
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100, 200, 300);
|
|
||||||
e.Current.Should().Be(30);
|
|
||||||
|
|
||||||
(await e.MoveNextAsync()).Should().BeFalse();
|
|
||||||
list.Should().Equal(100, 200, 300, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SyncExceptionFirst()
|
|
||||||
{
|
|
||||||
var from = 10;
|
|
||||||
var count = 100;
|
|
||||||
|
|
||||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
throw new UniTaskTestException();
|
|
||||||
await writer.YieldAsync(from + i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SyncException()
|
|
||||||
{
|
|
||||||
var from = 10;
|
|
||||||
var count = 100;
|
|
||||||
|
|
||||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
await writer.YieldAsync(from + i);
|
|
||||||
|
|
||||||
if (i == 15)
|
|
||||||
{
|
|
||||||
throw new UniTaskTestException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ASyncManually()
|
|
||||||
{
|
|
||||||
var list = new List<int>();
|
|
||||||
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
|
|
||||||
{
|
|
||||||
await UniTask.Yield();
|
|
||||||
|
|
||||||
list.Add(100);
|
|
||||||
await writer.YieldAsync(10);
|
|
||||||
|
|
||||||
await UniTask.Yield();
|
|
||||||
|
|
||||||
list.Add(200);
|
|
||||||
await writer.YieldAsync(20);
|
|
||||||
|
|
||||||
await UniTask.Yield();
|
|
||||||
list.Add(300);
|
|
||||||
await UniTask.Yield();
|
|
||||||
await writer.YieldAsync(30);
|
|
||||||
|
|
||||||
await UniTask.Yield();
|
|
||||||
|
|
||||||
list.Add(400);
|
|
||||||
});
|
|
||||||
|
|
||||||
list.Should().BeEmpty();
|
|
||||||
var e = xs.GetAsyncEnumerator();
|
|
||||||
|
|
||||||
list.Should().BeEmpty();
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100);
|
|
||||||
e.Current.Should().Be(10);
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100, 200);
|
|
||||||
e.Current.Should().Be(20);
|
|
||||||
|
|
||||||
await e.MoveNextAsync();
|
|
||||||
list.Should().Equal(100, 200, 300);
|
|
||||||
e.Current.Should().Be(30);
|
|
||||||
|
|
||||||
(await e.MoveNextAsync()).Should().BeFalse();
|
|
||||||
list.Should().Equal(100, 200, 300, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task AwaitForeachBreak()
|
|
||||||
{
|
|
||||||
var finallyCalled = false;
|
|
||||||
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await writer.YieldAsync(1);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
finallyCalled = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await foreach (var x in enumerable)
|
|
||||||
{
|
|
||||||
x.Should().Be(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
finallyCalled.Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
async IAsyncEnumerable<int> Range(int from, int count)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
yield return from + i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,11 +39,11 @@ 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]
|
||||||
public async Task TakeUntilCanceled()
|
public async Task TakeUntil()
|
||||||
{
|
{
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,7 @@ namespace NetCoreTests.Linq
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task SkipUntilCanceled()
|
public async Task SkipUntil()
|
||||||
{
|
{
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
@ -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[] { 30, 40 });
|
||||||
|
|
||||||
async Task CancelAsync()
|
async Task CancelAsync()
|
||||||
{
|
{
|
||||||
|
@ -102,64 +102,5 @@ namespace NetCoreTests.Linq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task TakeUntil()
|
|
||||||
{
|
|
||||||
var cts = new AsyncReactiveProperty<int>(0);
|
|
||||||
|
|
||||||
var rp = new AsyncReactiveProperty<int>(1);
|
|
||||||
|
|
||||||
var xs = rp.TakeUntil(cts.WaitAsync()).ToArrayAsync();
|
|
||||||
|
|
||||||
var c = CancelAsync();
|
|
||||||
|
|
||||||
await c;
|
|
||||||
var foo = await xs;
|
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 1, 10, 20 });
|
|
||||||
|
|
||||||
async Task CancelAsync()
|
|
||||||
{
|
|
||||||
rp.Value = 10;
|
|
||||||
await Task.Yield();
|
|
||||||
rp.Value = 20;
|
|
||||||
await Task.Yield();
|
|
||||||
cts.Value = 9999;
|
|
||||||
rp.Value = 30;
|
|
||||||
await Task.Yield();
|
|
||||||
rp.Value = 40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SkipUntil()
|
|
||||||
{
|
|
||||||
var cts = new AsyncReactiveProperty<int>(0);
|
|
||||||
|
|
||||||
var rp = new AsyncReactiveProperty<int>(1);
|
|
||||||
|
|
||||||
var xs = rp.SkipUntil(cts.WaitAsync()).ToArrayAsync();
|
|
||||||
|
|
||||||
var c = CancelAsync();
|
|
||||||
|
|
||||||
await c;
|
|
||||||
var foo = await xs;
|
|
||||||
|
|
||||||
foo.Should().Equal(new[] { 20, 30, 40 });
|
|
||||||
|
|
||||||
async Task CancelAsync()
|
|
||||||
{
|
|
||||||
rp.Value = 10;
|
|
||||||
await Task.Yield();
|
|
||||||
rp.Value = 20;
|
|
||||||
await Task.Yield();
|
|
||||||
cts.Value = 9999;
|
|
||||||
rp.Value = 30;
|
|
||||||
await Task.Yield();
|
|
||||||
rp.Value = 40;
|
|
||||||
|
|
||||||
rp.Dispose(); // complete.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace NetCoreTests
|
|
||||||
{
|
|
||||||
public class WithCancellationTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async Task Standard()
|
|
||||||
{
|
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var v = await UniTask.Run(() => 10).AttachExternalCancellation(cts.Token);
|
|
||||||
|
|
||||||
v.Should().Be(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Cancel()
|
|
||||||
{
|
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var t = UniTask.Create(async () =>
|
|
||||||
{
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
|
||||||
return 10;
|
|
||||||
}).AttachExternalCancellation(cts.Token);
|
|
||||||
|
|
||||||
cts.Cancel();
|
|
||||||
|
|
||||||
(await Assert.ThrowsAsync<OperationCanceledException>(async () => await t)).CancellationToken.Should().Be(cts.Token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
"overrideReferences": false,
|
"overrideReferences": false,
|
||||||
"precompiledReferences": [],
|
"precompiledReferences": [],
|
||||||
"autoReferenced": false,
|
"autoReferenced": true,
|
||||||
"defineConstraints": [],
|
"defineConstraints": [],
|
||||||
"versionDefines": [],
|
"versionDefines": [],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|
|
@ -7,239 +7,113 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public class AsyncLazy
|
public class AsyncLazy
|
||||||
{
|
{
|
||||||
static Action<object> continuation = SetCompletionSource;
|
Func<UniTask> valueFactory;
|
||||||
|
UniTask target;
|
||||||
Func<UniTask> taskFactory;
|
|
||||||
UniTaskCompletionSource completionSource;
|
|
||||||
UniTask.Awaiter awaiter;
|
|
||||||
|
|
||||||
object syncLock;
|
object syncLock;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
public AsyncLazy(Func<UniTask> taskFactory)
|
public AsyncLazy(Func<UniTask> valueFactory)
|
||||||
{
|
{
|
||||||
this.taskFactory = taskFactory;
|
this.valueFactory = valueFactory;
|
||||||
this.completionSource = new UniTaskCompletionSource();
|
this.target = default;
|
||||||
this.syncLock = new object();
|
this.syncLock = new object();
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AsyncLazy(UniTask task)
|
internal AsyncLazy(UniTask value)
|
||||||
{
|
{
|
||||||
this.taskFactory = null;
|
this.valueFactory = null;
|
||||||
this.completionSource = new UniTaskCompletionSource();
|
this.target = value;
|
||||||
this.syncLock = null;
|
this.syncLock = null;
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
var awaiter = task.GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
SetCompletionSource(awaiter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.awaiter = awaiter;
|
|
||||||
awaiter.SourceOnCompleted(continuation, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask Task
|
public UniTask Task => EnsureInitialized();
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return completionSource.Task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public UniTask.Awaiter GetAwaiter() => EnsureInitialized().GetAwaiter();
|
||||||
|
|
||||||
public UniTask.Awaiter GetAwaiter() => Task.GetAwaiter();
|
UniTask EnsureInitialized()
|
||||||
|
|
||||||
void EnsureInitialized()
|
|
||||||
{
|
{
|
||||||
if (Volatile.Read(ref initialized))
|
if (Volatile.Read(ref initialized))
|
||||||
{
|
{
|
||||||
return;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureInitializedCore();
|
return EnsureInitializedCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnsureInitializedCore()
|
UniTask EnsureInitializedCore()
|
||||||
{
|
{
|
||||||
lock (syncLock)
|
lock (syncLock)
|
||||||
{
|
{
|
||||||
if (!Volatile.Read(ref initialized))
|
if (!Volatile.Read(ref initialized))
|
||||||
{
|
{
|
||||||
var f = Interlocked.Exchange(ref taskFactory, null);
|
var f = Interlocked.Exchange(ref valueFactory, null);
|
||||||
if (f != null)
|
if (f != null)
|
||||||
{
|
{
|
||||||
var task = f();
|
target = f().Preserve(); // with preserve(allow multiple await).
|
||||||
var awaiter = task.GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
SetCompletionSource(awaiter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.awaiter = awaiter;
|
|
||||||
awaiter.SourceOnCompleted(continuation, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Volatile.Write(ref initialized, true);
|
Volatile.Write(ref initialized, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SetCompletionSource(in UniTask.Awaiter awaiter)
|
return target;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
awaiter.GetResult();
|
|
||||||
completionSource.TrySetResult();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetCompletionSource(object state)
|
|
||||||
{
|
|
||||||
var self = (AsyncLazy)state;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
self.awaiter.GetResult();
|
|
||||||
self.completionSource.TrySetResult();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.awaiter = default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AsyncLazy<T>
|
public class AsyncLazy<T>
|
||||||
{
|
{
|
||||||
static Action<object> continuation = SetCompletionSource;
|
Func<UniTask<T>> valueFactory;
|
||||||
|
UniTask<T> target;
|
||||||
Func<UniTask<T>> taskFactory;
|
|
||||||
UniTaskCompletionSource<T> completionSource;
|
|
||||||
UniTask<T>.Awaiter awaiter;
|
|
||||||
|
|
||||||
object syncLock;
|
object syncLock;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
public AsyncLazy(Func<UniTask<T>> taskFactory)
|
public AsyncLazy(Func<UniTask<T>> valueFactory)
|
||||||
{
|
{
|
||||||
this.taskFactory = taskFactory;
|
this.valueFactory = valueFactory;
|
||||||
this.completionSource = new UniTaskCompletionSource<T>();
|
this.target = default;
|
||||||
this.syncLock = new object();
|
this.syncLock = new object();
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AsyncLazy(UniTask<T> task)
|
internal AsyncLazy(UniTask<T> value)
|
||||||
{
|
{
|
||||||
this.taskFactory = null;
|
this.valueFactory = null;
|
||||||
this.completionSource = new UniTaskCompletionSource<T>();
|
this.target = value;
|
||||||
this.syncLock = null;
|
this.syncLock = null;
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
var awaiter = task.GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
SetCompletionSource(awaiter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.awaiter = awaiter;
|
|
||||||
awaiter.SourceOnCompleted(continuation, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask<T> Task
|
public UniTask<T> Task => EnsureInitialized();
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return completionSource.Task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public UniTask<T>.Awaiter GetAwaiter() => EnsureInitialized().GetAwaiter();
|
||||||
|
|
||||||
public UniTask<T>.Awaiter GetAwaiter() => Task.GetAwaiter();
|
UniTask<T> EnsureInitialized()
|
||||||
|
|
||||||
void EnsureInitialized()
|
|
||||||
{
|
{
|
||||||
if (Volatile.Read(ref initialized))
|
if (Volatile.Read(ref initialized))
|
||||||
{
|
{
|
||||||
return;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureInitializedCore();
|
return EnsureInitializedCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnsureInitializedCore()
|
UniTask<T> EnsureInitializedCore()
|
||||||
{
|
{
|
||||||
lock (syncLock)
|
lock (syncLock)
|
||||||
{
|
{
|
||||||
if (!Volatile.Read(ref initialized))
|
if (!Volatile.Read(ref initialized))
|
||||||
{
|
{
|
||||||
var f = Interlocked.Exchange(ref taskFactory, null);
|
var f = Interlocked.Exchange(ref valueFactory, null);
|
||||||
if (f != null)
|
if (f != null)
|
||||||
{
|
{
|
||||||
var task = f();
|
target = f().Preserve(); // with preserve(allow multiple await).
|
||||||
var awaiter = task.GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
SetCompletionSource(awaiter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.awaiter = awaiter;
|
|
||||||
awaiter.SourceOnCompleted(continuation, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Volatile.Write(ref initialized, true);
|
Volatile.Write(ref initialized, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SetCompletionSource(in UniTask<T>.Awaiter awaiter)
|
return target;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = awaiter.GetResult();
|
|
||||||
completionSource.TrySetResult(result);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetCompletionSource(object state)
|
|
||||||
{
|
|
||||||
var self = (AsyncLazy<T>)state;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = self.awaiter.GetResult();
|
|
||||||
self.completionSource.TrySetResult(result);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
self.awaiter = default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
T Value { get; }
|
T Value { get; }
|
||||||
IUniTaskAsyncEnumerable<T> WithoutCurrent();
|
IUniTaskAsyncEnumerable<T> WithoutCurrent();
|
||||||
UniTask<T> WaitAsync(CancellationToken cancellationToken = default);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>
|
public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>
|
||||||
|
@ -70,11 +69,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
return latestValue?.ToString();
|
return latestValue?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isValueType;
|
static bool isValueType;
|
||||||
|
|
||||||
static AsyncReactiveProperty()
|
static AsyncReactiveProperty()
|
||||||
|
@ -82,136 +76,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
isValueType = typeof(T).IsValueType;
|
isValueType = typeof(T).IsValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
|
class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
|
||||||
{
|
|
||||||
static Action<object> cancellationCallback = CancellationCallback;
|
|
||||||
|
|
||||||
static TaskPool<WaitAsyncSource> pool;
|
|
||||||
WaitAsyncSource nextNode;
|
|
||||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitAsyncSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncReactiveProperty<T> parent;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
|
||||||
|
|
||||||
WaitAsyncSource()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new WaitAsyncSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.parent = parent;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
|
|
||||||
if (cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.parent.triggerEvent.Add(result);
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancellationTokenRegistration = default;
|
|
||||||
parent.triggerEvent.Remove(this);
|
|
||||||
parent = null;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
|
||||||
{
|
|
||||||
var self = (WaitAsyncSource)state;
|
|
||||||
self.OnCanceled(self.cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IUniTaskSource
|
|
||||||
|
|
||||||
public T GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
|
||||||
{
|
|
||||||
GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
core.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
return core.GetStatus(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return core.UnsafeGetStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ITriggerHandler
|
|
||||||
|
|
||||||
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
|
|
||||||
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
|
|
||||||
|
|
||||||
public void OnCanceled(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted()
|
|
||||||
{
|
|
||||||
// Complete as Cancel.
|
|
||||||
core.TrySetCanceled(CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnError(Exception ex)
|
|
||||||
{
|
|
||||||
core.TrySetException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnNext(T value)
|
|
||||||
{
|
|
||||||
core.TrySetResult(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
|
|
||||||
{
|
{
|
||||||
readonly AsyncReactiveProperty<T> parent;
|
readonly AsyncReactiveProperty<T> parent;
|
||||||
|
|
||||||
|
@ -388,11 +253,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
return latestValue?.ToString();
|
return latestValue?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isValueType;
|
static bool isValueType;
|
||||||
|
|
||||||
static ReadOnlyAsyncReactiveProperty()
|
static ReadOnlyAsyncReactiveProperty()
|
||||||
|
@ -400,136 +260,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
isValueType = typeof(T).IsValueType;
|
isValueType = typeof(T).IsValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
|
class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
|
||||||
{
|
|
||||||
static Action<object> cancellationCallback = CancellationCallback;
|
|
||||||
|
|
||||||
static TaskPool<WaitAsyncSource> pool;
|
|
||||||
WaitAsyncSource nextNode;
|
|
||||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static WaitAsyncSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyAsyncReactiveProperty<T> parent;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
|
||||||
|
|
||||||
WaitAsyncSource()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new WaitAsyncSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.parent = parent;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
|
|
||||||
if (cancellationToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.parent.triggerEvent.Add(result);
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
cancellationTokenRegistration = default;
|
|
||||||
parent.triggerEvent.Remove(this);
|
|
||||||
parent = null;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
|
||||||
{
|
|
||||||
var self = (WaitAsyncSource)state;
|
|
||||||
self.OnCanceled(self.cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IUniTaskSource
|
|
||||||
|
|
||||||
public T GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
|
||||||
{
|
|
||||||
GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
core.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
return core.GetStatus(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return core.UnsafeGetStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ITriggerHandler
|
|
||||||
|
|
||||||
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
|
|
||||||
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
|
|
||||||
|
|
||||||
public void OnCanceled(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted()
|
|
||||||
{
|
|
||||||
// Complete as Cancel.
|
|
||||||
core.TrySetCanceled(CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnError(Exception ex)
|
|
||||||
{
|
|
||||||
core.TrySetException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnNext(T value)
|
|
||||||
{
|
|
||||||
core.TrySetResult(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
|
|
||||||
{
|
{
|
||||||
readonly ReadOnlyAsyncReactiveProperty<T> parent;
|
readonly ReadOnlyAsyncReactiveProperty<T> parent;
|
||||||
|
|
||||||
|
|
|
@ -9,56 +9,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
public static class CancellationTokenExtensions
|
public static class CancellationTokenExtensions
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationTokenCallback = Callback;
|
static readonly Action<object> cancellationTokenCallback = Callback;
|
||||||
static readonly Action<object> disposeCallback = DisposeCallback;
|
|
||||||
|
|
||||||
public static CancellationToken ToCancellationToken(this UniTask task)
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
ToCancellationTokenCore(task, cts).Forget();
|
|
||||||
return cts.Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken)
|
|
||||||
{
|
|
||||||
if (linkToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return linkToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!linkToken.CanBeCanceled)
|
|
||||||
{
|
|
||||||
return ToCancellationToken(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(linkToken);
|
|
||||||
ToCancellationTokenCore(task, cts).Forget();
|
|
||||||
|
|
||||||
return cts.Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
|
|
||||||
{
|
|
||||||
return ToCancellationToken(task.AsUniTask());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)
|
|
||||||
{
|
|
||||||
return ToCancellationToken(task.AsUniTask(), linkToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await task;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
cts.Cancel();
|
|
||||||
cts.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
|
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -125,17 +75,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CancellationTokenRegistration AddTo(this IDisposable disposable, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return cancellationToken.RegisterWithoutCaptureExecutionContext(disposeCallback, disposable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DisposeCallback(object state)
|
|
||||||
{
|
|
||||||
var d = (IDisposable)state;
|
|
||||||
d.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct CancellationTokenAwaitable
|
public struct CancellationTokenAwaitable
|
||||||
|
|
|
@ -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, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||||
|
|
||||||
static void CancelCancellationTokenSourceState(object state)
|
|
||||||
{
|
{
|
||||||
var cts = (CancellationTokenSource)state;
|
var delay = UniTask.Delay(millisecondsDelay, ignoreTimeScale, delayTiming, cts.Token);
|
||||||
cts.Cancel();
|
CancelAfterCore(cts, delay).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
public static void CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||||
{
|
{
|
||||||
return CancelAfterSlim(cts, TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming);
|
var delay = UniTask.Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cts.Token);
|
||||||
|
CancelAfterCore(cts, delay).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
static async UniTaskVoid CancelAfterCore(CancellationTokenSource cts, UniTask delayTask)
|
||||||
{
|
{
|
||||||
return PlayerLoopTimer.StartNew(delayTimeSpan, false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts);
|
var alreadyCanceled = await delayTask.SuppressCancellationThrow();
|
||||||
|
if (!alreadyCanceled)
|
||||||
|
{
|
||||||
|
cts.Cancel();
|
||||||
|
cts.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
// runner is finished, return first.
|
// runner is finished, return first.
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
{
|
{
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
// workaround for IL2CPP bug.
|
|
||||||
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
|
|
||||||
#else
|
|
||||||
runner.Return();
|
runner.Return();
|
||||||
#endif
|
|
||||||
runner = null;
|
runner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,12 +56,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
// runner is finished, return.
|
// runner is finished, return.
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
{
|
{
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
// workaround for IL2CPP bug.
|
|
||||||
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
|
|
||||||
#else
|
|
||||||
runner.Return();
|
runner.Return();
|
||||||
#endif
|
|
||||||
runner = null;
|
runner = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
using System;
|
using System;
|
||||||
|
@ -8,18 +8,10 @@ using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.CompilerServices
|
namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
{
|
{
|
||||||
// #ENABLE_IL2CPP in this file is to avoid bug of IL2CPP VM.
|
|
||||||
// Issue is tracked on https://issuetracker.unity3d.com/issues/il2cpp-incorrect-results-when-calling-a-method-from-outside-class-in-a-struct
|
|
||||||
// but currently it is labeled `Won't Fix`.
|
|
||||||
|
|
||||||
internal interface IStateMachineRunner
|
internal interface IStateMachineRunner
|
||||||
{
|
{
|
||||||
Action MoveNext { get; }
|
Action MoveNext { get; }
|
||||||
void Return();
|
void Return();
|
||||||
|
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
Action ReturnAction { get; }
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IStateMachineRunnerPromise : IUniTaskSource
|
internal interface IStateMachineRunnerPromise : IUniTaskSource
|
||||||
|
@ -40,7 +32,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
|
|
||||||
internal static class StateMachineUtility
|
internal static class StateMachineUtility
|
||||||
{
|
{
|
||||||
// Get AsyncStateMachine internal state to check IL2CPP bug
|
|
||||||
public static int GetState(IAsyncStateMachine stateMachine)
|
public static int GetState(IAsyncStateMachine stateMachine)
|
||||||
{
|
{
|
||||||
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
||||||
|
@ -55,19 +46,16 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
|
||||||
|
|
||||||
#if ENABLE_IL2CPP
|
#if ENABLE_IL2CPP
|
||||||
public Action ReturnAction { get; }
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
TStateMachine stateMachine;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
public AsyncUniTaskVoid()
|
public AsyncUniTaskVoid()
|
||||||
{
|
{
|
||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
ReturnAction = Return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
|
||||||
|
@ -87,8 +75,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()
|
||||||
{
|
{
|
||||||
|
@ -131,19 +118,18 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine>> pool;
|
||||||
|
|
||||||
#if ENABLE_IL2CPP
|
#if ENABLE_IL2CPP
|
||||||
readonly Action returnDelegate;
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
|
TStateMachine stateMachine;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
AsyncUniTask()
|
AsyncUniTask()
|
||||||
{
|
{
|
||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
returnDelegate = Return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
|
||||||
|
@ -158,22 +144,13 @@ 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()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Return()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
stateMachine = default;
|
|
||||||
pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
|
@ -219,12 +196,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
// workaround for IL2CPP bug.
|
|
||||||
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
|
|
||||||
#else
|
|
||||||
TryReturn();
|
TryReturn();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +217,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
{
|
{
|
||||||
core.OnCompleted(continuation, state, token);
|
core.OnCompleted(continuation, state, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~AsyncUniTask()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
|
internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
|
||||||
|
@ -253,20 +233,18 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
|
||||||
|
|
||||||
#if ENABLE_IL2CPP
|
#if ENABLE_IL2CPP
|
||||||
readonly Action returnDelegate;
|
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
|
||||||
|
#else
|
||||||
|
TStateMachine stateMachine;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public Action MoveNext { get; }
|
public Action MoveNext { get; }
|
||||||
|
|
||||||
TStateMachine stateMachine;
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
AsyncUniTask()
|
AsyncUniTask()
|
||||||
{
|
{
|
||||||
MoveNext = Run;
|
MoveNext = Run;
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
returnDelegate = Return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
|
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
|
||||||
|
@ -279,24 +257,18 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
|
|
||||||
runnerPromiseFieldRef = result; // set runner before copied.
|
runnerPromiseFieldRef = result; // set runner before copied.
|
||||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||||
|
|
||||||
|
// UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine));
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncUniTask<TStateMachine, T> nextNode;
|
|
||||||
public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
|
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
||||||
|
|
||||||
static AsyncUniTask()
|
static AsyncUniTask()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Return()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
stateMachine = default;
|
|
||||||
pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
bool TryReturn()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
|
@ -343,12 +315,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
#if ENABLE_IL2CPP
|
|
||||||
// workaround for IL2CPP bug.
|
|
||||||
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
|
|
||||||
#else
|
|
||||||
TryReturn();
|
TryReturn();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +342,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
{
|
{
|
||||||
core.OnCompleted(continuation, state, token);
|
core.OnCompleted(continuation, state, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~AsyncUniTask()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -58,9 +44,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
IEnumerator innerEnumerator;
|
IEnumerator innerEnumerator;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
int initialFrame;
|
|
||||||
bool loopRunning;
|
|
||||||
bool calledGetResult;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -83,18 +66,10 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
|
result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.loopRunning = true;
|
|
||||||
result.calledGetResult = false;
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
result.initialFrame = -1;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
|
|
||||||
// run immediately.
|
|
||||||
if (result.MoveNext())
|
|
||||||
{
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,15 +77,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
calledGetResult = true;
|
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (!loopRunning)
|
TryReturn();
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,38 +102,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initialFrame == -1)
|
|
||||||
{
|
|
||||||
// Time can not touch in threadpool.
|
|
||||||
if (PlayerLoopHelper.IsMainThread)
|
|
||||||
{
|
|
||||||
initialFrame = Time.frameCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (initialFrame == Time.frameCount)
|
|
||||||
{
|
|
||||||
return true; // already executed in first frame, skip.
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (innerEnumerator.MoveNext())
|
if (innerEnumerator.MoveNext())
|
||||||
|
@ -172,12 +117,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,10 +131,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
innerEnumerator = default;
|
innerEnumerator = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~EnumeratorPromise()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unwrap YieldInstructions
|
// Unwrap YieldInstructions
|
||||||
|
|
||||||
static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
|
static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
|
||||||
|
@ -203,10 +153,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 +183,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 +196,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,12 +216,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
|
static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
|
||||||
{
|
{
|
||||||
var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
|
var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
|
||||||
var elapsed = 0.0f;
|
var startTime = DateTimeOffset.UtcNow;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
elapsed += Time.deltaTime;
|
var elapsed = (DateTimeOffset.UtcNow - startTime).TotalSeconds;
|
||||||
if (elapsed >= second)
|
if (elapsed >= second)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -284,4 +238,5 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
654
src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs
vendored
Normal file
654
src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs
vendored
Normal file
|
@ -0,0 +1,654 @@
|
||||||
|
// asmdef Version Defines, enabled when com.unity.addressables is imported.
|
||||||
|
|
||||||
|
#if UNITASK_ADDRESSABLE_SUPPORT
|
||||||
|
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using System.Threading;
|
||||||
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public static class AddressableAsyncExtensions
|
||||||
|
{
|
||||||
|
#region AsyncOperationHandle
|
||||||
|
|
||||||
|
public static AsyncOperationHandleAwaiter GetAwaiter(this AsyncOperationHandle handle)
|
||||||
|
{
|
||||||
|
return new AsyncOperationHandleAwaiter(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (handle.IsDone) return UniTask.CompletedTask;
|
||||||
|
return new UniTask(AsyncOperationHandleWithCancellationSource.Create(handle, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
if (handle.IsDone) return UniTask.CompletedTask;
|
||||||
|
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
AsyncOperationHandle handle;
|
||||||
|
Action<AsyncOperationHandle> continuationAction;
|
||||||
|
|
||||||
|
public AsyncOperationHandleAwaiter(AsyncOperationHandle handle)
|
||||||
|
{
|
||||||
|
this.handle = handle;
|
||||||
|
this.continuationAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCompleted => handle.IsDone;
|
||||||
|
|
||||||
|
public void GetResult()
|
||||||
|
{
|
||||||
|
if (continuationAction != null)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
continuationAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
var e = handle.OperationException;
|
||||||
|
handle = default;
|
||||||
|
ExceptionDispatchInfo.Capture(e).Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = handle.Result;
|
||||||
|
handle = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
UnsafeOnCompleted(continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||||
|
continuationAction = PooledDelegate<AsyncOperationHandle>.Create(continuation);
|
||||||
|
handle.Completed += continuationAction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle> continuationAction;
|
||||||
|
AsyncOperationHandle handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperationHandle handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||||
|
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncOperationHandle handle;
|
||||||
|
IProgress<float> progress;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleConfiguredSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.progress = progress;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != null)
|
||||||
|
{
|
||||||
|
progress.Report(handle.PercentComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.IsDone)
|
||||||
|
{
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
core.Reset();
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
handle = default;
|
||||||
|
progress = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AsyncOperationHandle_T
|
||||||
|
|
||||||
|
public static AsyncOperationHandleAwaiter<T> GetAwaiter<T>(this AsyncOperationHandle<T> handle)
|
||||||
|
{
|
||||||
|
return new AsyncOperationHandleAwaiter<T>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||||
|
return new UniTask<T>(AsyncOperationHandleWithCancellationSource<T>.Create(handle, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
if (handle.IsDone) return UniTask.FromResult(handle.Result);
|
||||||
|
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct AsyncOperationHandleAwaiter<T> : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
AsyncOperationHandle<T> handle;
|
||||||
|
Action<AsyncOperationHandle> continuationAction;
|
||||||
|
|
||||||
|
public AsyncOperationHandleAwaiter(AsyncOperationHandle<T> handle)
|
||||||
|
{
|
||||||
|
this.handle = handle;
|
||||||
|
this.continuationAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCompleted => handle.IsDone;
|
||||||
|
|
||||||
|
public T GetResult()
|
||||||
|
{
|
||||||
|
if (continuationAction != null)
|
||||||
|
{
|
||||||
|
handle.CompletedTypeless -= continuationAction;
|
||||||
|
continuationAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
var e = handle.OperationException;
|
||||||
|
handle = default;
|
||||||
|
ExceptionDispatchInfo.Capture(e).Throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = handle.Result;
|
||||||
|
handle = default;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
UnsafeOnCompleted(continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(Action continuation)
|
||||||
|
{
|
||||||
|
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
||||||
|
continuationAction = PooledDelegate<AsyncOperationHandle>.Create(continuation);
|
||||||
|
handle.CompletedTypeless += continuationAction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleWithCancellationSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleWithCancellationSource<T>>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleWithCancellationSource<T>> pool;
|
||||||
|
public AsyncOperationHandleWithCancellationSource<T> NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleWithCancellationSource<T>), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
||||||
|
AsyncOperationHandle<T> handle;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleWithCancellationSource<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
||||||
|
|
||||||
|
handle.Completed += result.continuationAction;
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperationHandle<T> _)
|
||||||
|
{
|
||||||
|
handle.Completed -= continuationAction;
|
||||||
|
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(handle.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed = true;
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleWithCancellationSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||||
|
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
|
||||||
|
|
||||||
|
static AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncOperationHandle<T> handle;
|
||||||
|
IProgress<float> progress;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
|
AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncOperationHandleConfiguredSource<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.handle = handle;
|
||||||
|
result.progress = progress;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != null)
|
||||||
|
{
|
||||||
|
progress.Report(handle.PercentComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.IsDone)
|
||||||
|
{
|
||||||
|
if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
core.TrySetException(handle.OperationException);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(handle.Result);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
handle = default;
|
||||||
|
progress = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncOperationHandleConfiguredSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,483 +0,0 @@
|
||||||
// asmdef Version Defines, enabled when com.unity.addressables is imported.
|
|
||||||
|
|
||||||
#if UNITASK_ADDRESSABLE_SUPPORT
|
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Threading;
|
|
||||||
using UnityEngine.AddressableAssets;
|
|
||||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static class AddressablesAsyncExtensions
|
|
||||||
{
|
|
||||||
#region AsyncOperationHandle
|
|
||||||
|
|
||||||
public static UniTask.Awaiter GetAwaiter(this AsyncOperationHandle handle)
|
|
||||||
{
|
|
||||||
return ToUniTask(handle).GetAwaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
|
||||||
{
|
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
|
||||||
|
|
||||||
if (!handle.IsValid())
|
|
||||||
{
|
|
||||||
// autoReleaseHandle:true handle is invalid(immediately internal handle == null) so return completed.
|
|
||||||
return UniTask.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle.IsDone)
|
|
||||||
{
|
|
||||||
if (handle.Status == AsyncOperationStatus.Failed)
|
|
||||||
{
|
|
||||||
return UniTask.FromException(handle.OperationException);
|
|
||||||
}
|
|
||||||
return UniTask.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
|
||||||
{
|
|
||||||
AsyncOperationHandle handle;
|
|
||||||
Action<AsyncOperationHandle> continuationAction;
|
|
||||||
|
|
||||||
public AsyncOperationHandleAwaiter(AsyncOperationHandle handle)
|
|
||||||
{
|
|
||||||
this.handle = handle;
|
|
||||||
this.continuationAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsCompleted => handle.IsDone;
|
|
||||||
|
|
||||||
public void GetResult()
|
|
||||||
{
|
|
||||||
if (continuationAction != null)
|
|
||||||
{
|
|
||||||
handle.Completed -= continuationAction;
|
|
||||||
continuationAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle.Status == AsyncOperationStatus.Failed)
|
|
||||||
{
|
|
||||||
var e = handle.OperationException;
|
|
||||||
handle = default;
|
|
||||||
ExceptionDispatchInfo.Capture(e).Throw();
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = handle.Result;
|
|
||||||
handle = default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action continuation)
|
|
||||||
{
|
|
||||||
UnsafeOnCompleted(continuation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnsafeOnCompleted(Action continuation)
|
|
||||||
{
|
|
||||||
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
|
|
||||||
continuationAction = PooledDelegate<AsyncOperationHandle>.Create(continuation);
|
|
||||||
handle.Completed += continuationAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
|
||||||
AsyncOperationHandleConfiguredSource nextNode;
|
|
||||||
public ref AsyncOperationHandleConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncOperationHandleConfiguredSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle> completedCallback;
|
|
||||||
AsyncOperationHandle handle;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
IProgress<float> progress;
|
|
||||||
bool autoReleaseWhenCanceled;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
|
||||||
{
|
|
||||||
completedCallback = HandleCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AsyncOperationHandleConfiguredSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.handle = handle;
|
|
||||||
result.progress = progress;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.cancelImmediately = cancelImmediately;
|
|
||||||
result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
|
|
||||||
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);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
handle.Completed += result.completedCallback;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleCompleted(AsyncOperationHandle _)
|
|
||||||
{
|
|
||||||
if (handle.IsValid())
|
|
||||||
{
|
|
||||||
handle.Completed -= completedCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else if (handle.Status == AsyncOperationStatus.Failed)
|
|
||||||
{
|
|
||||||
core.TrySetException(handle.OperationException);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (completed)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
|
||||||
{
|
|
||||||
progress.Report(handle.GetDownloadStatus().Percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
handle = default;
|
|
||||||
progress = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region AsyncOperationHandle_T
|
|
||||||
|
|
||||||
public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> handle)
|
|
||||||
{
|
|
||||||
return ToUniTask(handle).GetAwaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
|
||||||
{
|
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
|
||||||
|
|
||||||
if (!handle.IsValid())
|
|
||||||
{
|
|
||||||
throw new Exception("Attempting to use an invalid operation handle");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle.IsDone)
|
|
||||||
{
|
|
||||||
if (handle.Status == AsyncOperationStatus.Failed)
|
|
||||||
{
|
|
||||||
return UniTask.FromException<T>(handle.OperationException);
|
|
||||||
}
|
|
||||||
return UniTask.FromResult(handle.Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
|
||||||
{
|
|
||||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
|
||||||
AsyncOperationHandleConfiguredSource<T> nextNode;
|
|
||||||
public ref AsyncOperationHandleConfiguredSource<T> NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncOperationHandleConfiguredSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle<T>> completedCallback;
|
|
||||||
AsyncOperationHandle<T> handle;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration;
|
|
||||||
IProgress<float> progress;
|
|
||||||
bool autoReleaseWhenCanceled;
|
|
||||||
bool cancelImmediately;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
|
||||||
{
|
|
||||||
completedCallback = HandleCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AsyncOperationHandleConfiguredSource<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.handle = handle;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
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);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
handle.Completed += result.completedCallback;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleCompleted(AsyncOperationHandle<T> argHandle)
|
|
||||||
{
|
|
||||||
if (handle.IsValid())
|
|
||||||
{
|
|
||||||
handle.Completed -= completedCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
|
||||||
{
|
|
||||||
core.TrySetException(argHandle.OperationException);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(argHandle.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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (autoReleaseWhenCanceled && handle.IsValid())
|
|
||||||
{
|
|
||||||
Addressables.Release(handle);
|
|
||||||
}
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
|
||||||
{
|
|
||||||
progress.Report(handle.GetDownloadStatus().Percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
handle = default;
|
|
||||||
progress = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"name": "UniTask.Addressables",
|
|
||||||
"references": [
|
|
||||||
"UniTask",
|
|
||||||
"Unity.ResourceManager",
|
|
||||||
"Unity.Addressables"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.unity.addressables",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.addressables.cn",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_ADDRESSABLE_SUPPORT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 593a5b492d29ac6448b1ebf7f035ef33
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 25cb2f742bfeb1d48a4e65d3140b955d
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,436 +0,0 @@
|
||||||
// asmdef Version Defines, enabled when com.demigiant.dotween is imported.
|
|
||||||
|
|
||||||
#if UNITASK_DOTWEEN_SUPPORT
|
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using DG.Tweening;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public enum TweenCancelBehaviour
|
|
||||||
{
|
|
||||||
Kill,
|
|
||||||
KillWithCompleteCallback,
|
|
||||||
Complete,
|
|
||||||
CompleteWithSequenceCallback,
|
|
||||||
CancelAwait,
|
|
||||||
|
|
||||||
// AndCancelAwait
|
|
||||||
KillAndCancelAwait,
|
|
||||||
KillWithCompleteCallbackAndCancelAwait,
|
|
||||||
CompleteAndCancelAwait,
|
|
||||||
CompleteWithSequenceCallbackAndCancelAwait
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DOTweenAsyncExtensions
|
|
||||||
{
|
|
||||||
enum CallbackType
|
|
||||||
{
|
|
||||||
Kill,
|
|
||||||
Complete,
|
|
||||||
Pause,
|
|
||||||
Play,
|
|
||||||
Rewind,
|
|
||||||
StepComplete
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TweenAwaiter GetAwaiter(this Tween tween)
|
|
||||||
{
|
|
||||||
return new TweenAwaiter(tween);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask WithCancellation(this Tween tween, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, CallbackType.Kill, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Kill, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask AwaitForComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Complete, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask AwaitForPause(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Pause, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask AwaitForPlay(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Play, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask AwaitForRewind(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Rewind, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask AwaitForStepComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
|
||||||
|
|
||||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.StepComplete, out var token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct TweenAwaiter : ICriticalNotifyCompletion
|
|
||||||
{
|
|
||||||
readonly Tween tween;
|
|
||||||
|
|
||||||
// killed(non active) as completed.
|
|
||||||
public bool IsCompleted => !tween.IsActive();
|
|
||||||
|
|
||||||
public TweenAwaiter(Tween tween)
|
|
||||||
{
|
|
||||||
this.tween = tween;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TweenAwaiter GetAwaiter()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(System.Action continuation)
|
|
||||||
{
|
|
||||||
UnsafeOnCompleted(continuation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnsafeOnCompleted(System.Action continuation)
|
|
||||||
{
|
|
||||||
// onKill is called after OnCompleted, both Complete(false/true) and Kill(false/true).
|
|
||||||
tween.onKill = PooledTweenCallback.Create(continuation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
|
|
||||||
{
|
|
||||||
static TaskPool<TweenConfiguredSource> pool;
|
|
||||||
TweenConfiguredSource nextNode;
|
|
||||||
public ref TweenConfiguredSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static TweenConfiguredSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly TweenCallback onCompleteCallbackDelegate;
|
|
||||||
|
|
||||||
Tween tween;
|
|
||||||
TweenCancelBehaviour cancelBehaviour;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
CancellationTokenRegistration cancellationRegistration;
|
|
||||||
CallbackType callbackType;
|
|
||||||
bool canceled;
|
|
||||||
|
|
||||||
TweenCallback originalCompleteAction;
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
|
||||||
|
|
||||||
TweenConfiguredSource()
|
|
||||||
{
|
|
||||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
DoCancelBeforeCreate(tween, cancelBehaviour);
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new TweenConfiguredSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.tween = tween;
|
|
||||||
result.cancelBehaviour = cancelBehaviour;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.callbackType = callbackType;
|
|
||||||
result.canceled = false;
|
|
||||||
|
|
||||||
switch (callbackType)
|
|
||||||
{
|
|
||||||
case CallbackType.Kill:
|
|
||||||
result.originalCompleteAction = tween.onKill;
|
|
||||||
tween.onKill = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
case CallbackType.Complete:
|
|
||||||
result.originalCompleteAction = tween.onComplete;
|
|
||||||
tween.onComplete = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
case CallbackType.Pause:
|
|
||||||
result.originalCompleteAction = tween.onPause;
|
|
||||||
tween.onPause = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
case CallbackType.Play:
|
|
||||||
result.originalCompleteAction = tween.onPlay;
|
|
||||||
tween.onPlay = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
case CallbackType.Rewind:
|
|
||||||
result.originalCompleteAction = tween.onRewind;
|
|
||||||
tween.onRewind = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
case CallbackType.StepComplete:
|
|
||||||
result.originalCompleteAction = tween.onStepComplete;
|
|
||||||
tween.onStepComplete = result.onCompleteCallbackDelegate;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
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);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
originalCompleteAction?.Invoke();
|
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (tweenCancelBehaviour)
|
|
||||||
{
|
|
||||||
case TweenCancelBehaviour.Kill:
|
|
||||||
default:
|
|
||||||
tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillAndCancelAwait:
|
|
||||||
tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallback:
|
|
||||||
tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
|
||||||
tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.Complete:
|
|
||||||
tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
|
||||||
tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
|
||||||
tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
|
||||||
tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
return core.GetStatus(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return core.UnsafeGetStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
core.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
cancellationRegistration.Dispose();
|
|
||||||
|
|
||||||
RestoreOriginalCallback();
|
|
||||||
|
|
||||||
tween = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
originalCompleteAction = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreOriginalCallback()
|
|
||||||
{
|
|
||||||
switch (callbackType)
|
|
||||||
{
|
|
||||||
case CallbackType.Kill:
|
|
||||||
tween.onKill = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Complete:
|
|
||||||
tween.onComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Pause:
|
|
||||||
tween.onPause = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Play:
|
|
||||||
tween.onPlay = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Rewind:
|
|
||||||
tween.onRewind = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.StepComplete:
|
|
||||||
tween.onStepComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class PooledTweenCallback
|
|
||||||
{
|
|
||||||
static readonly ConcurrentQueue<PooledTweenCallback> pool = new ConcurrentQueue<PooledTweenCallback>();
|
|
||||||
|
|
||||||
readonly TweenCallback runDelegate;
|
|
||||||
|
|
||||||
Action continuation;
|
|
||||||
|
|
||||||
|
|
||||||
PooledTweenCallback()
|
|
||||||
{
|
|
||||||
runDelegate = Run;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static TweenCallback Create(Action continuation)
|
|
||||||
{
|
|
||||||
if (!pool.TryDequeue(out var item))
|
|
||||||
{
|
|
||||||
item = new PooledTweenCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
item.continuation = continuation;
|
|
||||||
return item.runDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
void Run()
|
|
||||||
{
|
|
||||||
var call = continuation;
|
|
||||||
continuation = null;
|
|
||||||
if (call != null)
|
|
||||||
{
|
|
||||||
pool.Enqueue(this);
|
|
||||||
call.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"name": "UniTask.DOTween",
|
|
||||||
"references": [
|
|
||||||
"UniTask",
|
|
||||||
"DOTween.Modules"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.demigiant.dotween",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_DOTWEEN_SUPPORT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 029c1c1b674aaae47a6841a0b89ad80e
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
332
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs
vendored
Normal file
332
src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs
vendored
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
// asmdef Version Defines, enabled when com.demigiant.dotween is imported.
|
||||||
|
|
||||||
|
#if UNITASK_DOTWEEN_SUPPORT
|
||||||
|
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
using DG.Tweening;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
// The idea of TweenCancelBehaviour is borrowed from https://www.shibuya24.info/entry/dotween_async_await
|
||||||
|
public enum TweenCancelBehaviour
|
||||||
|
{
|
||||||
|
Kill,
|
||||||
|
KillWithCompleteCallback,
|
||||||
|
Complete,
|
||||||
|
CompleteWithSeqeunceCallback,
|
||||||
|
CancelAwait,
|
||||||
|
|
||||||
|
// AndCancelAwait
|
||||||
|
KillAndCancelAwait,
|
||||||
|
KillWithCompleteCallbackAndCancelAwait,
|
||||||
|
CompleteAndCancelAwait,
|
||||||
|
CompleteWithSeqeunceCallbackAndCancelAwait
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DOTweenAsyncExtensions
|
||||||
|
{
|
||||||
|
public static TweenAwaiter GetAwaiter(this Tween tween)
|
||||||
|
{
|
||||||
|
return new TweenAwaiter(tween);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask WithCancellation(this Tween tween, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||||
|
|
||||||
|
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||||
|
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||||
|
|
||||||
|
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||||
|
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct TweenAwaiter : ICriticalNotifyCompletion
|
||||||
|
{
|
||||||
|
readonly Tween tween;
|
||||||
|
|
||||||
|
// killed(non active) as completed.
|
||||||
|
public bool IsCompleted => !tween.IsActive();
|
||||||
|
|
||||||
|
public TweenAwaiter(Tween tween)
|
||||||
|
{
|
||||||
|
this.tween = tween;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TweenAwaiter GetAwaiter()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(System.Action continuation)
|
||||||
|
{
|
||||||
|
UnsafeOnCompleted(continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsafeOnCompleted(System.Action continuation)
|
||||||
|
{
|
||||||
|
// onKill is called after OnCompleted, both Complete(false/true) and Kill(false/true).
|
||||||
|
tween.onKill = PooledTweenCallback.Create(continuation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
|
||||||
|
{
|
||||||
|
static TaskPool<TweenConfiguredSource> pool;
|
||||||
|
public TweenConfiguredSource NextNode { get; set; }
|
||||||
|
|
||||||
|
static TweenConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly TweenCallback EmptyTweenCallback = () => { };
|
||||||
|
|
||||||
|
readonly TweenCallback onKillDelegate;
|
||||||
|
readonly TweenCallback onUpdateDelegate;
|
||||||
|
|
||||||
|
Tween tween;
|
||||||
|
TweenCancelBehaviour cancelBehaviour;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool canceled;
|
||||||
|
|
||||||
|
TweenCallback originalUpdateAction;
|
||||||
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
TweenConfiguredSource()
|
||||||
|
{
|
||||||
|
onKillDelegate = OnKill;
|
||||||
|
onUpdateDelegate = OnUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
DoCancelBeforeCreate(tween, cancelBehaviour);
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new TweenConfiguredSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.tween = tween;
|
||||||
|
result.cancelBehaviour = cancelBehaviour;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
result.originalUpdateAction = tween.onUpdate;
|
||||||
|
result.canceled = false;
|
||||||
|
|
||||||
|
if (result.originalUpdateAction == result.onUpdateDelegate)
|
||||||
|
{
|
||||||
|
result.originalUpdateAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
tween.onUpdate = result.onUpdateDelegate;
|
||||||
|
tween.onKill = result.onKillDelegate;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnKill()
|
||||||
|
{
|
||||||
|
if (canceled)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
this.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||||
|
this.core.TrySetCanceled(this.cancellationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (tweenCancelBehaviour)
|
||||||
|
{
|
||||||
|
case TweenCancelBehaviour.Kill:
|
||||||
|
default:
|
||||||
|
tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
|
tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
|
tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
|
tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.Complete:
|
||||||
|
tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
|
tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallback:
|
||||||
|
tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait:
|
||||||
|
tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return core.GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return core.UnsafeGetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
core.OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
tween.onUpdate = originalUpdateAction;
|
||||||
|
tween.onKill = null;
|
||||||
|
tween = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
originalUpdateAction = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TweenConfiguredSource()
|
||||||
|
{
|
||||||
|
if (TryReturn())
|
||||||
|
{
|
||||||
|
GC.ReRegisterForFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class PooledTweenCallback
|
||||||
|
{
|
||||||
|
static readonly ConcurrentQueue<PooledTweenCallback> pool = new ConcurrentQueue<PooledTweenCallback>();
|
||||||
|
|
||||||
|
readonly TweenCallback runDelegate;
|
||||||
|
|
||||||
|
Action continuation;
|
||||||
|
|
||||||
|
|
||||||
|
PooledTweenCallback()
|
||||||
|
{
|
||||||
|
runDelegate = Run;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TweenCallback Create(Action continuation)
|
||||||
|
{
|
||||||
|
if (!pool.TryDequeue(out var item))
|
||||||
|
{
|
||||||
|
item = new PooledTweenCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
item.continuation = continuation;
|
||||||
|
return item.runDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
void Run()
|
||||||
|
{
|
||||||
|
var call = continuation;
|
||||||
|
continuation = null;
|
||||||
|
if (call != null)
|
||||||
|
{
|
||||||
|
pool.Enqueue(this);
|
||||||
|
call.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,224 +0,0 @@
|
||||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using TMPro;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static partial class TextMeshProAsyncExtensions
|
|
||||||
{
|
|
||||||
public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnSelectAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnSelectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,66 +0,0 @@
|
||||||
<#@ template debug="false" hostspecific="false" language="C#" #>
|
|
||||||
<#@ assembly name="System.Core" #>
|
|
||||||
<#@ import namespace="System.Linq" #>
|
|
||||||
<#@ import namespace="System.Text" #>
|
|
||||||
<#@ import namespace="System.Collections.Generic" #>
|
|
||||||
<#@ output extension=".cs" #>
|
|
||||||
<#
|
|
||||||
var handlers = new (string name, string type)[] {
|
|
||||||
("ValueChanged", "string"),
|
|
||||||
("EndEdit", "string"),
|
|
||||||
("EndTextSelection", "(string, int, int)"),
|
|
||||||
("TextSelection", "(string, int, int)"),
|
|
||||||
("Deselect", "string"),
|
|
||||||
("Select", "string"),
|
|
||||||
("Submit", "string"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Func<string, bool> shouldConvert = x => x.EndsWith("TextSelection");
|
|
||||||
Func<string, string> eventName = x => shouldConvert(x) ? $"new TextSelectionEventConverter(inputField.on{x})" : $"inputField.on{x}";
|
|
||||||
#>
|
|
||||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using TMPro;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static partial class TextMeshProAsyncExtensions
|
|
||||||
{
|
|
||||||
<# foreach(var (name, type) in handlers) { #>
|
|
||||||
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, true).OnInvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
<# } #>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,130 +0,0 @@
|
||||||
#if UNITASK_TEXTMESHPRO_SUPPORT
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using TMPro;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
|
||||||
{
|
|
||||||
public static partial class TextMeshProAsyncExtensions
|
|
||||||
{
|
|
||||||
// <string> -> Text
|
|
||||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, bool rebindOnError = true)
|
|
||||||
{
|
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
|
||||||
{
|
|
||||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
|
||||||
{
|
|
||||||
var repeat = false;
|
|
||||||
BIND_AGAIN:
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
bool moveNext;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
moveNext = await e.MoveNextAsync();
|
|
||||||
repeat = false;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
if (rebindOnError && !repeat)
|
|
||||||
{
|
|
||||||
repeat = true;
|
|
||||||
goto BIND_AGAIN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!moveNext) return;
|
|
||||||
|
|
||||||
text.text = e.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// <T> -> Text
|
|
||||||
|
|
||||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, bool rebindOnError = true)
|
|
||||||
{
|
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
|
||||||
{
|
|
||||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void BindTo<T>(this AsyncReactiveProperty<T> source, TMP_Text text, bool rebindOnError = true)
|
|
||||||
{
|
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
|
||||||
{
|
|
||||||
var repeat = false;
|
|
||||||
BIND_AGAIN:
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
bool moveNext;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
moveNext = await e.MoveNextAsync();
|
|
||||||
repeat = false;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
if (rebindOnError && !repeat)
|
|
||||||
{
|
|
||||||
repeat = true;
|
|
||||||
goto BIND_AGAIN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!moveNext) return;
|
|
||||||
|
|
||||||
text.text = e.Current.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"name": "UniTask.TextMeshPro",
|
|
||||||
"references": [
|
|
||||||
"UniTask",
|
|
||||||
"Unity.TextMeshPro"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.unity.textmeshpro",
|
|
||||||
"expression": "",
|
|
||||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.ugui",
|
|
||||||
"expression": "2.0.0",
|
|
||||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: dc47925d1a5fa2946bdd37746b2b5d48
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
{
|
{
|
||||||
const int MaxArrayLength = 0X7FEFFFFF;
|
const int MaxArrayLength = 0X7FEFFFFF;
|
||||||
const int InitialSize = 16;
|
const int InitialSize = 16;
|
||||||
|
|
||||||
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,17 +170,10 @@ 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
|
|
||||||
{
|
action();
|
||||||
action();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Internal
|
|
||||||
{
|
|
||||||
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
|
||||||
|
|
||||||
internal static class UnityWebRequestResultExtensions
|
|
||||||
{
|
|
||||||
public static bool IsError(this UnityWebRequest unityWebRequest)
|
|
||||||
{
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
var result = unityWebRequest.result;
|
|
||||||
return (result == UnityWebRequest.Result.ConnectionError)
|
|
||||||
|| (result == UnityWebRequest.Result.DataProcessingError)
|
|
||||||
|| (result == UnityWebRequest.Result.ProtocolError);
|
|
||||||
#else
|
|
||||||
return unityWebRequest.isHttpError || unityWebRequest.isNetworkError;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Internal
|
|
||||||
{
|
|
||||||
internal readonly struct ValueStopwatch
|
|
||||||
{
|
|
||||||
static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
|
|
||||||
|
|
||||||
readonly long startTimestamp;
|
|
||||||
|
|
||||||
public static ValueStopwatch StartNew() => new ValueStopwatch(Stopwatch.GetTimestamp());
|
|
||||||
|
|
||||||
ValueStopwatch(long startTimestamp)
|
|
||||||
{
|
|
||||||
this.startTimestamp = startTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
|
|
||||||
|
|
||||||
public bool IsInvalid => startTimestamp == 0;
|
|
||||||
|
|
||||||
public long ElapsedTicks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (startTimestamp == 0)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Detected invalid initialization(use 'default'), only to create from StartNew().");
|
|
||||||
}
|
|
||||||
|
|
||||||
var delta = Stopwatch.GetTimestamp() - startTimestamp;
|
|
||||||
return (long)(delta * TimestampToTicks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
|
||||||
{
|
|
||||||
public static partial class UniTaskAsyncEnumerable
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<T> Create<T>(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(create, nameof(create));
|
|
||||||
return new Create<T>(create);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IAsyncWriter<T>
|
|
||||||
{
|
|
||||||
UniTask YieldAsync(T value);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class Create<T> : IUniTaskAsyncEnumerable<T>
|
|
||||||
{
|
|
||||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
|
||||||
|
|
||||||
public Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
|
||||||
{
|
|
||||||
this.create = create;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return new _Create(create, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _Create : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
|
||||||
{
|
|
||||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
|
||||||
readonly CancellationToken cancellationToken;
|
|
||||||
|
|
||||||
int state = -1;
|
|
||||||
AsyncWriter writer;
|
|
||||||
|
|
||||||
public _Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
this.create = create;
|
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Current { get; private set; }
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
writer.Dispose();
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
if (state == -2) return default;
|
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
MoveNext();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveNext()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case -1: // init
|
|
||||||
{
|
|
||||||
writer = new AsyncWriter(this);
|
|
||||||
RunWriterTask(create(writer, cancellationToken)).Forget();
|
|
||||||
if (Volatile.Read(ref state) == -2)
|
|
||||||
{
|
|
||||||
return; // complete synchronously
|
|
||||||
}
|
|
||||||
state = 0; // wait YieldAsync, it set TrySetResult(true)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
writer.SignalWriter();
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
goto DONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
state = -2;
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DONE:
|
|
||||||
state = -2;
|
|
||||||
completionSource.TrySetResult(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTaskVoid RunWriterTask(UniTask task)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await task;
|
|
||||||
goto DONE;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Volatile.Write(ref state, -2);
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DONE:
|
|
||||||
Volatile.Write(ref state, -2);
|
|
||||||
completionSource.TrySetResult(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetResult(T value)
|
|
||||||
{
|
|
||||||
Current = value;
|
|
||||||
completionSource.TrySetResult(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
|
||||||
{
|
|
||||||
readonly _Create enumerator;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
|
||||||
|
|
||||||
public AsyncWriter(_Create enumerator)
|
|
||||||
{
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
var status = core.GetStatus(core.Version);
|
|
||||||
if (status == UniTaskStatus.Pending)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
return core.GetStatus(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return core.UnsafeGetStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
core.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask YieldAsync(T value)
|
|
||||||
{
|
|
||||||
core.Reset();
|
|
||||||
enumerator.SetResult(value);
|
|
||||||
return new UniTask(this, core.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SignalWriter()
|
|
||||||
{
|
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 0202f723469f93945afa063bfb440d15
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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
|
|
|
@ -88,7 +88,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -157,7 +156,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +195,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -266,7 +263,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +302,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -387,7 +382,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +422,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -509,7 +502,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,7 +541,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -630,7 +621,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,7 +661,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.moveNextAction = MoveNext;
|
this.moveNextAction = MoveNext;
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TResult Current { get; private set; }
|
public TResult Current { get; private set; }
|
||||||
|
@ -752,7 +741,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,187 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
|
||||||
{
|
|
||||||
public static partial class UniTaskAsyncEnumerable
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, UniTask other)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
|
|
||||||
return new SkipUntil<TSource>(source, other, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<CancellationToken, UniTask> other)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(other));
|
|
||||||
|
|
||||||
return new SkipUntil<TSource>(source, default, other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class SkipUntil<TSource> : IUniTaskAsyncEnumerable<TSource>
|
|
||||||
{
|
|
||||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
|
||||||
readonly UniTask other;
|
|
||||||
readonly Func<CancellationToken, UniTask> other2;
|
|
||||||
|
|
||||||
public SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, Func<CancellationToken, UniTask> other2)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.other = other;
|
|
||||||
this.other2 = other2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (other2 != null)
|
|
||||||
{
|
|
||||||
return new _SkipUntil(source, this.other2(cancellationToken), cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new _SkipUntil(source, this.other, cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _SkipUntil : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
|
||||||
{
|
|
||||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
|
||||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
|
||||||
|
|
||||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
|
||||||
CancellationToken cancellationToken1;
|
|
||||||
|
|
||||||
bool completed;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
|
||||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
|
||||||
UniTask<bool>.Awaiter awaiter;
|
|
||||||
bool continueNext;
|
|
||||||
Exception exception;
|
|
||||||
|
|
||||||
public _SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, CancellationToken cancellationToken1)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.cancellationToken1 = cancellationToken1;
|
|
||||||
if (cancellationToken1.CanBeCanceled)
|
|
||||||
{
|
|
||||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
RunOther(other).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TSource Current { get; private set; }
|
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
if (exception != null)
|
|
||||||
{
|
|
||||||
return UniTask.FromException<bool>(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken1.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return UniTask.FromCanceled<bool>(cancellationToken1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enumerator == null)
|
|
||||||
{
|
|
||||||
enumerator = source.GetAsyncEnumerator(cancellationToken1);
|
|
||||||
}
|
|
||||||
completionSource.Reset();
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
SourceMoveNext();
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SourceMoveNext()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LOOP:
|
|
||||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
continueNext = true;
|
|
||||||
MoveNextCore(this);
|
|
||||||
if (continueNext)
|
|
||||||
{
|
|
||||||
continueNext = false;
|
|
||||||
goto LOOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MoveNextCore(object state)
|
|
||||||
{
|
|
||||||
var self = (_SkipUntil)state;
|
|
||||||
|
|
||||||
if (self.TryGetResult(self.awaiter, out var result))
|
|
||||||
{
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
self.Current = self.enumerator.Current;
|
|
||||||
self.completionSource.TrySetResult(true);
|
|
||||||
if (self.continueNext)
|
|
||||||
{
|
|
||||||
self.SourceMoveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetResult(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTaskVoid RunOther(UniTask other)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await other;
|
|
||||||
completed = true;
|
|
||||||
SourceMoveNext();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exception = ex;
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnCanceled1(object state)
|
|
||||||
{
|
|
||||||
var self = (_SkipUntil)state;
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
cancellationTokenRegistration1.Dispose();
|
|
||||||
if (enumerator != null)
|
|
||||||
{
|
|
||||||
return enumerator.DisposeAsync();
|
|
||||||
}
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: de932d79c8d9f3841a066d05ff29edc9
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -32,17 +32,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
sealed class _SkipUntilCanceled : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
sealed class _SkipUntilCanceled : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||||
{
|
{
|
||||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
|
||||||
static readonly Action<object> CancelDelegate2 = OnCanceled2;
|
|
||||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||||
|
|
||||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||||
CancellationToken cancellationToken1;
|
CancellationToken cancellationToken1;
|
||||||
CancellationToken cancellationToken2;
|
CancellationToken cancellationToken2;
|
||||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration2;
|
|
||||||
|
|
||||||
int isCanceled;
|
bool isCanceled;
|
||||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||||
UniTask<bool>.Awaiter awaiter;
|
UniTask<bool>.Awaiter awaiter;
|
||||||
bool continueNext;
|
bool continueNext;
|
||||||
|
@ -52,14 +48,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.cancellationToken1 = cancellationToken1;
|
this.cancellationToken1 = cancellationToken1;
|
||||||
this.cancellationToken2 = cancellationToken2;
|
this.cancellationToken2 = cancellationToken2;
|
||||||
if (cancellationToken1.CanBeCanceled)
|
|
||||||
{
|
|
||||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
|
||||||
}
|
|
||||||
if (cancellationToken1 != cancellationToken2 && cancellationToken2.CanBeCanceled)
|
|
||||||
{
|
|
||||||
this.cancellationTokenRegistration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(CancelDelegate2, this);
|
|
||||||
}
|
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
TaskTracker.TrackActiveTask(this, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,18 +55,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
|
if (cancellationToken1.IsCancellationRequested) isCanceled = true;
|
||||||
|
if (cancellationToken2.IsCancellationRequested) isCanceled = true;
|
||||||
|
|
||||||
if (enumerator == null)
|
if (enumerator == null)
|
||||||
{
|
{
|
||||||
if (cancellationToken1.IsCancellationRequested) isCanceled = 1;
|
|
||||||
if (cancellationToken2.IsCancellationRequested) isCanceled = 1;
|
|
||||||
enumerator = source.GetAsyncEnumerator(cancellationToken2); // use only AsyncEnumerator provided token.
|
enumerator = source.GetAsyncEnumerator(cancellationToken2); // use only AsyncEnumerator provided token.
|
||||||
}
|
}
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
SourceMoveNext();
|
||||||
if (isCanceled != 0)
|
|
||||||
{
|
|
||||||
SourceMoveNext();
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,11 +102,25 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
self.Current = self.enumerator.Current;
|
AGAIN:
|
||||||
self.completionSource.TrySetResult(true);
|
|
||||||
if (self.continueNext)
|
if (self.isCanceled)
|
||||||
{
|
{
|
||||||
self.SourceMoveNext();
|
self.continueNext = false;
|
||||||
|
self.Current = self.enumerator.Current;
|
||||||
|
self.completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (self.cancellationToken1.IsCancellationRequested) self.isCanceled = true;
|
||||||
|
if (self.cancellationToken2.IsCancellationRequested) self.isCanceled = true;
|
||||||
|
|
||||||
|
if (self.isCanceled) goto AGAIN;
|
||||||
|
|
||||||
|
if (!self.continueNext)
|
||||||
|
{
|
||||||
|
self.SourceMoveNext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -131,37 +130,9 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnCanceled1(object state)
|
|
||||||
{
|
|
||||||
var self = (_SkipUntilCanceled)state;
|
|
||||||
if (self.isCanceled == 0)
|
|
||||||
{
|
|
||||||
if (Interlocked.Increment(ref self.isCanceled) == 1)
|
|
||||||
{
|
|
||||||
self.cancellationTokenRegistration2.Dispose();
|
|
||||||
self.SourceMoveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnCanceled2(object state)
|
|
||||||
{
|
|
||||||
var self = (_SkipUntilCanceled)state;
|
|
||||||
if (self.isCanceled == 0)
|
|
||||||
{
|
|
||||||
if (Interlocked.Increment(ref self.isCanceled) == 1)
|
|
||||||
{
|
|
||||||
self.cancellationTokenRegistration2.Dispose();
|
|
||||||
self.SourceMoveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
cancellationTokenRegistration1.Dispose();
|
|
||||||
cancellationTokenRegistration2.Dispose();
|
|
||||||
if (enumerator != null)
|
if (enumerator != null)
|
||||||
{
|
{
|
||||||
return enumerator.DisposeAsync();
|
return enumerator.DisposeAsync();
|
||||||
|
|
|
@ -1,536 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using Subscribes = Cysharp.Threading.Tasks.Linq.Subscribe;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
|
||||||
{
|
|
||||||
public static partial class UniTaskAsyncEnumerable
|
|
||||||
{
|
|
||||||
// OnNext
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> action)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> action, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(action, nameof(action));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnNext, OnError
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnNext, OnCompleted
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action onCompleted)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
|
||||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
|
||||||
|
|
||||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// IObserver
|
|
||||||
|
|
||||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(observer, nameof(observer));
|
|
||||||
|
|
||||||
var cts = new CancellationTokenDisposable();
|
|
||||||
Subscribes.SubscribeCore(source, observer, cts.Token).Forget();
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(observer, nameof(observer));
|
|
||||||
|
|
||||||
Subscribes.SubscribeCore(source, observer, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class CancellationTokenDisposable : IDisposable
|
|
||||||
{
|
|
||||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
public CancellationToken Token => cts.Token;
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!cts.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
cts.Cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class Subscribe
|
|
||||||
{
|
|
||||||
public static readonly Action<Exception> NopError = _ => { };
|
|
||||||
public static readonly Action NopCompleted = () => { };
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
onNext(e.Current);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (onError == NopError)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
onError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
onNext(e.Current).Forget();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (onError == NopError)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
onError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
onNext(e.Current, cancellationToken).Forget();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (onError == NopError)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
onError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
observer.OnNext(e.Current);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
observer.OnCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
observer.OnError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await onNext(e.Current);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (onError == NopError)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
onError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (await e.MoveNextAsync())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await onNext(e.Current, cancellationToken);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onCompleted();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (onError == NopError)
|
|
||||||
{
|
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex is OperationCanceledException) return;
|
|
||||||
|
|
||||||
onError(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
await e.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 263479eb04c189741931fc0e2f615c2d
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,190 +0,0 @@
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Linq
|
|
||||||
{
|
|
||||||
public static partial class UniTaskAsyncEnumerable
|
|
||||||
{
|
|
||||||
public static IUniTaskAsyncEnumerable<TSource> TakeUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, UniTask other)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
|
|
||||||
return new TakeUntil<TSource>(source, other, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<TSource> TakeUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<CancellationToken, UniTask> other)
|
|
||||||
{
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(source));
|
|
||||||
Error.ThrowArgumentNullException(source, nameof(other));
|
|
||||||
|
|
||||||
return new TakeUntil<TSource>(source, default, other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class TakeUntil<TSource> : IUniTaskAsyncEnumerable<TSource>
|
|
||||||
{
|
|
||||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
|
||||||
readonly UniTask other;
|
|
||||||
readonly Func<CancellationToken, UniTask> other2;
|
|
||||||
|
|
||||||
public TakeUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, Func<CancellationToken, UniTask> other2)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.other = other;
|
|
||||||
this.other2 = other2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (other2 != null)
|
|
||||||
{
|
|
||||||
return new _TakeUntil(source, this.other2(cancellationToken), cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new _TakeUntil(source, this.other, cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class _TakeUntil : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
|
||||||
{
|
|
||||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
|
||||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
|
||||||
|
|
||||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
|
||||||
CancellationToken cancellationToken1;
|
|
||||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
|
||||||
|
|
||||||
bool completed;
|
|
||||||
Exception exception;
|
|
||||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
|
||||||
UniTask<bool>.Awaiter awaiter;
|
|
||||||
|
|
||||||
public _TakeUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, CancellationToken cancellationToken1)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.cancellationToken1 = cancellationToken1;
|
|
||||||
|
|
||||||
if (cancellationToken1.CanBeCanceled)
|
|
||||||
{
|
|
||||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 3);
|
|
||||||
|
|
||||||
RunOther(other).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TSource Current { get; private set; }
|
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
return CompletedTasks.False;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exception != null)
|
|
||||||
{
|
|
||||||
return UniTask.FromException<bool>(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken1.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return UniTask.FromCanceled<bool>(cancellationToken1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enumerator == null)
|
|
||||||
{
|
|
||||||
enumerator = source.GetAsyncEnumerator(cancellationToken1);
|
|
||||||
}
|
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
SourceMoveNext();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SourceMoveNext()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
|
||||||
if (awaiter.IsCompleted)
|
|
||||||
{
|
|
||||||
MoveNextCore(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MoveNextCore(object state)
|
|
||||||
{
|
|
||||||
var self = (_TakeUntil)state;
|
|
||||||
|
|
||||||
if (self.TryGetResult(self.awaiter, out var result))
|
|
||||||
{
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (self.exception != null)
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetException(self.exception);
|
|
||||||
}
|
|
||||||
else if (self.cancellationToken1.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.Current = self.enumerator.Current;
|
|
||||||
self.completionSource.TrySetResult(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.completionSource.TrySetResult(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async UniTaskVoid RunOther(UniTask other)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await other;
|
|
||||||
completed = true;
|
|
||||||
completionSource.TrySetResult(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exception = ex;
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnCanceled1(object state)
|
|
||||||
{
|
|
||||||
var self = (_TakeUntil)state;
|
|
||||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask DisposeAsync()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
cancellationTokenRegistration1.Dispose();
|
|
||||||
if (enumerator != null)
|
|
||||||
{
|
|
||||||
return enumerator.DisposeAsync();
|
|
||||||
}
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 12bda324162f15349afefc2c152ac07f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -19,6 +19,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// UnityEngine.Debug.Log("Called ToArray");
|
||||||
|
|
||||||
var pool = ArrayPool<TSource>.Shared;
|
var pool = ArrayPool<TSource>.Shared;
|
||||||
var array = pool.Rent(16);
|
var array = pool.Rent(16);
|
||||||
|
|
||||||
|
|
|
@ -248,18 +248,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (queuedResult)
|
if (queuedResult.Count != 0)
|
||||||
{
|
{
|
||||||
if (queuedResult.Count != 0)
|
current = queuedResult.Dequeue();
|
||||||
{
|
useCachedCurrent = true;
|
||||||
current = queuedResult.Dequeue();
|
return current;
|
||||||
useCachedCurrent = true;
|
}
|
||||||
return current;
|
else
|
||||||
}
|
{
|
||||||
else
|
return default; // undefined.
|
||||||
{
|
|
||||||
return default; // undefined.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,49 +4,36 @@ 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;
|
|
||||||
|
|
||||||
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 +43,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();
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
completionSource.Reset();
|
||||||
{
|
|
||||||
completionSource.TrySetCanceled(cancellationToken);
|
|
||||||
}
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +54,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
cancellationTokenRegistration.Dispose();
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -80,13 +62,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,16 +179,8 @@ 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)
|
||||||
{
|
{
|
||||||
first = false;
|
first = false;
|
||||||
|
@ -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,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || !target.TryGetTarget(out var t))
|
UnityEngine.Debug.Log("TRY_RESULT:" + target.TryGetTarget(out var _));
|
||||||
|
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
|
||||||
{
|
{
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue