diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..def5ba5d90b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/compute-entropy.py b/.github/workflows/compute-entropy.py new file mode 100644 index 00000000000..42655913bb3 --- /dev/null +++ b/.github/workflows/compute-entropy.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +import sys, math, json, subprocess +from collections import Counter +from pathlib import Path + +def shannon_entropy(text: str) -> float: + if not text or len(text) < 10: + return 0.0 + freq = Counter(text) + probs = [count / len(text) for count in freq.values()] + return -sum(p * math.log2(p) for p in probs if p > 0) + +# Get changed files safely for pull_request events +changed_files = [] +try: + # GitHub provides github.event.pull_request.base.sha and head.sha in the context + base_sha = subprocess.check_output(['git', 'rev-parse', 'origin/${{ github.base_ref }}'], text=True).strip() + changed_files = subprocess.check_output( + ['git', 'diff', '--name-only', base_sha, 'HEAD'], text=True + ).splitlines() +except subprocess.CalledProcessError: + # Fallback for first-time PRs or edge cases: use the merge-base or just files in HEAD + try: + changed_files = subprocess.check_output( + ['git', 'diff', '--name-only', 'HEAD~1', 'HEAD'], text=True + ).splitlines() + except subprocess.CalledProcessError: + # Last resort: all files in the repo + changed_files = subprocess.check_output(['git', 'ls-files'], text=True).splitlines() + +results = [] +total_ent = 0.0 +count = 0 + +for f in changed_files: + path = Path(f.strip()) + if not path.exists() or path.suffix in {'.png', '.jpg', '.gif', '.bin', '.lock', '.exe', '.dll', '.so'}: + continue + try: + content = path.read_text(encoding='utf-8', errors='ignore') + ent = shannon_entropy(content) + results.append(f"{f}: {ent:.3f}") + total_ent += ent + count += 1 + except Exception: + pass + +avg = round(total_ent / count, 3) if count > 0 else 0.0 + +verdict = ( + "✅ Mid-4 beauty detected (thoughtful human code!)" if 4.3 <= avg <= 4.7 else + "⚠️ Consider review — entropy outside sweet spot" if avg > 0 else + "No source files changed" +) + +with open('/tmp/beauty.json', 'w') as f: + json.dump({ + "average_entropy": avg, + "verdict": verdict, + "files": results[:20] + }, f, indent=2) + +print(f"Average entropy: {avg}") +print(verdict) diff --git a/.github/workflows/entropy-beauty-scan.yml b/.github/workflows/entropy-beauty-scan.yml new file mode 100644 index 00000000000..0923ba510d0 --- /dev/null +++ b/.github/workflows/entropy-beauty-scan.yml @@ -0,0 +1,123 @@ +name: Entropy Beauty + TruffleHog Scan + +on: [push, release, pull_request, pull_request_target] + +permissions: + contents: read + pull-requests: write + issues: write # must be at workflow level for push/merge events + +jobs: + scan: + runs-on: ubuntu-latest + steps: + - name: Checkout code (full history) + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Run TruffleHog + uses: trufflesecurity/trufflehog@main + with: + path: . + extra_args: --results=verified,unknown --filter-entropy=3.5 --json + + - name: Compute mid-4 beauty entropy + run: python .github/workflows/compute-entropy.py + + - name: Post summary comment (PR only) + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: actions/github-script@v8 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + + // Read TruffleHog output — it prints one JSON object per line (NDJSON) + let findings = []; + if (fs.existsSync('trufflehog.json')) { + try { + const lines = fs.readFileSync('trufflehog.json', 'utf8').trim().split('\n'); + findings = lines.map(line => { + try { return JSON.parse(line); } catch(e) { return null; } + }).filter(Boolean); + } catch(e) {} + } else { + // Fallback: the action also logs to GITHUB_STEP_SUMMARY, but we use the file from the Python step + console.log("No trufflehog.json found, using empty findings"); + } + + const beauty = JSON.parse(fs.readFileSync('/tmp/beauty.json', 'utf8')); + + let body = `## 🐷 TruffleHog + Entropy Beauty Scan\n\n`; + body += `**Average entropy of changed code:** ${beauty.average_entropy} bits/char\n`; + body += `**Verdict:** ${beauty.verdict}\n\n`; + + if (beauty.files && beauty.files.length) { + body += `**Changed files entropy:**\n\`\`\`\n${beauty.files.join('\n')}\n\`\`\`\n\n`; + } + + if (findings.length > 0) { + body += `⚠️ **TruffleHog found ${findings.length} potential issue(s)**\n`; + } else { + body += `✅ No secrets or suspicious high-entropy strings found.\n`; + } + + body += `\n*Mid-4 beauty heuristic in action — powered by our entropy chats! 😊*`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); + # ── Create issue on push ONLY if suspicious (entropy outside 4.3–4.7) ── + - name: Create issue on suspicious push + if: github.event_name == 'push' || github.event_name == 'release' + uses: actions/github-script@v8 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const beauty = JSON.parse(fs.readFileSync('/tmp/beauty.json', 'utf8')); + + // Only create issue if it's NOT beautiful mid-4 + if (beauty.average_entropy >= 4.3 && beauty.average_entropy <= 4.7) { + console.log("✅ Mid-4 beauty — no issue created"); + return; + } + + let findings = []; + if (fs.existsSync('trufflehog.json')) { + try { + const lines = fs.readFileSync('trufflehog.json', 'utf8').trim().split('\n'); + findings = lines.map(line => { + try { return JSON.parse(line); } catch(e) { return null; } + }).filter(Boolean); + } catch(e) {} + } + + let body = `**Average entropy:** ${beauty.average_entropy} bits/char\n\n`; + body += `**Verdict:** ${beauty.verdict}\n\n`; + + if (beauty.files && beauty.files.length) { + body += `**Changed files:**\n\`\`\`\n${beauty.files.join('\n')}\n\`\`\`\n\n`; + } + + if (findings.length > 0) { + body += `**TruffleHog found ${findings.length} potential issue(s)**\n`; + } else { + body += `✅ No secrets or suspicious high-entropy strings found.\n`; + } + + body += `\n*Triggered by push to \`${context.sha}\` — mid-4 beauty heuristic*`; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `🚨 Suspicious entropy detected in recent push (${beauty.average_entropy})`, + body: body, + labels: ['entropy', 'security', 'review-needed'] + }); + + console.log("⚠️ Created issue because entropy was outside mid-4 range"); diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 405a2b30659..4174da20727 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -1,10 +1,13 @@ name: "Validate Gradle Wrapper" on: [push, pull_request] +permissions: + contents: read + jobs: validation: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: gradle/wrapper-validation-action@v1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: gradle/wrapper-validation-action@f9c9c575b8b21b6485636a91ffecd10e558c62f6 # v3.5.0 diff --git a/.github/workflows/gradle_branch.yml b/.github/workflows/gradle_branch.yml new file mode 100644 index 00000000000..ef7ad91cc20 --- /dev/null +++ b/.github/workflows/gradle_branch.yml @@ -0,0 +1,37 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Branch + +on: + push: + branches-ignore: [ '3.x' ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'zulu' + java-version: '11' + - name: Cache Gradle packages + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }} + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build RxJava + run: ./gradlew build --stacktrace + - name: Upload to Codecov + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + - name: Generate Javadoc + run: ./gradlew javadoc --stacktrace diff --git a/.github/workflows/gradle_jdk11.yml b/.github/workflows/gradle_jdk11.yml new file mode 100644 index 00000000000..8eab1cf14a3 --- /dev/null +++ b/.github/workflows/gradle_jdk11.yml @@ -0,0 +1,42 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: JDK 11 + +on: + push: + branches: [ 3.x ] + pull_request: + branches: [ 3.x ] + +permissions: + contents: read + +env: + BUILD_WITH_11: true + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'zulu' + java-version: '11' + - name: Cache Gradle packages + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-1-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-1- + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Verify generated module-info + run: ./gradlew -PjavaCompatibility=9 jar + - name: Build RxJava + run: ./gradlew build --stacktrace +# - name: Generate Javadoc +# run: ./gradlew javadoc --stacktrace diff --git a/.github/workflows/gradle_pr.yml b/.github/workflows/gradle_pr.yml new file mode 100644 index 00000000000..815b14d9631 --- /dev/null +++ b/.github/workflows/gradle_pr.yml @@ -0,0 +1,37 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Pull Request + +on: + pull_request: + branches: [ 3.x ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'zulu' + java-version: '11' + - name: Cache Gradle packages + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-1-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-1- + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build RxJava + run: ./gradlew build --stacktrace + - name: Upload to Codecov + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + - name: Generate Javadoc + run: ./gradlew javadoc --stacktrace diff --git a/.github/workflows/gradle_release.yml b/.github/workflows/gradle_release.yml new file mode 100644 index 00000000000..3d3ddc27f25 --- /dev/null +++ b/.github/workflows/gradle_release.yml @@ -0,0 +1,70 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Release + +on: + release: + types: [ released, prereleased ] + branches: [ '3.x' ] + tags: + - 'v3.*.*' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: write + env: + CI_BUILD_NUMBER: ${{ github.run_number }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'zulu' + java-version: '11' + - name: Cache Gradle packages + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }} + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Grant execute permission for push + run: chmod +x push_javadoc.sh + - name: Extract version tag + run: echo "BUILD_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV + - name: Build RxJava + run: ./gradlew build --stacktrace --no-daemon + - name: Upload to Codecov + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 +# - name: Upload release +# run: ./gradlew -PreleaseMode=full publish --no-daemon --no-parallel --stacktrace +# env: +# # Define secrets at https://github.com/ReactiveX/RxJava/settings/secrets/actions +# # ------------------------------------------------------------------------------ +# ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USER }} +# ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} +# ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_PRIVATE_KEY }} +# ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + - name: Publish release + run: ./gradlew -PreleaseMode=full publishAndReleaseToMavenCentral --no-configuration-cache --no-daemon --no-parallel --stacktrace + env: + # Define secrets at https://github.com/ReactiveX/RxJava/settings/secrets/actions + # ------------------------------------------------------------------------------ + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} + ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_PRIVATE_KEY }} + ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + - name: Push Javadoc + run: ./push_javadoc.sh + env: + # Define secrets at https://github.com/ReactiveX/RxJava/settings/secrets/actions + # ------------------------------------------------------------------------------ + JAVADOCS_TOKEN: ${{ secrets.JAVADOCS_TOKEN }} diff --git a/.github/workflows/gradle_snapshot.yml b/.github/workflows/gradle_snapshot.yml new file mode 100644 index 00000000000..e56c9019aad --- /dev/null +++ b/.github/workflows/gradle_snapshot.yml @@ -0,0 +1,56 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Snapshot + +on: + push: + branches: [ '3.x' ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + if: github.repository == 'ReactiveX/RxJava' + permissions: + contents: write + env: + # ------------------------------------------------------------------------------ + CI_BUILD_NUMBER: ${{ github.run_number }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'zulu' + java-version: '11' + - name: Cache Gradle packages + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle-${{ secrets.CACHE_VERSION }} + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Grant execute permission for push + run: chmod +x push_javadoc.sh + - name: Build RxJava + run: ./gradlew build --stacktrace --no-daemon + - name: Upload Snapshot + run: ./gradlew -PreleaseMode=branch publishAllPublicationsToMavenCentralRepository --no-daemon --no-parallel --stacktrace + env: + # Define secrets at https://github.com/ReactiveX/RxJava/settings/secrets/actions + # ------------------------------------------------------------------------------ + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} + - name: Upload to Codecov + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + - name: Push Javadoc + run: ./push_javadoc.sh + # Define secrets at https://github.com/ReactiveX/RxJava/settings/secrets/actions + # ------------------------------------------------------------------------------ + env: + JAVADOCS_TOKEN: ${{ secrets.JAVADOCS_TOKEN }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000000..26a487cffea --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,59 @@ +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '43 12 * * 4' + push: + branches: [ "3.x" ] + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if + # you want to enable the Branch-Protection check on a *public* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.29.5 + with: + sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 428d55b2fb3..b60171cf2df 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,10 @@ bin/ # PMD files .pmd .ruleset -test-output/ \ No newline at end of file +test-output/ + +# Checkstyle local config +.checkstyle + +# Some editor's config +.editorconfig diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000000..954870bba66 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,139 @@ +## Learn more about this file at 'https://www.gitpod.io/docs/references/gitpod-yml' +## +## This '.gitpod.yml' file when placed at the root of a project instructs +## Gitpod how to prepare & build the project, start development environments +## and configure continuous prebuilds. Prebuilds when enabled builds a project +## like a CI server so you can start coding right away - no more waiting for +## dependencies to download and builds to finish when reviewing pull-requests +## or hacking on something new. +## +## With Gitpod you can develop software from any device (even iPads) via +## desktop or browser based versions of VS Code or any JetBrains IDE and +## customise it to your individual needs - from themes to extensions, you +## have full control. +## +## The easiest way to try out Gitpod is install the browser extenion: +## 'https://www.gitpod.io/docs/browser-extension' or by prefixing +## 'https://gitpod.io#' to the source control URL of any project. +## +## For example: 'https://gitpod.io#https://github.com/gitpod-io/gitpod' + + +## The 'image' section defines which Docker image Gitpod should use. +## By default, Gitpod uses a standard Docker Image called 'workspace-full' +## which can be found at 'https://github.com/gitpod-io/workspace-images' +## +## Workspaces started based on this default image come pre-installed with +## Docker, Go, Java, Node.js, C/C++, Python, Ruby, Rust, PHP as well as +## tools such as Homebrew, Tailscale, Nginx and several more. +## +## If this image does not include the tools needed for your project then +## a public Docker image or your own Docker file can be configured. +## +## Learn more about images at 'https://www.gitpod.io/docs/config-docker' + +#image: node:buster # use 'https://hub.docker.com/_/node' +# +#image: # leave image undefined if using a Dockerfile +# file: .gitpod.Dockerfile # relative path to the Dockerfile from the +# # root of the project + +## The 'tasks' section defines how Gitpod prepares and builds this project +## or how Gitpod can start development servers. With Gitpod, there are three +## types of tasks: +## +## - before: Use this for tasks that need to run before init and before command. +## - init: Use this to configure prebuilds of heavy-lifting tasks such as +## downloading dependencies or compiling source code. +## - command: Use this to start your database or application when the workspace starts. +## +## Learn more about these tasks at 'https://www.gitpod.io/docs/config-start-tasks' + +#tasks: +# - before: | +# # commands to execute... +# +# - init: | +# # sudo apt-get install python3 # can be used to install operating system +# # dependencies but these are not kept after the +# # prebuild completes thus Gitpod recommends moving +# # operating system dependency installation steps +# # to a custom Dockerfile to make prebuilds faster +# # and to keep your codebase DRY. +# # 'https://www.gitpod.io/docs/config-docker' +# +# # pip install -r requirements.txt # install codebase dependencies +# # cmake # precompile codebase +# +# - name: Web Server +# openMode: split-left +# env: +# WEBSERVER_PORT: 8080 +# command: | +# python3 -m http.server $WEBSERVER_PORT +# +# - name: Web Browser +# openMode: split-right +# env: +# WEBSERVER_PORT: 8080 +# command: | +# gp await-port $WEBSERVER_PORT +# lynx `gp url` + +tasks: + - command: ./gradlew build + +## The 'ports' section defines various ports your may listen on are +## configured in Gitpod on an authenticated URL. By default, all ports +## are in private visibility state. +## +## Learn more about ports at 'https://www.gitpod.io/docs/config-ports' + +#ports: +# - port: 8080 # alternatively configure entire ranges via '8080-8090' +# visibility: private # either 'public' or 'private' (default) +# onOpen: open-browser # either 'open-browser', 'open-preview' or 'ignore' + + +## The 'vscode' section defines a list of Visual Studio Code extensions from +## the OpenVSX.org registry to be installed upon workspace startup. OpenVSX +## is an open alternative to the proprietary Visual Studio Code Marketplace +## and extensions can be added by sending a pull-request with the extension +## identifier to https://github.com/open-vsx/publish-extensions +## +## The identifier of an extension is always ${publisher}.${name}. +## +## For example: 'vscodevim.vim' +## +## Learn more at 'https://www.gitpod.io/docs/ides-and-editors/vscode' + +#vscode: +# extensions: +# - vscodevim.vim +# - esbenp.prettier-vscode@9.5.0 +# - https://example.com/abc/releases/extension-0.26.0.vsix + + +## The 'github' section defines configuration of continuous prebuilds +## for GitHub repositories when the GitHub application +## 'https://github.com/apps/gitpod-io' is installed in GitHub and granted +## permissions to access the repository. +## +## Learn more at 'https://www.gitpod.io/docs/prebuilds' + +github: + prebuilds: + # enable for the default branch + master: true + # enable for all branches in this repo + branches: true + # enable for pull requests coming from this repo + pullRequests: true + # enable for pull requests coming from forks + pullRequestsFromForks: true + # add a check to pull requests + addCheck: true + # add a "Review in Gitpod" button as a comment to pull requests + addComment: false + # add a "Review in Gitpod" button to the pull request's description + addBadge: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6e595b4e930..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: java -jdk: -- openjdk8 - -# prevent travis running gradle assemble; let the build script do it anyway -install: true - -# running in container causes test failures and 2x-3x longer build, use standalone instances -sudo: required - -# script for build and release via Travis to Bintray -script: gradle/buildViaTravis.sh - -# Code coverage -after_success: - - bash <(curl -s --retry 10 https://codecov.io/bash) - - bash gradle/push_javadoc.sh - -# cache between builds -cache: - directories: - - $HOME/.m2 - - $HOME/.gradle -env: - global: - - secure: YcLpYfNc/dyDON+oDvnJK5pFNhpPeJHxlAHV8JBt42e51prAl6njqrg1Qlfdp0pvBiskTPQHUxbFy9DOB1Z+43lPj5vlqz6qBgtS3vtBnsrczr+5Xx7NTdVKq6oZGl45VjfNPT7zdM6GQ5ifdzOid6kJIFu34g9JZkCzOY3BWGM= - - secure: WVmfSeW1UMNdem7+X4cVDjkEkqdeNavYH4udn3bFN1IFaWdliWFp4FYVBVi+p1T/IgkRSqzoW9Bm43DABe1UMFoErFCbfd7B0Ofgb4NZAsxFgokHGVLCe6k5+rQyASseiO7k0itSj3Kq9TrDueKPhv+g+IG0w1A8yZTnXdhXHvY= - - secure: Xt8E09nmSr+5r7ly95hG/EiBitZbhFGPRGp8oqPkNn1A2fzG9+hnvlNLgQhVPsISZGzJwkWa3LGBxAVGmuysVOz7eCwkoqlDZaaSLYAPfWXqkr+cmYGPkErgHSp+n/hnQG4TylX0YxzqX8flr6db21zWyNduiyHmo+xFydI5LeM= - - secure: RmpIsmYa5BdLLWR6DILjhEE/dx2q3O0NIkvnMx5G1cyRCNCrOf1B7fYFHnsTDwpvRA+6H6dZinmeyf6D3G+czOG5q/TW2jcu5nh+YOLhBb6jPIqRDfq/WHAa5Lkdssxs5g9RdWlEDVFMoE62lGc4cnfJz5F5puH29dy2SvXxIQw= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4547f563a86..c1f0974f79c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,22 @@ If you would like to contribute code you can do so through GitHub by forking the When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. +## AI contributions + +We are not against contributions from AI tools, LLM-based or future architectures. However, you as a human are responsible for its contributions and suggestions. + +This means, you have to make sure it doesn't hallucinate issues or elements of the contribution, doesn't try to hack rewards or hack established unit tests, doesn't go wild +and rearchitect established components. + +If you post a contribution that is broken, we will not argue with your LLM or prompt engineer for you. You are responsible for having the the LLM's output work within the confines +of this project. + +Please also be aware that this project is large both in current and historical sense with some rules not documented or enforced by unit tests. This is because such unwritten rules +were trivial or readily inferrable by humans in the past. The project predates LLMs several years and thus is not organized to be accessible by LLMs today. Nor should it be. + +Consequently, the amount of prompting and the context window size to include all possible information about it could become so much that it can become prohibitively expensive to have +an LLM come up with more than basic and trivial contributions. Needless to say, don't bankrupt yourself and don't just accept the LLM's output at face value. + ## License By contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/ReactiveX/RxJava/blob/3.x/LICENSE @@ -13,19 +29,16 @@ All files are released with the Apache 2.0 license. If you are adding a new file it should have a header like this: ``` -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ ``` diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000000..5d2c6e53f3c --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,13 @@ +Copyright (c) 2016-present, RxJava Contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index 698aa96f40d..5276c0bd375 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # RxJava: Reactive Extensions for the JVM - + [![codecov.io](http://codecov.io/github/ReactiveX/RxJava/coverage.svg?branch=3.x)](https://codecov.io/gh/ReactiveX/RxJava/branch/3.x) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.reactivex.rxjava3/rxjava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.reactivex.rxjava3/rxjava) +[![Maven Central](https://maven-badges.sml.io/sonatype-central/io.reactivex.rxjava3/rxjava/badge.svg)](https://maven-badges.sml.io/sonatype-central/io.reactivex.rxjava3/rxjava) +[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/ReactiveX/RxJava) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/ReactiveX/RxJava/badge)](https://securityscorecards.dev/viewer/?uri=github.com/ReactiveX/RxJava) RxJava is a Java VM implementation of [Reactive Extensions](http://reactivex.io): a library for composing asynchronous and event-based programs by using observable sequences. @@ -10,22 +12,27 @@ It extends the [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern) #### Version 3.x ([Javadoc](http://reactivex.io/RxJava/3.x/javadoc/)) -- single dependency: [Reactive-Streams](https://github.com/reactive-streams/reactive-streams-jvm) -- Java 8+ ([Android](https://github.com/ReactiveX/RxAndroid) desugar friendly) -- Java 8 lambda-friendly API -- fixed API mistakes and many limits of RxJava 2 -- intended to be a replacement for RxJava 2 with relatively few binary incompatible changes -- non-opinionated about the source of concurrency (threads, pools, event loops, fibers, actors, etc.) -- async or synchronous execution -- virtual time and schedulers for parameterized concurrency -- test and diagnostic support via test schedulers, test consumers and plugin hooks +- Single dependency: [Reactive-Streams](https://github.com/reactive-streams/reactive-streams-jvm). +- Java 8+ or Android API 21+ required. +- Java 8 lambda-friendly API. +- [Android](https://github.com/ReactiveX/RxAndroid) desugar friendly. +- Fixed API mistakes and many limits of RxJava 2. +- Intended to be a replacement for RxJava 2 with relatively few binary incompatible changes. +- Non-opinionated about the source of concurrency (threads, pools, event loops, fibers, actors, etc.). +- Async or synchronous execution. +- Virtual time and schedulers for parameterized concurrency. +- Test and diagnostic support via test schedulers, test consumers and plugin hooks. +- Interop with newer JDK versions via 3rd party libraries, such as + - [Java 9 Flow API](https://github.com/akarnokd/RxJavaJdk9Interop#rxjavajdk9interop) + - [Java 21 Virtual Threads](https://github.com/akarnokd/RxJavaFiberInterop#rxjavafiberinterop) Learn more about RxJava in general on the Wiki Home. +:information_source: Please read the [What's different in 3.0](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-3.0) for details on the changes and migration information when upgrading from 2.x. + #### Version 2.x -The [2.x version](https://github.com/ReactiveX/RxJava/tree/2.x) will be supported with bugfixes and important documentation updates until -**December 31, 2020**. No new features will be added to 2.x. +The [2.x version](https://github.com/ReactiveX/RxJava/tree/2.x) is end-of-life as of **February 28, 2021**. No further development, support, maintenance, PRs and updates will happen. The [Javadoc]([Javadoc](http://reactivex.io/RxJava/2.x/javadoc/)) of the very last version, **2.2.21**, will remain accessible. #### Version 1.x @@ -41,7 +48,7 @@ The first step is to include RxJava 3 into your project, for example, as a Gradl implementation "io.reactivex.rxjava3:rxjava:3.x.y" ``` -(Please replace `x` and `y` with the latest version numbers: [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.reactivex.rxjava3/rxjava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.reactivex.rxjava3/rxjava) +(Please replace `x` and `y` with the latest version numbers: [![Maven Central](https://maven-badges.sml.io/sonatype-central/io.reactivex.rxjava3/rxjava/badge.svg)](https://maven-badges.sml.io/sonatype-central/io.reactivex.rxjava3/rxjava) ) ### Hello World @@ -194,7 +201,7 @@ RxJava operators don't work with `Thread`s or `ExecutorService`s directly but wi - `Schedulers.single()`: Run work on a single thread in a sequential and FIFO manner. - `Schedulers.trampoline()`: Run work in a sequential and FIFO manner in one of the participating threads, usually for testing purposes. -These are available on all JVM platforms but some specific platforms, such as Android, have their own typical `Scheduler`s defined: `AndroidSchedulers.mainThread()`, `SwingScheduler.instance()` or `JavaFXSchedulers.gui()`. +These are available on all JVM platforms but some specific platforms, such as Android, have their own typical `Scheduler`s defined: `AndroidSchedulers.mainThread()`, `SwingScheduler.instance()` or `JavaFXScheduler.platform()`. In addition, there is an option to wrap an existing `Executor` (and its subtypes such as `ExecutorService`) into a `Scheduler` via `Schedulers.from(Executor)`. This can be used, for example, to have a larger but still fixed pool of threads (unlike `computation()` and `io()` respectively). @@ -503,7 +510,7 @@ For further details, consult the [wiki](https://github.com/ReactiveX/RxJava/wiki - Google Group: [RxJava](http://groups.google.com/d/forum/rxjava) - Twitter: [@RxJava](http://twitter.com/RxJava) - [GitHub Issues](https://github.com/ReactiveX/RxJava/issues) -- StackOverflow: [rx-java](http://stackoverflow.com/questions/tagged/rx-java) and [rx-java2](http://stackoverflow.com/questions/tagged/rx-java2) +- StackOverflow: [rx-java](http://stackoverflow.com/questions/tagged/rx-java), [rx-java2](http://stackoverflow.com/questions/tagged/rx-java2) and [rx-java3](http://stackoverflow.com/questions/tagged/rx-java3) - [Gitter.im](https://gitter.im/ReactiveX/RxJava) ## Versioning @@ -524,7 +531,7 @@ APIs marked with the [`@Experimental`][experimental source link] annotation at t #### @Deprecated -APIs marked with the `@Deprecated` annotation at the class or method level will remain supported until the next major release but it is recommended to stop using them. +APIs marked with the `@Deprecated` annotation at the class or method level will remain supported until the next major release, but it is recommended to stop using them. #### io.reactivex.rxjava3.internal.* @@ -564,19 +571,19 @@ and for Ivy: ### Snapshots -Snapshots are available via https://oss.jfrog.org/libs-snapshot/io/reactivex/rxjava3/rxjava/ +Snapshots after May 19st, 2025 are available via https://central.sonatype.com/repository/maven-snapshots/io/reactivex/rxjava3/rxjava/ ```groovy repositories { - maven { url 'https://oss.jfrog.org/libs-snapshot' } + maven { url 'https://central.sonatype.com/repository/maven-snapshots' } } dependencies { - compile 'io.reactivex.rxjava3:rxjava:3.0.0-SNAPSHOT' + implementation 'io.reactivex.rxjava3:rxjava:3.0.0-SNAPSHOT' } ``` -JavaDoc snapshots are available at http://reactivex.io/RxJava/3.x/javadoc/snapshot +JavaDoc snapshots are available at https://reactivex.io/RxJava/3.x/javadoc/snapshot ## Build @@ -611,5 +618,5 @@ For bugs, questions and discussions please use the [Github Issues](https://githu See the License for the specific language governing permissions and limitations under the License. -[beta source link]: https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/annotations/Beta.java -[experimental source link]: https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/annotations/Experimental.java +[beta source link]: https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/rxjava3/annotations/Beta.java +[experimental source link]: https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/rxjava3/annotations/Experimental.java diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..10035743316 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/ReactiveX/RxJava/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. diff --git a/build.gradle b/build.gradle index b0a12f1c790..8bcfddb7175 100644 --- a/build.gradle +++ b/build.gradle @@ -1,76 +1,39 @@ -buildscript { - - // Dependency versions - // --------------------------------------- - - ext.reactiveStreamsVersion = "1.0.3" - ext.junitVersion = "4.13" - ext.testNgVersion = "7.0.0" - ext.mockitoVersion = "3.2.4" - ext.jmhLibVersion = "1.21" - ext.jmhGradleVersion = "0.5.0" - ext.guavaVersion = "28.2-jre" - ext.jacocoVersion = "0.8.4" - ext.animalSnifferVersion = "1.5.0" - ext.licenseVersion = "0.15.0" - ext.bintrayVersion = "1.8.4" - ext.jfrogExtractorVersion = "4.13.0" - ext.bndVersion = "5.0.0" - ext.checkstyleVersion = "8.26" - - // -------------------------------------- - - repositories { - jcenter() - mavenCentral() - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath "ru.vyarus:gradle-animalsniffer-plugin:$animalSnifferVersion" - classpath "gradle.plugin.com.hierynomus.gradle.plugins:license-gradle-plugin:$licenseVersion" - classpath "me.champeau.gradle:jmh-gradle-plugin:$jmhGradleVersion" - classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$bintrayVersion" - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$jfrogExtractorVersion" - classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:$bndVersion" - } -} - -group = "io.reactivex.rxjava3" -ext.githubProjectName = "rxjava" - -version = project.properties["release.version"] - -def releaseTag = System.getenv("TRAVIS_TAG"); +plugins { + id("java-library") + id("checkstyle") + id("eclipse") + id("jacoco") + id("maven-publish") + id("ru.vyarus.animalsniffer") version "2.0.1" + id("me.champeau.jmh") version "0.7.3" + id("com.github.hierynomus.license") version "0.16.1" + id("biz.aQute.bnd.builder") version "6.4.0" + id("com.vanniktech.maven.publish") version "0.33.0" + id("org.beryx.jar") version "2.0.0" + id("signing") +} + +ext { + reactiveStreamsVersion = "1.0.4" + junitVersion = "4.13.2" + testNgVersion = "7.5" + mockitoVersion = "4.11.0" + jmhLibVersion = "1.21" + guavaVersion = "33.5.0-jre" +} + +def releaseTag = System.getenv("BUILD_TAG") if (releaseTag != null && !releaseTag.isEmpty()) { if (releaseTag.startsWith("v")) { - releaseTag = releaseTag.substring(1); + releaseTag = releaseTag.substring(1) } - version = releaseTag; - project.properties.put("release.version", releaseTag); + project.version = releaseTag - println("Releasing with version " + version); + logger.lifecycle("Releasing with version: " + project.version) } -description = "RxJava: Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM." - -apply plugin: "java-library" -apply plugin: "checkstyle" -apply plugin: "jacoco" -apply plugin: "ru.vyarus.animalsniffer" -apply plugin: "maven" -apply plugin: "me.champeau.gradle.jmh" -apply plugin: "com.github.hierynomus.license" -apply plugin: "com.jfrog.bintray" -apply plugin: "com.jfrog.artifactory" -apply plugin: "eclipse" - -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 - repositories { - mavenCentral() + mavenCentral() } dependencies { @@ -87,12 +50,27 @@ dependencies { testImplementation "com.google.guava:guava:$guavaVersion" } +def buildWith11 = System.getenv("BUILD_WITH_11") +java { + toolchain { + vendor = JvmVendorSpec.ADOPTIUM + if ("true".equals(buildWith11)) { + languageVersion = JavaLanguageVersion.of(11) + } else { + languageVersion = JavaLanguageVersion.of(8) + } + } + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + tasks.withType(JavaCompile) { - options.compilerArgs << "-parameters"; + options.compilerArgs << "-parameters" } +apply from: file("gradle/javadoc_cleanup.gradle") + javadoc { - failOnError = false exclude "**/internal/**" exclude "**/test/**" exclude "**/perf/**" @@ -104,111 +82,57 @@ javadoc { options.addStringOption("top").value = "" options.addStringOption("doctitle").value = "" options.addStringOption("header").value = "" - options.stylesheetFile = new File(projectDir, "gradle/stylesheet.css"); + options.stylesheetFile = project.file("gradle/stylesheet.css") options.links( - "https://docs.oracle.com/javase/8/docs/api/", - "http://www.reactive-streams.org/reactive-streams-${reactiveStreamsVersion}-javadoc/" + "https://docs.oracle.com/javase/8/docs/api/", + "https://reactivex.io/RxJava/org.reactivestreams.javadoc/${reactiveStreamsVersion}/" ) + + finalizedBy javadocCleanup } animalsniffer { annotation = "io.reactivex.rxjava3.internal.util.SuppressAnimalSniffer" } -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = "sources" - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = "javadoc" - from javadoc.destinationDir -} - -artifacts { - archives jar - archives sourcesJar - archives javadocJar +moduleConfig { + moduleInfoPath = 'src/main/module/module-info.java' + multiReleaseVersion = 9 + version = project.version } -apply plugin: 'biz.aQute.bnd.builder' - jar { - bnd ('Bundle-Name': 'rxjava', - 'Bundle-Vendor': 'RxJava Contributors', - 'Bundle-Description': 'Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.', - 'Import-Package': '!org.junit,!junit.framework,!org.mockito.*,!org.testng.*,*', - 'Bundle-DocURL': 'https://github.com/ReactiveX/RxJava', - 'Eclipse-ExtensibleAPI': 'true', - 'Automatic-Module-Name': 'io.reactivex.rxjava3', - 'Export-Package': '!io.reactivex.rxjava3.internal.*, io.reactivex.rxjava3.*' + from('.') { + include 'LICENSE' + include 'COPYRIGHT' + into('META-INF/') + } + exclude("module-info.class") + + // Cover for bnd still not supporting MR Jars: https://github.com/bndtools/bnd/issues/2227 + bnd('-fixupmessages': '^Classes found in the wrong directory: \\\\{META-INF/versions/9/module-info\\\\.class=module-info}$') + bnd( + "Bundle-Name": "rxjava", + "Bundle-Vendor": "RxJava Contributors", + "Bundle-Description": "Reactive Extensions for the JVM - a library for composing asynchronous and event-based programs using observable sequences for the Java VM.", + "Import-Package": "!org.junit,!junit.framework,!org.mockito.*,!org.testng.*,*", + "Bundle-DocURL": "https://github.com/ReactiveX/RxJava", + "Eclipse-ExtensibleAPI": "true", + "Export-Package": "!io.reactivex.rxjava3.internal.*, io.reactivex.rxjava3.*", + "Bundle-SymbolicName": "io.reactivex.rxjava3.rxjava", + "Multi-Release": "true" ) } license { - header rootProject.file("HEADER") + header project.file("config/license/HEADER") ext.year = Calendar.getInstance().get(Calendar.YEAR) skipExistingHeaders true ignoreFailures true excludes(["**/*.md", "**/*.txt"]) } -apply plugin: "maven-publish" - -install { - repositories.mavenInstaller.pom.project { - name "RxJava" - description "Reactive Extensions for Java" - url "https://github.com/ReactiveX/RxJava" - licenses { - license { - name "The Apache Software License, Version 2.0" - url "http://www.apache.org/licenses/LICENSE-2.0.txt" - distribution "repo" - } - } - developers { - developer { - id "akarnokd" - name "David Karnok" - email "akarnokd@gmail.com" - } - } - scm { - connection "scm:git:git@github.com:ReactiveX/RxJava.git" - url "scm:git:git@github.com:ReactiveX/RxJava.git" - developerConnection "scm:git:git@github.com:ReactiveX/RxJava.git" - } - issueManagement { - system "github" - url "https://github.com/ReactiveX/RxJava/issues" - } - } -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact (sourcesJar) { - classifier = "sources" - } - } - } -} - -// Reactive-Streams as compile dependency -publishing.publications.all { - pom.withXml { - asNode().dependencies."*".findAll() { - it.scope.text() == "runtime" && project.configurations.compile.allDependencies.find { dep -> - dep.name == it.artifactId.text() - } - }.each { it.scope*.value = "compile"} - } -} - jmh { jmhVersion = jmhLibVersion humanOutputFile = null @@ -217,162 +141,79 @@ jmh { jvmArgsAppend = ["-Djmh.separateClasspathJAR=true"] if (project.hasProperty("jmh")) { - include = ".*" + project.jmh + ".*" - println("JMH: " + include); + includes = [".*" + project.jmh + ".*"] + logger.info("JMH: {}", includes) } +} +test { + maxHeapSize = "1200m" } -plugins.withType(EclipsePlugin) { - project.eclipse.classpath.plusConfigurations += [ configurations.jmh ] +task testNG(type: Test) { + useTestNG() } -test { - - testLogging { - // showing skipped occasionally should prevent CI timeout due to lack of standard output - events=["skipped", "failed"] // "started", "passed" - // showStandardStreams = true - exceptionFormat="full" +check.dependsOn testNG + +tasks.withType(Test) { + testLogging { + events = ["skipped", "failed"] + exceptionFormat = "full" debug.events = ["skipped", "failed"] - debug.exceptionFormat="full" + debug.exceptionFormat = "full" info.events = ["failed", "skipped"] - info.exceptionFormat="full" - + info.exceptionFormat = "full" + warn.events = ["failed", "skipped"] - warn.exceptionFormat="full" + warn.exceptionFormat = "full" } - maxHeapSize = "1200m" - if (System.getenv("CI") == null) { maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 } } -task testng(type: Test) { - useTestNG() - testLogging { - events=["skipped", "failed"] - exceptionFormat="full" - - debug.events = ["skipped", "failed"] - debug.exceptionFormat="full" - - info.events = ["failed", "skipped"] - info.exceptionFormat="full" - - warn.events = ["failed", "skipped"] - warn.exceptionFormat="full" - } -} - -check.dependsOn testng - -jacoco { - toolVersion = jacocoVersion // See http://www.eclemma.org/jacoco/. -} - -task GCandMem(dependsOn: "check") doLast { - print("Memory usage before: ") - println(java.lang.management.ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1024.0 / 1024.0) - System.gc() - Thread.sleep(200) - print("Memory usage: ") - println(java.lang.management.ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1024.0 / 1024.0) -} - -task GCandMem2(dependsOn: "test") doLast { - print("Memory usage before: ") - println(java.lang.management.ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1024.0 / 1024.0) - System.gc() - Thread.sleep(200) - print("Memory usage: ") - println(java.lang.management.ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1024.0 / 1024.0) -} - -testng.dependsOn GCandMem2 - jacocoTestReport { + dependsOn test + dependsOn testNG + reports { - xml.enabled = true - html.enabled = true + xml.required.set(true) + csv.required.set(false) + html.required.set(true) } } -jacocoTestReport.dependsOn GCandMem - -build.dependsOn jacocoTestReport +check.dependsOn jacocoTestReport checkstyle { - configFile file("checkstyle.xml") - ignoreFailures = true - toolVersion = checkstyleVersion + configFile = project.file("config/checkstyle/checkstyle.xml") + configProperties = [ + "checkstyle.suppressions.file": project.file("config/checkstyle/suppressions.xml"), + "checkstyle.header.file" : project.file("config/license/HEADER_JAVA") + ] + checkstyleMain.exclude '**/module-info.java' } -if (rootProject.hasProperty("releaseMode")) { - - if ("branch".equals(rootProject.releaseMode)) { - // From https://github.com/ReactiveX/RxAndroid/blob/2.x/rxandroid/build.gradle#L94 - - println("ReleaseMode: " + rootProject.releaseMode); - artifactory { - contextUrl = "https://oss.jfrog.org" - - publish { - repository { - repoKey = "oss-snapshot-local" - - username = rootProject.bintrayUser - password = rootProject.bintrayKey - } - - defaults { - publishConfigs("archives") - } - } +if (project.hasProperty("releaseMode")) { + logger.lifecycle("ReleaseMode: {}", project.releaseMode) + + + if ("full" == project.releaseMode) { + signing { + if (project.hasProperty("SIGNING_PRIVATE_KEY") && project.hasProperty("SIGNING_PASSWORD")) { + useInMemoryPgpKeys(project.getProperty("SIGNING_PRIVATE_KEY"), project.getProperty("SIGNING_PASSWORD")) + sign(publishing.publications) + } } - - build.finalizedBy(artifactoryPublish) } + mavenPublishing { + // or when publishing to https://central.sonatype.com/ + publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.CENTRAL_PORTAL) - if ("full".equals(rootProject.releaseMode)) { - // based on https://github.com/bintray/gradle-bintray-plugin - def rver = version; - - println("ReleaseMode: " + rootProject.releaseMode + " version " + rver); - - bintray { - user = rootProject.bintrayUser - key = rootProject.bintrayKey - configurations = ["archives"] - publish = true - pkg { - repo = "RxJava" - name = "RxJava" - userOrg = "reactivex" - labels = ["rxjava", "reactivex"] - licenses = ["Apache-2.0"] - vcsUrl = "https://github.com/ReactiveX/RxJava.git" - version { - name = rver - gpg { - sign = true - } - mavenCentralSync { - sync = true - user = rootProject.sonatypeUsername - password = rootProject.sonatypePassword - close = "1" - } - } - } - } - - build.finalizedBy(bintrayUpload) - } + // signAllPublications() + } } - -apply from: file("gradle/javadoc_cleanup.gradle") diff --git a/checkstyle.xml b/checkstyle.xml deleted file mode 100644 index 3e7ba879da5..00000000000 --- a/checkstyle.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 00000000000..05896aee126 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 00000000000..cf580e45e60 --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/HEADER b/config/license/HEADER similarity index 100% rename from HEADER rename to config/license/HEADER diff --git a/config/license/HEADER_JAVA b/config/license/HEADER_JAVA new file mode 100644 index 00000000000..d95b44938b5 --- /dev/null +++ b/config/license/HEADER_JAVA @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ diff --git a/docs/Additional-Reading.md b/docs/Additional-Reading.md index 85e7d47077e..4badd813085 100644 --- a/docs/Additional-Reading.md +++ b/docs/Additional-Reading.md @@ -3,7 +3,7 @@ A more complete and up-to-date list of resources can be found at the [reactivex. # Introducing Reactive Programming * [Introduction to Rx](http://www.introtorx.com/): a free, on-line book by Lee Campbell **(1.x)** * [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) by Andre Staltz -* [Mastering Observables](http://docs.couchbase.com/developer/java-2.0/observables.html) from the Couchbase documentation **(1.x)** +* [Mastering Observables](https://docs.huihoo.com/couchbase/developer-guide/java-2.0/observables.html) from the Couchbase documentation **(1.x)** * [Reactive Programming in Java 8 With RxJava](http://pluralsight.com/training/Courses/TableOfContents/reactive-programming-java-8-rxjava), a course designed by Russell Elledge **(1.x)** * [33rd Degree Reactive Java](http://www.slideshare.net/tkowalcz/33rd-degree-reactive-java) by Tomasz Kowalczewski **(1.x)** * [What Every Hipster Should Know About Functional Reactive Programming](http://www.infoq.com/presentations/game-functional-reactive-programming) - Bodil Stokke demos the creation of interactive game mechanics in RxJS diff --git a/docs/Backpressure-(2.0).md b/docs/Backpressure-(2.0).md index 61361d21c4b..6b2f2860af5 100644 --- a/docs/Backpressure-(2.0).md +++ b/docs/Backpressure-(2.0).md @@ -172,7 +172,7 @@ If some of the values can be safely ignored, one can use the sampling (with time } ``` -Note hovewer that these operators only reduce the rate of value reception by the downstream and thus they may still lead to `MissingBackpressureException`. +Note however that these operators only reduce the rate of value reception by the downstream and thus they may still lead to `MissingBackpressureException`. ## onBackpressureBuffer() @@ -229,7 +229,7 @@ Note that the last two strategies cause discontinuity in the stream as they drop ## onBackpressureDrop() -Whenever the downstream is not ready to receive values, this operator will drop that elemenet from the sequence. One can think of it as a 0 capacity `onBackpressureBuffer` with strategy `ON_OVERFLOW_DROP_LATEST`. +Whenever the downstream is not ready to receive values, this operator will drop that element from the sequence. One can think of it as a 0 capacity `onBackpressureBuffer` with strategy `ON_OVERFLOW_DROP_LATEST`. This operator is useful when one can safely ignore values from a source (such as mouse moves or current GPS location signals) as there will be more up-to-date values later on. diff --git a/docs/Backpressure.md b/docs/Backpressure.md index bfe90330bbb..8529ec0995b 100644 --- a/docs/Backpressure.md +++ b/docs/Backpressure.md @@ -20,7 +20,7 @@ Cold Observables are ideal for the reactive pull model of backpressure described Your first line of defense against the problems of over-producing Observables is to use some of the ordinary set of Observable operators to reduce the number of emitted items to a more manageable number. The examples in this section will show how you might use such operators to handle a bursty Observable like the one illustrated in the following marble diagram: -​ +​ By fine-tuning the parameters to these operators you can ensure that a slow-consuming observer is not overwhelmed by a fast-producing Observable. @@ -33,7 +33,7 @@ The following diagrams show how you could use each of these operators on the bur ### sample (or throttleLast) The `sample` operator periodically "dips" into the sequence and emits only the most recently emitted item during each dip: -​ +​ ```java Observable burstySampled = bursty.sample(500, TimeUnit.MILLISECONDS); ``` @@ -41,7 +41,7 @@ Observable burstySampled = bursty.sample(500, TimeUnit.MILLISECONDS); ### throttleFirst The `throttleFirst` operator is similar, but emits not the most recently emitted item, but the first item that was emitted after the previous "dip": -​ +​ ```java Observable burstyThrottled = bursty.throttleFirst(500, TimeUnit.MILLISECONDS); ``` @@ -49,7 +49,7 @@ Observable burstyThrottled = bursty.throttleFirst(500, TimeUnit.MILLISE ### debounce (or throttleWithTimeout) The `debounce` operator emits only those items from the source Observable that are not followed by another item within a specified duration: -​ +​ ```java Observable burstyDebounced = bursty.debounce(10, TimeUnit.MILLISECONDS); ``` @@ -64,14 +64,14 @@ The following diagrams show how you could use each of these operators on the bur You could, for example, close and emit a buffer of items from the bursty Observable periodically, at a regular interval of time: -​ +​ ```java Observable> burstyBuffered = bursty.buffer(500, TimeUnit.MILLISECONDS); ``` Or you could get fancy, and collect items in buffers during the bursty periods and emit them at the end of each burst, by using the `debounce` operator to emit a buffer closing indicator to the `buffer` operator: -​ +​ ```java // we have to multicast the original bursty Observable so we can use it // both as our source and as the source for our buffer closing selector: @@ -86,14 +86,14 @@ Observable> burstyBuffered = burstyMulticast.buffer(burstyDebounce `window` is similar to `buffer`. One variant of `window` allows you to periodically emit Observable windows of items at a regular interval of time: -​ +​ ```java Observable> burstyWindowed = bursty.window(500, TimeUnit.MILLISECONDS); ```` You could also choose to emit a new window each time you have collected a particular number of items from the source Observable: -​ +​ ```java Observable> burstyWindowed = bursty.window(5); ``` @@ -128,7 +128,7 @@ someObservable.subscribe(new Subscriber() { } @Override - public void onNext(t n) { + public void onNext(T n) { // do something with the emitted item "n" // request another item: request(1); @@ -158,18 +158,18 @@ For this to work, though, Observables _A_ and _B_ must respond correctly to the
onBackpressureBuffer
-
maintains a buffer of all emissions from the source Observable and emits them to downstream Subscribers according to the requests they generate

an experimental version of this operator (not available in RxJava 1.0) allows you to set the capacity of the buffer; applying this operator will cause the resulting Observable to terminate with an error if this buffer is overrun​
+
maintains a buffer of all emissions from the source Observable and emits them to downstream Subscribers according to the requests they generate

an experimental version of this operator (not available in RxJava 1.0) allows you to set the capacity of the buffer; applying this operator will cause the resulting Observable to terminate with an error if this buffer is overrun​
onBackpressureDrop
-
drops emissions from the source Observable unless there is a pending request from a downstream Subscriber, in which case it will emit enough items to fulfill the request
+
drops emissions from the source Observable unless there is a pending request from a downstream Subscriber, in which case it will emit enough items to fulfill the request
onBackpressureBlock (experimental, not in RxJava 1.0)
-
blocks the thread on which the source Observable is operating until such time as a Subscriber issues a request for items, and then unblocks the thread only so long as there are pending requests
+
blocks the thread on which the source Observable is operating until such time as a Subscriber issues a request for items, and then unblocks the thread only so long as there are pending requests
If you do not apply any of these operators to an Observable that does not support backpressure, _and_ if either you as the Subscriber or some operator between you and the Observable attempts to apply reactive pull backpressure, you will encounter a `MissingBackpressureException` which you will be notified of via your `onError()` callback. # Further reading -If the standard operators are providing the expected behavior, [one can write custom operators in RxJava](https://github.com/ReactiveX/RxJava/wiki/Implementing-custom-operators-(draft)). +If the standard operators aren't providing the expected behavior, [one can write custom operators in RxJava](https://github.com/ReactiveX/RxJava/wiki/Implementing-custom-operators-(draft)). # See also * [RxJava 0.20.0-RC1 release notes](https://github.com/ReactiveX/RxJava/releases/tag/0.20.0-RC1) diff --git a/docs/Blocking-Observable-Operators.md b/docs/Blocking-Observable-Operators.md index 64d6e1b40ab..fe2a640f497 100644 --- a/docs/Blocking-Observable-Operators.md +++ b/docs/Blocking-Observable-Operators.md @@ -18,7 +18,7 @@ To transform an `Observable` into a `BlockingObservable`, use the [`Observable.t > This documentation accompanies its explanations with a modified form of "marble diagrams." Here is how these marble diagrams represent Blocking Observables: - + #### see also: * javadoc: `BlockingObservable` diff --git a/docs/Conditional-and-Boolean-Operators.md b/docs/Conditional-and-Boolean-Operators.md index f7ed64ce343..e6d1358e318 100644 --- a/docs/Conditional-and-Boolean-Operators.md +++ b/docs/Conditional-and-Boolean-Operators.md @@ -1,21 +1,169 @@ This section explains operators with which you conditionally emit or transform Observables, or can do boolean evaluations of them: ### Conditional Operators -* [**`amb( )`**](http://reactivex.io/documentation/operators/amb.html) — given two or more source Observables, emits all of the items from the first of these Observables to emit an item -* [**`defaultIfEmpty( )`**](http://reactivex.io/documentation/operators/defaultifempty.html) — emit items from the source Observable, or emit a default item if the source Observable completes after emitting no items -* (`rxjava-computation-expressions`) [**`doWhile( )`**](http://reactivex.io/documentation/operators/repeat.html) — emit the source Observable's sequence, and then repeat the sequence as long as a condition remains true -* (`rxjava-computation-expressions`) [**`ifThen( )`**](http://reactivex.io/documentation/operators/defer.html) — only emit the source Observable's sequence if a condition is true, otherwise emit an empty or default sequence -* [**`skipUntil( )`**](http://reactivex.io/documentation/operators/skipuntil.html) — discard items emitted by a source Observable until a second Observable emits an item, then emit the remainder of the source Observable's items -* [**`skipWhile( )`**](http://reactivex.io/documentation/operators/skipwhile.html) — discard items emitted by an Observable until a specified condition is false, then emit the remainder -* (`rxjava-computation-expressions`) [**`switchCase( )`**](http://reactivex.io/documentation/operators/defer.html) — emit the sequence from a particular Observable based on the results of an evaluation -* [**`takeUntil( )`**](http://reactivex.io/documentation/operators/takeuntil.html) — emits the items from the source Observable until a second Observable emits an item or issues a notification -* [**`takeWhile( )` and `takeWhileWithIndex( )`**](http://reactivex.io/documentation/operators/takewhile.html) — emit items emitted by an Observable as long as a specified condition is true, then skip the remainder -* (`rxjava-computation-expressions`) [**`whileDo( )`**](http://reactivex.io/documentation/operators/repeat.html) — if a condition is true, emit the source Observable's sequence and then repeat the sequence as long as the condition remains true - -> (`rxjava-computation-expressions`) — indicates that this operator is currently part of the optional `rxjava-computation-expressions` package under `rxjava-contrib` and is not included with the standard RxJava set of operators + +### Outline + +- [`amb`](#all) +- [`defaultIfEmpty`](#defaultIfEmpty) +- [`skipUntil`](#skipUntil) +- [`skipWhile`](#skipWhile) +- [`takeUntil`](#takeUntil) +- [`takeWhile`](#takeUntil) + +## amb + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/amb.html](http://reactivex.io/documentation/operators/amb.html) + +given two or more source Observables, emits all of the items from the first of these Observables to emit an item + +```java + Observable source1 = Observable.range(1, 5); + Observable source2 = Observable.range(6, 5); + Observable.amb(new ArrayList(Arrays.asList(source1, source2))) + .subscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s\n", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` +## defaultIfEmpty + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/defaultifempty.html](http://reactivex.io/documentation/operators/defaultifempty.html) + +emit items from the source Observable, or emit a default item if the source Observable completes after emitting no items + +```java + Observable.empty().defaultIfEmpty(1).blockingSubscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` + +## skipUntil + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/skipuntil.html](http://reactivex.io/documentation/operators/skipuntil.html) + +discard items emitted by a source Observable until a second Observable emits an item, then emit the remainder of the source Observable's items + +```java +Observable observable1 = Observable.range(1, 10).doOnNext(next -> Thread.sleep(1000)); + +observable1.skipUntil(Observable.timer(3, TimeUnit.SECONDS)) + .subscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` +## skipWhile + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/skipwhile.html](http://reactivex.io/documentation/operators/skipwhile.html) + +discard items emitted by an Observable until a specified condition is false, then emit the remainder + +```java +Observable.range(1, 10).skipWhile(next -> next < 5) + .subscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` + +## takeUntil + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/takeuntil.html](http://reactivex.io/documentation/operators/takeuntil.html) + +emits the items from the source Observable until a second Observable emits an item or issues a notification + +```java +Observable.range(1, 10).takeUntil(value -> value >= 5) + .subscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` + +## takeWhile + +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/takewhile.html](http://reactivex.io/documentation/operators/takewhile.html) + +emit items emitted by an Observable as long as a specified condition is true, then skip the remainder + +```java + Observable.range(1, 10).takeWhile(value -> value <= 5) + .subscribe(next -> System.out.printf("next: %s\n", next), // onNext + throwable -> System.out.printf("error: %s", throwable), //onError + () -> System.out.println("Completed") //onComplete + ); +``` ### Boolean Operators -* [**`all( )`**](http://reactivex.io/documentation/operators/all.html) — determine whether all items emitted by an Observable meet some criteria -* [**`contains( )`**](http://reactivex.io/documentation/operators/contains.html) — determine whether an Observable emits a particular item or not -* [**`exists( )` and `isEmpty( )`**](http://reactivex.io/documentation/operators/contains.html) — determine whether an Observable emits any items or not -* [**`sequenceEqual( )`**](http://reactivex.io/documentation/operators/sequenceequal.html) — test the equality of the sequences emitted by two Observables + +### Outline + +- [`all`](#all) +- [`contains`](#contains) +- [`isEmpty`](#isEmpty) +- [`sequenceEqual`](#sequenceEqual) + +## all +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/all.html](http://reactivex.io/documentation/operators/all.html) + +determine whether all items emitted by an Observable meet some criteria + +```java +Flowable.range(0,10).doOnNext(next -> System.out.println(next)).all(integer -> integer<10). + blockingSubscribe(success->System.out.println("Success: "+success)); +``` + +## contains +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/contains.html](http://reactivex.io/documentation/operators/contains.html) + +determine whether an Observable emits a particular item or not + +```java +Flowable.range(1,10).doOnNext(next->System.out.println(next)) + .contains(4).blockingSubscribe(contains->System.out.println("contains: "+contains)); +``` + +## isEmpty +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/contains.html](http://reactivex.io/documentation/operators/contains.html) + +determine whether the source Publisher is empty + +```java +Flowable.empty().isEmpty().subscribe(isEmpty -> System.out.printf("isEmpty: %s", isEmpty)); +``` + +## sequenceEqual +**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` + +**ReactiveX documentation:** [http://reactivex.io/documentation/operators/sequenceequal.html](http://reactivex.io/documentation/operators/sequenceequal.html) + +test the equality of the sequences emitted by two Observables + +```java +Flowable flowable1 = Flowable.range(1,3).doOnNext(next-> System.out.print("flowable1: "+next + " ")); + +Flowable flowable2 = Flowable.range(1,3).doOnNext(next-> System.out.println("flowable2: "+next)); + +Flowable.sequenceEqual(Flowable.fromPublisher(flowable1),Flowable.fromPublisher(flowable2)) + .blockingSubscribe(sequenceEqual->System.out.println("sequenceEqual: "+sequenceEqual)); +``` diff --git a/docs/Connectable-Observable-Operators.md b/docs/Connectable-Observable-Operators.md index a0485475296..157ded821b1 100644 --- a/docs/Connectable-Observable-Operators.md +++ b/docs/Connectable-Observable-Operators.md @@ -7,25 +7,22 @@ This section explains the [`ConnectableObservable`](http://reactivex.io/RxJava/j A Connectable Observable resembles an ordinary Observable, except that it does not begin emitting items when it is subscribed to, but only when its `connect()` method is called. In this way you can wait for all intended Subscribers to subscribe to the Observable before the Observable begins emitting items. - + The following example code shows two Subscribers subscribing to the same Observable. In the first case, they subscribe to an ordinary Observable; in the second case, they subscribe to a Connectable Observable that only connects after both Subscribers subscribe. Note the difference in the output: **Example #1:** -```groovy -def firstMillion = Observable.range( 1, 1000000 ).sample(7, java.util.concurrent.TimeUnit.MILLISECONDS); +```java +Observable firstMillion = Observable.range(1, 1000000).sample(7, java.util.concurrent.TimeUnit.MILLISECONDS); -firstMillion.subscribe( - { println("Subscriber #1:" + it); }, // onNext - { println("Error: " + it.getMessage()); }, // onError - { println("Sequence #1 complete"); } // onCompleted -); - -firstMillion.subscribe( - { println("Subscriber #2:" + it); }, // onNext - { println("Error: " + it.getMessage()); }, // onError - { println("Sequence #2 complete"); } // onCompleted -); +firstMillion.subscribe(next -> System.out.println("Subscriber #1: " + next), // onNext + throwable -> System.out.println("Error: " + throwable), // onError + () -> System.out.println("Sequence #1 complete") // onComplete + ); +firstMillion.subscribe(next -> System.out.println("Subscriber #2: " + next), // onNext + throwable -> System.out.println("Error: " + throwable), // onError + () -> System.out.println("Sequence #2 complete") // onComplete + ); ``` ``` Subscriber #1:211128 @@ -40,20 +37,18 @@ Subscriber #2:826996 Sequence #2 complete ``` **Example #2:** -```groovy -def firstMillion = Observable.range( 1, 1000000 ).sample(7, java.util.concurrent.TimeUnit.MILLISECONDS).publish(); +```java +ConnectableObservable firstMillion = Observable.range(1, 1000000).sample(7, java.util.concurrent.TimeUnit.MILLISECONDS).publish(); -firstMillion.subscribe( - { println("Subscriber #1:" + it); }, // onNext - { println("Error: " + it.getMessage()); }, // onError - { println("Sequence #1 complete"); } // onCompleted -); +firstMillion.subscribe(next -> System.out.println("Subscriber #1: " + next), // onNext + throwable -> System.out.println("Error: " + throwable), // onError + () -> System.out.println("Sequence #1 complete") // onComplete + ); -firstMillion.subscribe( - { println("Subscriber #2:" + it); }, // onNext - { println("Error: " + it.getMessage()); }, // onError - { println("Sequence #2 complete"); } // onCompleted -); +firstMillion.subscribe(next -> System.out.println("Subscriber #2: " + next), // onNext + throwable -> System.out.println("Error: " + throwable), // onError + () -> System.out.println("Sequence #2 complete") // onComplete + ); firstMillion.connect(); ``` diff --git a/docs/Filtering-Observables.md b/docs/Filtering-Observables.md index 620800dc8cd..512b69ba8a1 100644 --- a/docs/Filtering-Observables.md +++ b/docs/Filtering-Observables.md @@ -259,7 +259,7 @@ firstOrError.subscribe( **ReactiveX documentation:** [http://reactivex.io/documentation/operators/ignoreelements.html](http://reactivex.io/documentation/operators/ignoreelements.html) -Ignores the single item emitted by a `Single` or `Maybe` source, and returns a `Completable` that signals only the error or completion event from the the source. +Ignores the single item emitted by a `Single` or `Maybe` source, and returns a `Completable` that signals only the error or completion event from the source. ### ignoreElement example diff --git a/docs/Getting-Started.md b/docs/Getting-Started.md index fb9baa47dd7..69b69a8ca61 100644 --- a/docs/Getting-Started.md +++ b/docs/Getting-Started.md @@ -1,20 +1,20 @@ ## Getting Binaries -You can find binaries and dependency information for Maven, Ivy, Gradle, SBT, and others at [http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cg%3A"io.reactivex.rxjava2"%20AND%20"rxjava2"). +You can find binaries and dependency information for Maven, Ivy, Gradle, SBT, and others at [http://search.maven.org](https://search.maven.org/search?q=g:io.reactivex.rxjava3%20AND%20rxjava). Example for Maven: ```xml - io.reactivex.rxjava2 + io.reactivex.rxjava3 rxjava - 2.2.0 + 3.0.4 ``` and for Ivy: ```xml - + ``` and for SBT: @@ -22,12 +22,12 @@ and for SBT: ```scala libraryDependencies += "io.reactivex" %% "rxscala" % "0.26.5" -libraryDependencies += "io.reactivex.rxjava2" % "rxjava" % "2.2.0" +libraryDependencies += "io.reactivex.rxjava3" % "rxjava" % "3.0.4" ``` and for Gradle: ```groovy -compile 'io.reactivex.rxjava2:rxjava:2.2.0' +implementation 'io.reactivex.rxjava3:rxjava:3.0.4' ``` If you need to download the jars instead of using a build system, create a Maven `pom` file like this with the desired version: @@ -38,17 +38,17 @@ If you need to download the jars instead of using a build system, create a Maven xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.reactivex.rxjava2 + io.reactivex.rxjava3 rxjava - 2.2.0 + 3.0.4 RxJava Reactive Extensions for Java https://github.com/ReactiveX/RxJava - io.reactivex.rxjava2 + io.reactivex.rxjava3 rxjava - 2.2.0 + 3.0.4 @@ -66,18 +66,21 @@ You need Java 6 or later. ### Snapshots -Snapshots are available via [JFrog](https://oss.jfrog.org/libs-snapshot/io/reactivex/rxjava2/rxjava/): +Snapshots after May 1st, 2021 are available via https://oss.sonatype.org/content/repositories/snapshots/io/reactivex/rxjava3/rxjava/ ```groovy repositories { - maven { url 'https://oss.jfrog.org/libs-snapshot' } + maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } } dependencies { - compile 'io.reactivex.rxjava2:rxjava:2.2.0-SNAPSHOT' + implementation 'io.reactivex.rxjava3:rxjava:3.0.0-SNAPSHOT' } ``` +JavaDoc snapshots are available at http://reactivex.io/RxJava/3.x/javadoc/snapshot + + ## Building To check out and build the RxJava source, issue the following commands: diff --git a/docs/How-To-Use-RxJava.md b/docs/How-To-Use-RxJava.md index ad309496b93..41a46bb75de 100644 --- a/docs/How-To-Use-RxJava.md +++ b/docs/How-To-Use-RxJava.md @@ -285,7 +285,7 @@ onNext => value_14_xform Here is a marble diagram that illustrates this transformation: - + This next example, in Clojure, consumes three asynchronous Observables, including a dependency from one to another, and emits a single response item by combining the items emitted by each of the three Observables with the [`zip`](http://reactivex.io/documentation/operators/zip.html) operator and then transforming the result with [`map`](http://reactivex.io/documentation/operators/map.html): @@ -333,7 +333,7 @@ The response looks like this: And here is a marble diagram that illustrates how that code produces that response: - + The following example, in Groovy, comes from [Ben Christensen’s QCon presentation on the evolution of the Netflix API](https://speakerdeck.com/benjchristensen/evolution-of-the-netflix-api-qcon-sf-2013). It combines two Observables with the [`merge`](http://reactivex.io/documentation/operators/merge.html) operator, then uses the [`reduce`](http://reactivex.io/documentation/operators/reduce.html) operator to construct a single item out of the resulting sequence, then transforms that item with [`map`](http://reactivex.io/documentation/operators/map.html) before emitting it: @@ -350,7 +350,7 @@ public Observable getVideoSummary(APIVideo video) { And here is a marble diagram that illustrates how that code uses the [`reduce`](http://reactivex.io/documentation/operators/reduce.html) operator to bring the results from multiple Observables together in one structure: - + ## Error Handling diff --git a/docs/Phantom-Operators.md b/docs/Phantom-Operators.md index 60da4a1a403..5193147a228 100644 --- a/docs/Phantom-Operators.md +++ b/docs/Phantom-Operators.md @@ -19,7 +19,7 @@ These operators have been proposed but are not part of the 1.0 release of RxJava ## chunkify( ) #### returns an iterable that periodically returns a list of items emitted by the source Observable since the last list - + The `chunkify( )` operator represents a blocking observable as an Iterable, that, each time you iterate over it, returns a list of items emitted by the source Observable since the previous iteration. These lists may be empty if there have been no such items emitted. @@ -27,7 +27,7 @@ The `chunkify( )` operator represents a blocking observable as an Iterable, th ## fromFuture( ) #### convert a Future into an Observable, but do not attempt to get the Future's value until a Subscriber subscribes - + The `fromFuture( )` method also converts a Future into an Observable, but it obtains this Future indirectly, by means of a function you provide. It creates the Observable immediately, but waits to call the function and to obtain the Future until a Subscriber subscribes to it. @@ -35,7 +35,7 @@ The `fromFuture( )` method also converts a Future into an Observable, but it o ## forEachFuture( ) #### create a futureTask that will invoke a specified function on each item emitted by an Observable - + The `forEachFuture( )` returns a `FutureTask` for each item emitted by the source Observable (or each item and each notification) that, when executed, will apply a function you specify to each such item (or item and notification). @@ -43,7 +43,7 @@ The `forEachFuture( )` returns a `FutureTask` for each item emitted by the sou ## forIterable( ) #### apply a function to the elements of an Iterable to create Observables which are then concatenated - + `forIterable( )` is similar to `from(Iterable )` but instead of the resulting Observable emitting the elements of the Iterable as its own emitted items, it applies a specified function to each of these elements to generate one Observable per element, and then concatenates the emissions of these Observables to be its own sequence of emitted items. @@ -58,7 +58,7 @@ If the a subscriber to the Observable that results when a Future is converted to ## generate( ) and generateAbsoluteTime( ) #### create an Observable that emits a sequence of items as generated by a function of your choosing - + The basic form of `generate( )` takes four parameters. These are `initialState` and three functions: `iterate( )`, `condition( )`, and `resultSelector( )`. `generate( )` uses these four parameters to generate an Observable sequence, which is its return value. It does so in the following way. @@ -66,7 +66,7 @@ The basic form of `generate( )` takes four parameters. These are `initialState There are also versions of `generate( )` that allow you to do the work of generating the sequence on a particular `Scheduler` and that allow you to set the time interval between emissions by applying a function to the current state. The `generateAbsoluteTime( )` allows you to control the time at which an item is emitted by applying a function to the state to get an absolute system clock time (rather than an interval from the previous emission). - + #### see also: * Introduction to Rx: Generate @@ -79,7 +79,7 @@ There are also versions of `generate( )` that allow you to do the work of gene This version of `groupBy` adds another parameter: an Observable that emits duration markers. When a duration marker is emitted by this Observable, any grouped Observables that have been opened are closed, and `groupByUntil( )` will create new grouped Observables for any subsequent emissions by the source Observable. -​ +​ Another variety of `groupByUntil( )` limits the number of groups that can be active at any particular time. If an item is emitted by the source Observable that would cause the number of groups to exceed this maximum, before the new group is emitted, one of the existing groups is closed (that is, the Observable it represents terminates by calling its Subscribers' `onCompleted` methods and then expires). @@ -101,7 +101,7 @@ To represent an Observable as a Connectable Observable, use the `multicast( )` ## onErrorFlatMap( ) #### instructs an Observable to emit a sequence of items whenever it encounters an error -​ +​ The `onErrorFlatMap( )` method is similar to `onErrorResumeNext( )` except that it does not assume the source Observable will correctly terminate when it issues an error. Because of this, after emitting its backup sequence of items, `onErrorFlatMap( )` relinquishes control of the emitted sequence back to the source Observable. If that Observable again issues an error, `onErrorFlatMap( )` will again emit its backup sequence. @@ -111,13 +111,13 @@ Because `onErrorFlatMap( )` is designed to work with pathological source Obser Note that you should apply `onErrorFlatMap( )` directly to the pathological source Observable, and not to that Observable after it has been modified by additional operators, as such operators may effectively renormalize the source Observable by unsubscribing from it immediately after it issues an error. Below, for example, is an illustration showing how `onErrorFlatMap( )` will respond to two error-generating Observables that have been merged by the `merge( )` operator. Note that it will *not* react to both errors generated by both Observables, but only to the single error passed along by `merge( )`: -​ +​ *** ## parallel( ) #### split the work done on the emissions from an Observable into multiple Observables each operating on its own parallel thread -​ +​ The `parallel( )` method splits an Observable into as many Observables as there are available processors, and does work in parallel on each of these Observables. `parallel( )` then merges the results of these parallel computations back into a single, well-behaved Observable sequence. @@ -127,7 +127,7 @@ streamOfItems.flatMap(item -> { itemToObservable(item).subscribeOn(Schedulers.io()); }); ``` -Kick off your work for each item inside [`flatMap`](Transforming-Observables#flatmap-concatmap-and-flatmapiterable) using [`subscribeOn`](Observable-Utility-Operators#subscribeon) to make it asynchronous, or by using a function that already makes asychronous calls. +Kick off your work for each item inside [`flatMap`](Transforming-Observables#flatmap-concatmap-and-flatmapiterable) using [`subscribeOn`](Observable-Utility-Operators#subscribeon) to make it asynchronous, or by using a function that already makes asynchronous calls. #### see also: * RxJava Threading Examples by Graham Lea @@ -136,7 +136,7 @@ Kick off your work for each item inside [`flatMap`](Transforming-Observables#fla ## parallelMerge( ) #### combine multiple Observables into a smaller number of Observables, to facilitate parallelism -​ +​ Use the `parallelMerge( )` method to take an Observable that emits a large number of Observables and to reduce it to an Observable that emits a particular, smaller number of Observables that emit the same set of items as the original larger set of Observables: for instance a number of Observables that matches the number of parallel processes that you want to use when processing the emissions from the complete set of Observables. @@ -144,7 +144,7 @@ Use the `parallelMerge( )` method to take an Observable that emits a large num ## pivot( ) #### combine multiple sets of grouped observables so that they are arranged primarily by group rather than by set -​ +​ If you combine multiple sets of grouped observables, such as those created by [`groupBy( )` and `groupByUntil( )`](Transforming-Observables#wiki-groupby-and-groupbyuntil), then even if those grouped observables have been grouped by a similar differentiation function, the resulting grouping will be primarily based on which set the observable came from, not on which group the observable belonged to. @@ -152,13 +152,13 @@ An example may make this clearer. Imagine you use `groupBy( )` to group the em The result will be a grouped observable that emits two groups: the grouped observable resulting from transforming Observable1, and the grouped observable resulting from transforming Observable2. Each of those grouped observables emit observables that in turn emit the odds and evens from the source observables. You can use `pivot( )` to change this around: by applying `pivot( )` to this grouped observable it will transform into one that emits two different groups: the odds group and the evens group, with each of these groups emitting a separate observable corresponding to which source observable its set of integers came from. Here is an illustration: -​ +​ *** ## publishLast( ) #### represent an Observable as a Connectable Observable that emits only the last item emitted by the source Observable - + #### see also: * RxJS: `publishLast` diff --git a/docs/What's-different-in-2.0.md b/docs/What's-different-in-2.0.md index fac50df56d2..edc681fa7fd 100644 --- a/docs/What's-different-in-2.0.md +++ b/docs/What's-different-in-2.0.md @@ -450,12 +450,12 @@ Before 2.0.7, the operator `strict()` had to be applied in order to achieve the As one of the primary goals of RxJava 2, the design focuses on performance and in order enable it, RxJava 2.0.7 adds a custom `io.reactivex.FlowableSubscriber` interface (extends `org.reactivestreams.Subscriber`) but adds no new methods to it. The new interface is **constrained to RxJava 2** and represents a consumer to `Flowable` that is able to work in a mode that relaxes the Reactive-Streams version 1.0.0 specification in rules §1.3, §2.3, §2.12 and §3.9: - - §1.3 relaxation: `onSubscribe` may run concurrently with `onNext` in case the `FlowableSubscriber` calls `request()` from inside `onSubscribe` and it is the resposibility of `FlowableSubscriber` to ensure thread-safety between the remaining instructions in `onSubscribe` and `onNext`. + - §1.3 relaxation: `onSubscribe` may run concurrently with `onNext` in case the `FlowableSubscriber` calls `request()` from inside `onSubscribe` and it is the responsibility of `FlowableSubscriber` to ensure thread-safety between the remaining instructions in `onSubscribe` and `onNext`. - §2.3 relaxation: calling `Subscription.cancel` and `Subscription.request` from `FlowableSubscriber.onComplete()` or `FlowableSubscriber.onError()` is considered a no-operation. - §2.12 relaxation: if the same `FlowableSubscriber` instance is subscribed to multiple sources, it must ensure its `onXXX` methods remain thread safe. - §3.9 relaxation: issuing a non-positive `request()` will not stop the current stream but signal an error via `RxJavaPlugins.onError`. -From a user's perspective, if one was using the the `subscribe` methods other than `Flowable.subscribe(Subscriber)`, there is no need to do anything regarding this change and there is no extra penalty for it. +From a user's perspective, if one was using the `subscribe` methods other than `Flowable.subscribe(Subscriber)`, there is no need to do anything regarding this change and there is no extra penalty for it. If one was using `Flowable.subscribe(Subscriber)` with the built-in RxJava `Subscriber` implementations such as `DisposableSubscriber`, `TestSubscriber` and `ResourceSubscriber`, there is a small runtime overhead (one `instanceof` check) associated when the code is not recompiled against 2.0.7. diff --git a/docs/Writing-operators-for-2.0.md b/docs/Writing-operators-for-2.0.md index e8486564b1f..1a51664880e 100644 --- a/docs/Writing-operators-for-2.0.md +++ b/docs/Writing-operators-for-2.0.md @@ -565,7 +565,7 @@ Version 2.0.7 introduced a new interface, `FlowableSubscriber` that extends `Sub The rule relaxations are as follows: -- §1.3 relaxation: `onSubscribe` may run concurrently with onNext in case the `FlowableSubscriber` calls `request()` from inside `onSubscribe` and it is the resposibility of `FlowableSubscriber` to ensure thread-safety between the remaining instructions in `onSubscribe` and `onNext`. +- §1.3 relaxation: `onSubscribe` may run concurrently with onNext in case the `FlowableSubscriber` calls `request()` from inside `onSubscribe` and it is the responsibility of `FlowableSubscriber` to ensure thread-safety between the remaining instructions in `onSubscribe` and `onNext`. - §2.3 relaxation: calling `Subscription.cancel` and `Subscription.request` from `FlowableSubscriber.onComplete()` or `FlowableSubscriber.onError()` is considered a no-operation. - §2.12 relaxation: if the same `FlowableSubscriber` instance is subscribed to multiple sources, it must ensure its `onXXX` methods remain thread safe. - §3.9 relaxation: issuing a non-positive `request()` will not stop the current stream but signal an error via `RxJavaPlugins.onError`. diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index 32e201fc464..22961acec3e 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -27,6 +27,6 @@ * [Writing operators](https://github.com/ReactiveX/RxJava/wiki/Writing-operators-for-2.0) * [Backpressure](https://github.com/ReactiveX/RxJava/wiki/Backpressure-(2.0)) * [another explanation](https://github.com/ReactiveX/RxJava/wiki/Backpressure) -* [JavaDoc](http://reactivex.io/RxJava/2.x/javadoc) +* JavaDoc: [1.x](http://reactivex.io/RxJava/1.x/javadoc), [2.x](http://reactivex.io/RxJava/2.x/javadoc), [3.x](http://reactivex.io/RxJava/3.x/javadoc) * [Coming from RxJava 1](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0) * [Additional Reading](https://github.com/ReactiveX/RxJava/wiki/Additional-Reading) diff --git a/gradle.properties b/gradle.properties index 820b2a5bc10..e685b8103a4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,24 @@ -release.scope=patch -release.version=3.0.0-SNAPSHOT +group=io.reactivex.rxjava3 +version=3.0.0-SNAPSHOT +description=RxJava: Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM. + +POM_ARTIFACT_ID=rxjava +POM_NAME=RxJava +POM_PACKAGING=jar + +POM_DESCRIPTION=Reactive Extensions for Java +POM_INCEPTION_YEAR=2013 + +POM_URL=https://github.com/ReactiveX/RxJava +POM_SCM_URL=https://github.com/ReactiveX/RxJava +POM_SCM_CONNECTION=scm:git:git://github.com/ReactiveX/RxJava.git +POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/ReactiveX/RxJava.git + +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo + +POM_DEVELOPER_ID=akarnokd +POM_DEVELOPER_NAME=David Karnok +POM_DEVELOPER_URL=https://github.com/akarnokd/ +POM_DEVELOPER_EMAIL=akarnokd@gmail.com diff --git a/gradle/buildViaTravis.sh b/gradle/buildViaTravis.sh deleted file mode 100755 index ea385c3e920..00000000000 --- a/gradle/buildViaTravis.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# This script will build the project. - -buildTag="$TRAVIS_TAG" - -if [ "$buildTag" != "" ] && [ "${buildTag:0:3}" != "v3." ]; then - echo -e "Wrong tag on the 3.x brach: $buildTag : build stopped" - exit 1 -fi - -export GRADLE_OPTS=-Xmx1024m - -if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - echo -e "Build Pull Request #$TRAVIS_PULL_REQUEST => Branch [$TRAVIS_BRANCH]" - ./gradlew -PreleaseMode=pr build --stacktrace -elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" == "" ]; then - if [ "$TRAVIS_BRANCH" != "3.x" ]; then - echo -e 'Build secondary Branch (no snapshot) => Branch ['$TRAVIS_BRANCH']' - ./gradlew -PreleaseMode=pr build --stacktrace - else - echo -e 'Build Branch with Snapshot => Branch ['$TRAVIS_BRANCH']' - ./gradlew -PreleaseMode=branch -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" -PsonatypeUsername="${sonatypeUsername}" -PsonatypePassword="${sonatypePassword}" build --stacktrace - fi -elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then - echo -e 'Build Branch for Release => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG']' - ./gradlew -PreleaseMode=full -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" -PsonatypeUsername="${sonatypeUsername}" -PsonatypePassword="${sonatypePassword}" build --stacktrace -else - echo -e 'WARN: Should not be here => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG'] Pull Request ['$TRAVIS_PULL_REQUEST']' -fi diff --git a/gradle/javadoc_cleanup.gradle b/gradle/javadoc_cleanup.gradle index 12216464a7d..63b4f7f0456 100644 --- a/gradle/javadoc_cleanup.gradle +++ b/gradle/javadoc_cleanup.gradle @@ -1,36 +1,74 @@ // remove the excessive whitespaces between method arguments in the javadocs task javadocCleanup(dependsOn: "javadoc") doLast { - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Flowable.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Observable.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Single.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Maybe.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Completable.html')); + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Flowable.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Observable.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Single.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Maybe.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/core/Completable.html')) - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/flowables/ConnectableFlowable.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/observables/ConnectableObservable.html')); + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/flowables/ConnectableFlowable.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/observables/ConnectableObservable.html')) - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/ReplaySubject.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/ReplayProcessor.html')); - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/plugins/RxJavaPlugins.html')); + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/ReplaySubject.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/ReplayProcessor.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/PublishSubject.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/PublishProcessor.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/AsyncSubject.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/AsyncProcessor.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/BehaviorSubject.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/BehaviorProcessor.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/MulticastProcessor.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subjects/UnicastSubject.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/processors/UnicastProcessor.html')) - fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/parallel/ParallelFlowable.html')); + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/plugins/RxJavaPlugins.html')) + + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/parallel/ParallelFlowable.html')) + + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/disposables/Disposable.html')) + + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/observers/TestObserver.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/observers/BaseTestConsumer.html')) + fixJavadocFile(rootProject.file('build/docs/javadoc/io/reactivex/rxjava3/subscribers/TestSubscriber.html')) } def fixJavadocFile(file) { - println("Cleaning up: " + file); + logger.lifecycle("Cleaning up: " + file) String fileContents = file.getText('UTF-8') // lots of spaces after the previous method argument - fileContents = fileContents.replaceAll(",\\s{4,}", ",\n "); + fileContents = fileContents.replaceAll(",\\s{4,}", ",\n ") // lots of spaces after the @NonNull annotations - fileContents = fileContents.replaceAll("@NonNull\\s{4,}", "@NonNull "); + fileContents = fileContents.replaceAll("@NonNull\\s{4,}", "@NonNull ") // lots of spaces after the @Nullable annotations - fileContents = fileContents.replaceAll("@Nullable\\s{4,}", "@Nullable "); + fileContents = fileContents.replaceAll("@Nullable\\s{4,}", "@Nullable ") - file.setText(fileContents, 'UTF-8'); -} + // javadoc bug: duplicates the link to @NonNull for some reason + def nonNullText1 = "@NonNull" + + fileContents = fileContents.replace(nonNullText1 + " " + nonNullText1, nonNullText1) + fileContents = fileContents.replace(nonNullText1 + "\n " + nonNullText1, nonNullText1) + fileContents = fileContents.replace(nonNullText1 + "\r\n " + nonNullText1, nonNullText1) + + def nonNullText2 = "@NonNull" + fileContents = fileContents.replace(nonNullText2 + " " + nonNullText2, nonNullText2) + fileContents = fileContents.replace(nonNullText2 + "\n " + nonNullText2, nonNullText2) + fileContents = fileContents.replace(nonNullText2 + "\r\n " + nonNullText2, nonNullText2) -javadocJar.dependsOn javadocCleanup -build.dependsOn javadocCleanup \ No newline at end of file + // javadoc bug: duplicates the link to @Nullable for some reason + def nullableText1 = "@Nullable" + + fileContents = fileContents.replace(nullableText1 + " " + nullableText1, nullableText1) + fileContents = fileContents.replace(nullableText1 + "\n " + nullableText1, nullableText1) + fileContents = fileContents.replace(nullableText1 + "\r\n " + nullableText1, nullableText1) + + def nullableText2 = "@Nullable" + + fileContents = fileContents.replace(nullableText2 + " " + nullableText2, nullableText2) + fileContents = fileContents.replace(nullableText2 + "\n " + nullableText2, nullableText2) + fileContents = fileContents.replace(nullableText2 + "\r\n " + nullableText2, nullableText2) + + file.setText(fileContents, 'UTF-8') +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b..afba109285a 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 94920145f34..3c44eb1b6f5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfdc31..65dcd68d65c 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9618d8d9607..93e3f59f135 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/gradle/push_javadoc.sh b/push_javadoc.sh similarity index 78% rename from gradle/push_javadoc.sh rename to push_javadoc.sh index c8f648258e0..28ce74f1db1 100644 --- a/gradle/push_javadoc.sh +++ b/push_javadoc.sh @@ -8,21 +8,9 @@ targetRepo=github.com/ReactiveX/RxJava.git # ======================================================================= -# only for main pushes, for now -if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - echo -e "Pull request detected, skipping JavaDocs pushback." - exit 0 -fi - -# only when on the 3.x branch and not tagged -if [ "$TRAVIS_BRANCH" != "3.x" ] && [ "$TRAVIS_TAG" == "" ]; then - echo -e "On a secondary branch '$TRAVIS_BRANCH', skipping JavaDocs pushback." - exit 0 -fi - # get the current build tag if any -buildTag="$TRAVIS_TAG" -echo -e "Travis tag: '$buildTag'" +buildTag="$BUILD_TAG" +echo -e "Build tag: '$buildTag'" if [ "$buildTag" == "" ]; then buildTag="snapshot" @@ -33,18 +21,18 @@ fi echo -e "JavaDocs pushback for tag: $buildTag" # check if the token is actually there -if [ "$GITHUB_TOKEN" == "" ]; then +if [ "$JAVADOCS_TOKEN" == "" ]; then echo -e "No access to GitHub, skipping JavaDocs pushback." exit 0 fi # prepare the git information -git config --global user.email "travis@travis-ci.org" -git config --global user.name "Travis CI" +git config --global user.email "akarnokd+ci@gmail.com" +git config --global user.name "akarnokd+ci" # setup the remote echo -e "Adding the target repository to git" -git remote add origin-pages https://${GITHUB_TOKEN}@${targetRepo} > /dev/null 2>&1 +git remote add origin-pages https://${JAVADOCS_TOKEN}@${targetRepo} > /dev/null 2>&1 # stash changes due to chmod echo -e "Stashing any local non-ignored changes" @@ -119,8 +107,8 @@ echo -e "Removing deleted files" git add -u # commit all -echo -e "commit Travis build: $TRAVIS_BUILD_NUMBER for $buildTag" -git commit --message "Travis build: $TRAVIS_BUILD_NUMBER for $buildTag" +echo -e "commit CI build: $CI_BUILD_NUMBER for $buildTag" +git commit --message "CI build: $CI_BUILD_NUMBER for $buildTag" # debug file list #find -name "*.html" diff --git a/src/jmh/java/io/reactivex/rxjava3/core/BinaryFlatMapPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/BinaryFlatMapPerf.java index 836957192ec..6e6ae7e3c62 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/BinaryFlatMapPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/BinaryFlatMapPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -139,9 +139,9 @@ public Observable apply(Integer v) { } }); - singleFlatMapHideObservable = Single.just(1).flatMapObservable(new Function>() { + singleFlatMapHideObservable = Single.just(1).flatMapObservable(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return arrayObservableHide; } }); @@ -153,16 +153,16 @@ public Iterable apply(Integer v) { } }); - maybeFlatMapObservable = Maybe.just(1).flatMapObservable(new Function>() { + maybeFlatMapObservable = Maybe.just(1).flatMapObservable(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return arrayObservable; } }); - maybeFlatMapHideObservable = Maybe.just(1).flatMapObservable(new Function>() { + maybeFlatMapHideObservable = Maybe.just(1).flatMapObservable(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return arrayObservableHide; } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/core/BlockingGetPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/BlockingGetPerf.java index f40a8ca55b6..7f3711788ab 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/BlockingGetPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/BlockingGetPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/BlockingPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/BlockingPerf.java index 020befc21a1..5fb2825b3ee 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/BlockingPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/BlockingPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/CallableAsyncPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/CallableAsyncPerf.java index 8098b1aaf40..1bae28f9f9d 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/CallableAsyncPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/CallableAsyncPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/EachTypeFlatMapPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/EachTypeFlatMapPerf.java index 37a4f196e8f..14aa8c3605e 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/EachTypeFlatMapPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/EachTypeFlatMapPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlatMapJustPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlatMapJustPerf.java index 2a1fd7539c2..597fae480d6 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlatMapJustPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlatMapJustPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlattenCrossMapPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlattenCrossMapPerf.java index 866fe5de776..c5d516423f2 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlattenCrossMapPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlattenCrossMapPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlattenJustPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlattenJustPerf.java index d2ac9aa5b7c..3bb1ad1473e 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlattenJustPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlattenJustPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlattenRangePerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlattenRangePerf.java index a3195b760d4..0339f345c31 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlattenRangePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlattenRangePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableAsyncPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableAsyncPerf.java index e9494e97dff..0ebb2d4458b 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableAsyncPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableAsyncPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableSyncPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableSyncPerf.java index 34f53a954af..400e0609a8f 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableSyncPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/FlowableFlatMapCompletableSyncPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/InputWithIncrementingInteger.java b/src/jmh/java/io/reactivex/rxjava3/core/InputWithIncrementingInteger.java index 772d202dca8..44d109fb4d5 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/InputWithIncrementingInteger.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/InputWithIncrementingInteger.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/JustAsyncPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/JustAsyncPerf.java index f60204c88b2..6906470aeaa 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/JustAsyncPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/JustAsyncPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/LatchedSingleObserver.java b/src/jmh/java/io/reactivex/rxjava3/core/LatchedSingleObserver.java index 1b908ac6b28..6bcdba465ed 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/LatchedSingleObserver.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/LatchedSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/MemoryPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/MemoryPerf.java index c7c407de158..7cd45de74ee 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/MemoryPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/MemoryPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/ObservableFlatMapPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/ObservableFlatMapPerf.java index d0d75e78d4a..65145b07b42 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/ObservableFlatMapPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/ObservableFlatMapPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/OperatorFlatMapPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/OperatorFlatMapPerf.java index 0eb7f03aa9c..777fc9e1a6c 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/OperatorFlatMapPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/OperatorFlatMapPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/OperatorMergePerf.java b/src/jmh/java/io/reactivex/rxjava3/core/OperatorMergePerf.java index 560736c86c1..24605fc02a6 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/OperatorMergePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/OperatorMergePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfAsyncConsumer.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfAsyncConsumer.java index 7c222fddab0..ccaaf755735 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfAsyncConsumer.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfAsyncConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfBoundedSubscriber.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfBoundedSubscriber.java index 8ec19a833ab..68083976be9 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfBoundedSubscriber.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfBoundedSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfConsumer.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfConsumer.java index 6025438218b..60f93f089a0 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfConsumer.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfInteropConsumer.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfInteropConsumer.java index 6dfbac7a310..fc7f0b04b0f 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfInteropConsumer.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfInteropConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfObserver.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfObserver.java index 5f09b97ffe6..a62a1e68f60 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfObserver.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PerfSubscriber.java b/src/jmh/java/io/reactivex/rxjava3/core/PerfSubscriber.java index 51da5a5c53b..8c0f30cffa5 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PerfSubscriber.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PerfSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/PublishProcessorPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/PublishProcessorPerf.java index c64e1f794d0..1278bfd641c 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/PublishProcessorPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/PublishProcessorPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/RangePerf.java b/src/jmh/java/io/reactivex/rxjava3/core/RangePerf.java index c9723b086da..0773cd4f724 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/RangePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/RangePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/ReducePerf.java b/src/jmh/java/io/reactivex/rxjava3/core/ReducePerf.java index faf0423760c..3d2bb476c8a 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/ReducePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/ReducePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/RxVsStreamPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/RxVsStreamPerf.java index 74c8952c7a0..8861a6cdf53 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/RxVsStreamPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/RxVsStreamPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/StrictPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/StrictPerf.java index 59d17f4d60c..23315ef6179 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/StrictPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/StrictPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/TakeUntilPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/TakeUntilPerf.java index b2f89a39ca2..a6a39496059 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/TakeUntilPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/TakeUntilPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/ToFlowablePerf.java b/src/jmh/java/io/reactivex/rxjava3/core/ToFlowablePerf.java index 9c86e836784..7b7f0dc36d2 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/ToFlowablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/ToFlowablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/core/XMapYPerf.java b/src/jmh/java/io/reactivex/rxjava3/core/XMapYPerf.java index 6205efa25da..b95d76ffe46 100644 --- a/src/jmh/java/io/reactivex/rxjava3/core/XMapYPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/core/XMapYPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/parallel/ParallelPerf.java b/src/jmh/java/io/reactivex/rxjava3/parallel/ParallelPerf.java index 4eaac7b0dac..c6fd16ffb60 100644 --- a/src/jmh/java/io/reactivex/rxjava3/parallel/ParallelPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/parallel/ParallelPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -109,4 +109,4 @@ public void groupBy(Blackhole bh) { public void parallel(Blackhole bh) { subscribe(parallel, bh); } -} \ No newline at end of file +} diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapCompletablePerf.java index 9e1096ab74a..f1124f7a81d 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybeEmptyPerf.java index a211fbe8292..7eabfcfbded 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybePerf.java index 059a0b162be..4310ea2e955 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.concatMapMaybe(new Function>() { + flowableDedicated = source.concatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapSinglePerf.java index e812708a156..cbeac5ada90 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableConcatMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapCompletablePerf.java index 1960735cfa4..b46725986fe 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybeEmptyPerf.java index 96e6fcf6724..699f76c0743 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.flatMapMaybe(new Function>() { + flowableDedicated = source.flatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.empty(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybePerf.java index 2f71d5793e4..f81ed10ec33 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.flatMapMaybe(new Function>() { + flowableDedicated = source.flatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapSinglePerf.java index 2bbdf9bf958..5a92bf20ffb 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableFlatMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.flatMapSingle(new Function>() { + flowableDedicated = source.flatMapSingle(new Function>() { @Override - public Single apply(Integer v) { + public Single apply(Integer v) { return Single.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapCompletablePerf.java index 033d35c4290..4e419a5d2e7 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybeEmptyPerf.java index adc60601893..46ce694f6dd 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.switchMapMaybe(new Function>() { + flowableDedicated = source.switchMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.empty(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybePerf.java index d5d8cb9443e..e96bbc39194 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.switchMapMaybe(new Function>() { + flowableDedicated = source.switchMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapSinglePerf.java index a997f27b537..ef06ebfa668 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/FlowableSwitchMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,9 @@ public Publisher apply(Integer v) { } }); - flowableDedicated = source.switchMapSingle(new Function>() { + flowableDedicated = source.switchMapSingle(new Function>() { @Override - public Single apply(Integer v) { + public Single apply(Integer v) { return Single.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapCompletablePerf.java index ca6174a006e..2229eed77a9 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,16 +45,16 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.concatMap(new Function>() { + observablePlain = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - observableConvert = source.concatMap(new Function>() { + observableConvert = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Completable.complete().toObservable(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybeEmptyPerf.java index b194580fa8f..cfde5183e5f 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.concatMap(new Function>() { + observablePlain = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - concatMapToObservableEmpty = source.concatMap(new Function>() { + concatMapToObservableEmpty = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.empty().toObservable(); } }); - observableDedicated = source.concatMapMaybe(new Function>() { + observableDedicated = source.concatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.empty(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybePerf.java index 5c7d6ad7a09..75e75067245 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.concatMap(new Function>() { + observablePlain = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.concatMap(new Function>() { + observableConvert = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.just(v).toObservable(); } }); - observableDedicated = source.concatMapMaybe(new Function>() { + observableDedicated = source.concatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapSinglePerf.java index 1785b591355..4227791222b 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableConcatMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.concatMap(new Function>() { + observablePlain = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.concatMap(new Function>() { + observableConvert = source.concatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Single.just(v).toObservable(); } }); - observableDedicated = source.concatMapSingle(new Function>() { + observableDedicated = source.concatMapSingle(new Function>() { @Override - public Single apply(Integer v) { + public Single apply(Integer v) { return Single.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapCompletablePerf.java index 64247ac219a..6a916a68f1e 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,16 +45,16 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.flatMap(new Function>() { + observablePlain = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - observableConvert = source.flatMap(new Function>() { + observableConvert = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Completable.complete().toObservable(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybeEmptyPerf.java index 5e38b30061c..377a8bba933 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.flatMap(new Function>() { + observablePlain = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - observableConvert = source.flatMap(new Function>() { + observableConvert = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.empty().toObservable(); } }); - observableDedicated = source.flatMapMaybe(new Function>() { + observableDedicated = source.flatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.empty(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybePerf.java index ffc5b15e564..248ca981126 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.flatMap(new Function>() { + observablePlain = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.flatMap(new Function>() { + observableConvert = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.just(v).toObservable(); } }); - observableDedicated = source.flatMapMaybe(new Function>() { + observableDedicated = source.flatMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapSinglePerf.java index 6356ad8acee..880da95f5a1 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableFlatMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.flatMap(new Function>() { + observablePlain = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.flatMap(new Function>() { + observableConvert = source.flatMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Single.just(v).toObservable(); } }); - observableDedicated = source.flatMapSingle(new Function>() { + observableDedicated = source.flatMapSingle(new Function>() { @Override - public Single apply(Integer v) { + public Single apply(Integer v) { return Single.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapCompletablePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapCompletablePerf.java index 1fc6eef9b39..41964c3dbde 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapCompletablePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapCompletablePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,16 +45,16 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.switchMap(new Function>() { + observablePlain = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - observableConvert = source.switchMap(new Function>() { + observableConvert = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Completable.complete().toObservable(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybeEmptyPerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybeEmptyPerf.java index 47374934206..6a4ea5c73bd 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybeEmptyPerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybeEmptyPerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.switchMap(new Function>() { + observablePlain = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.empty(); } }); - observableConvert = source.switchMap(new Function>() { + observableConvert = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.empty().toObservable(); } }); - observableDedicated = source.switchMapMaybe(new Function>() { + observableDedicated = source.switchMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.empty(); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybePerf.java index b8dca2d95ba..f0c32858904 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapMaybePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.switchMap(new Function>() { + observablePlain = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.switchMap(new Function>() { + observableConvert = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Maybe.just(v).toObservable(); } }); - observableDedicated = source.switchMapMaybe(new Function>() { + observableDedicated = source.switchMapMaybe(new Function>() { @Override - public Maybe apply(Integer v) { + public Maybe apply(Integer v) { return Maybe.just(v); } }); diff --git a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapSinglePerf.java b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapSinglePerf.java index 682e2712f00..087f32c8e36 100644 --- a/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapSinglePerf.java +++ b/src/jmh/java/io/reactivex/rxjava3/xmapz/ObservableSwitchMapSinglePerf.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,23 +45,23 @@ public void setup() { Observable source = Observable.fromArray(sourceArray); - observablePlain = source.switchMap(new Function>() { + observablePlain = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Observable.just(v); } }); - observableConvert = source.switchMap(new Function>() { + observableConvert = source.switchMap(new Function>() { @Override - public Observable apply(Integer v) { + public Observable apply(Integer v) { return Single.just(v).toObservable(); } }); - observableDedicated = source.switchMapSingle(new Function>() { + observableDedicated = source.switchMapSingle(new Function>() { @Override - public Single apply(Integer v) { + public Single apply(Integer v) { return Single.just(v); } }); diff --git a/src/main/java/io/reactivex/rxjava3/annotations/BackpressureKind.java b/src/main/java/io/reactivex/rxjava3/annotations/BackpressureKind.java index fd53c196b34..3b979a045da 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/BackpressureKind.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/BackpressureKind.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/BackpressureSupport.java b/src/main/java/io/reactivex/rxjava3/annotations/BackpressureSupport.java index 9deafa22f5f..b73a477fec1 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/BackpressureSupport.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/BackpressureSupport.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/Beta.java b/src/main/java/io/reactivex/rxjava3/annotations/Beta.java index 123842b7739..ca75ea0b3b1 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/Beta.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/Beta.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/CheckReturnValue.java b/src/main/java/io/reactivex/rxjava3/annotations/CheckReturnValue.java index 3091d2647fd..02c7f2e0d92 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/CheckReturnValue.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/CheckReturnValue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/Experimental.java b/src/main/java/io/reactivex/rxjava3/annotations/Experimental.java index 32d60e14424..061361f9b4d 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/Experimental.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/Experimental.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/NonNull.java b/src/main/java/io/reactivex/rxjava3/annotations/NonNull.java index 03e51805888..4495092fc7c 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/NonNull.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/NonNull.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/Nullable.java b/src/main/java/io/reactivex/rxjava3/annotations/Nullable.java index c95ef4a35c3..a6af9eb1b59 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/Nullable.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/Nullable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/SchedulerSupport.java b/src/main/java/io/reactivex/rxjava3/annotations/SchedulerSupport.java index 53b395f06b1..0132b6a33d3 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/SchedulerSupport.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/SchedulerSupport.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/annotations/package-info.java b/src/main/java/io/reactivex/rxjava3/annotations/package-info.java index 8fa44fd5535..a4daca2a325 100644 --- a/src/main/java/io/reactivex/rxjava3/annotations/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/annotations/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/core/BackpressureOverflowStrategy.java b/src/main/java/io/reactivex/rxjava3/core/BackpressureOverflowStrategy.java index 750a1308f21..144dbb68076 100644 --- a/src/main/java/io/reactivex/rxjava3/core/BackpressureOverflowStrategy.java +++ b/src/main/java/io/reactivex/rxjava3/core/BackpressureOverflowStrategy.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; /** diff --git a/src/main/java/io/reactivex/rxjava3/core/BackpressureStrategy.java b/src/main/java/io/reactivex/rxjava3/core/BackpressureStrategy.java index 4a260726508..f2bf8d01ae4 100644 --- a/src/main/java/io/reactivex/rxjava3/core/BackpressureStrategy.java +++ b/src/main/java/io/reactivex/rxjava3/core/BackpressureStrategy.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 682a493849c..e31a44c32c3 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; import java.util.*; @@ -18,8 +19,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; -import io.reactivex.rxjava3.core.Observable; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.*; @@ -29,7 +29,7 @@ import io.reactivex.rxjava3.internal.operators.completable.*; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.internal.operators.mixed.*; -import io.reactivex.rxjava3.internal.operators.single.*; +import io.reactivex.rxjava3.internal.operators.single.SingleDelayWithCompletable; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -52,7 +52,7 @@ * Note that as with the {@code Observable} protocol, {@code onError} and {@code onComplete} are mutually exclusive events. *

* Like {@code Observable}, a running {@code Completable} can be stopped through the {@link Disposable} instance - * provided to consumers through {@link SingleObserver#onSubscribe}. + * provided to consumers through {@link CompletableObserver#onSubscribe}. *

* Like an {@code Observable}, a {@code Completable} is lazy, can be either "hot" or "cold", synchronous or * asynchronous. {@code Completable} instances returned by the methods of this class are cold @@ -479,7 +479,7 @@ public static Completable unsafeCreate(@NonNull CompletableSource onSubscribe) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable defer(@NonNull Supplier supplier) { + public static Completable defer(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new CompletableDefer(supplier)); } @@ -503,7 +503,7 @@ public static Completable defer(@NonNull Supplier s @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable error(@NonNull Supplier supplier) { + public static Completable error(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new CompletableErrorSupplier(supplier)); } @@ -529,8 +529,8 @@ public static Completable error(@NonNull Throwable throwable) { } /** - * Returns a {@code Completable} instance that runs the given {@link Action} for each subscriber and - * emits either an unchecked exception or simply completes. + * Returns a {@code Completable} instance that runs the given {@link Action} for each {@link CompletableObserver} and + * emits either an exception or simply completes. *

* *

@@ -544,7 +544,7 @@ public static Completable error(@NonNull Throwable throwable) { * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. * *
- * @param action the {@code Action} to run for each subscribing {@link CompletableObserver} + * @param action the {@code Action} to run for each subscribing {@code CompletableObserver} * @return the new {@code Completable} instance * @throws NullPointerException if {@code action} is {@code null} */ @@ -601,6 +601,7 @@ public static Completable fromCallable(@NonNull Callable callable) { * @param future the {@code Future} to react to * @return the new {@code Completable} instance * @throws NullPointerException if {@code future} is {@code null} + * @see #fromCompletionStage(CompletionStage) */ @CheckReturnValue @NonNull @@ -630,21 +631,26 @@ public static Completable fromFuture(@NonNull Future future) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable fromMaybe(@NonNull MaybeSource maybe) { + public static <@NonNull T> Completable fromMaybe(@NonNull MaybeSource maybe) { Objects.requireNonNull(maybe, "maybe is null"); return RxJavaPlugins.onAssembly(new MaybeIgnoreElementCompletable<>(maybe)); } /** * Returns a {@code Completable} instance that runs the given {@link Runnable} for each {@link CompletableObserver} and - * emits either its exception or simply completes. + * emits either its unchecked exception or simply completes. *

* + *

+ * If the code to be wrapped needs to throw a checked or more broader {@link Throwable} exception, that + * exception has to be converted to an unchecked exception by the wrapped code itself. Alternatively, + * use the {@link #fromAction(Action)} method which allows the wrapped code to throw any {@code Throwable} + * exception and will signal it to observers as-is. *

*
Scheduler:
*
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
*
Error handling:
- *
If the {@code Runnable} throws an exception, the respective {@link Throwable} is + *
If the {@code Runnable} throws an exception, the respective {@code Throwable} is * delivered to the downstream via {@link CompletableObserver#onError(Throwable)}, * except when the downstream has disposed this {@code Completable} source. * In this latter case, the {@code Throwable} is delivered to the global error handler via @@ -654,6 +660,7 @@ public static Completable fromMaybe(@NonNull MaybeSource maybe) { * @param run the {@code Runnable} to run for each {@code CompletableObserver} * @return the new {@code Completable} instance * @throws NullPointerException if {@code run} is {@code null} + * @see #fromAction(Action) */ @CheckReturnValue @NonNull @@ -680,7 +687,7 @@ public static Completable fromRunnable(@NonNull Runnable run) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable fromObservable(@NonNull ObservableSource observable) { + public static <@NonNull T> Completable fromObservable(@NonNull ObservableSource observable) { Objects.requireNonNull(observable, "observable is null"); return RxJavaPlugins.onAssembly(new CompletableFromObservable<>(observable)); } @@ -718,7 +725,7 @@ public static Completable fromObservable(@NonNull ObservableSource observ @NonNull @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) - public static Completable fromPublisher(@NonNull Publisher publisher) { + public static <@NonNull T> Completable fromPublisher(@NonNull Publisher publisher) { Objects.requireNonNull(publisher, "publisher is null"); return RxJavaPlugins.onAssembly(new CompletableFromPublisher<>(publisher)); } @@ -740,7 +747,7 @@ public static Completable fromPublisher(@NonNull Publisher publisher) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable fromSingle(@NonNull SingleSource single) { + public static <@NonNull T> Completable fromSingle(@NonNull SingleSource single) { Objects.requireNonNull(single, "single is null"); return RxJavaPlugins.onAssembly(new CompletableFromSingle<>(single)); } @@ -981,7 +988,7 @@ private static Completable merge0(@NonNull Publisher<@NonNull ? extends Completa @SafeVarargs public static Completable mergeArrayDelayError(@NonNull CompletableSource... sources) { Objects.requireNonNull(sources, "sources is null"); - return RxJavaPlugins.onAssembly(new CompletableMergeDelayErrorArray(sources)); + return RxJavaPlugins.onAssembly(new CompletableMergeArrayDelayError(sources)); } /** @@ -1219,7 +1226,7 @@ public static Completable switchOnNextDelayError(@NonNull Publisher<@NonNull ? e @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Completable using(@NonNull Supplier resourceSupplier, + public static <@NonNull R> Completable using(@NonNull Supplier resourceSupplier, @NonNull Function sourceSupplier, @NonNull Consumer resourceCleanup) { return using(resourceSupplier, sourceSupplier, resourceCleanup, true); @@ -1255,7 +1262,7 @@ public static Completable using(@NonNull Supplier resourceSupplier, @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable using( + public static <@NonNull R> Completable using( @NonNull Supplier resourceSupplier, @NonNull Function sourceSupplier, @NonNull Consumer resourceCleanup, @@ -1902,11 +1909,12 @@ public final Completable doOnLifecycle(@NonNull Consumer onS *
Scheduler:
*
{@code doOnLifecycle} does not operate by default on a particular {@link Scheduler}.
*
- * @param onSubscribe the consumer called when a {@link CompletableObserver} subscribes. - * @param onError the consumer called when this emits an {@code onError} event - * @param onComplete the runnable called just before when the current {@code Completable} completes normally - * @param onAfterTerminate the runnable called after this {@code Completable} completes normally - * @param onDispose the {@link Runnable} called when the downstream disposes the subscription + * @param onSubscribe the {@link Consumer} called when a {@link CompletableObserver} subscribes. + * @param onError the {@code Consumer} called when this emits an {@code onError} event + * @param onComplete the {@link Action} called just before when the current {@code Completable} completes normally + * @param onTerminate the {@code Action} called just before this {@code Completable} terminates + * @param onAfterTerminate the {@code Action} called after this {@code Completable} completes normally + * @param onDispose the {@code Action} called when the downstream disposes the subscription * @return the new {@code Completable} instance * @throws NullPointerException if {@code onSubscribe}, {@code onError}, {@code onComplete} * {@code onTerminate}, {@code onAfterTerminate} or {@code onDispose} is {@code null} @@ -2173,7 +2181,7 @@ public final Completable lift(@NonNull CompletableOperator onLift) { * Maps the signal types of this {@code Completable} into a {@link Notification} of the same kind * and emits it as a single success value to downstream. *

- * + * *

*
Scheduler:
*
{@code materialize} does not operate by default on a particular {@link Scheduler}.
@@ -2187,7 +2195,7 @@ public final Completable lift(@NonNull CompletableOperator onLift) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single> materialize() { + public final <@NonNull T> Single> materialize() { return RxJavaPlugins.onAssembly(new CompletableMaterialize<>(this)); } @@ -2349,7 +2357,7 @@ public final Completable onErrorResumeWith(@NonNull CompletableSource fallback) @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe onErrorReturn(@NonNull Function itemSupplier) { + public final <@NonNull T> Maybe onErrorReturn(@NonNull Function itemSupplier) { Objects.requireNonNull(itemSupplier, "itemSupplier is null"); return RxJavaPlugins.onAssembly(new CompletableOnErrorReturn<>(this, itemSupplier)); } @@ -2377,7 +2385,7 @@ public final Maybe onErrorReturn(@NonNull Function Maybe onErrorReturnItem(@NonNull T item) { + public final <@NonNull T> Maybe onErrorReturnItem(@NonNull T item) { Objects.requireNonNull(item, "item is null"); return onErrorReturn(Functions.justFunction(item)); } @@ -2476,7 +2484,7 @@ public final Completable repeatUntil(@NonNull BooleanSupplier stop) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Completable repeatWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Completable repeatWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return fromPublisher(toFlowable().repeatWhen(handler)); } @@ -2648,7 +2656,7 @@ public final Completable retryUntil(@NonNull BooleanSupplier stop) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Completable retryWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Completable retryWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return fromPublisher(toFlowable().retryWhen(handler)); } @@ -2719,7 +2727,7 @@ public final Completable startWith(@NonNull CompletableSource other) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public final Flowable startWith(@NonNull SingleSource other) { + public final <@NonNull T> Flowable startWith(@NonNull SingleSource other) { Objects.requireNonNull(other, "other is null"); return Flowable.concat(Single.wrap(other).toFlowable(), toFlowable()); } @@ -2745,7 +2753,7 @@ public final Flowable startWith(@NonNull SingleSource other) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public final Flowable startWith(@NonNull MaybeSource other) { + public final <@NonNull T> Flowable startWith(@NonNull MaybeSource other) { Objects.requireNonNull(other, "other is null"); return Flowable.concat(Maybe.wrap(other).toFlowable(), toFlowable()); } @@ -2767,7 +2775,7 @@ public final Flowable startWith(@NonNull MaybeSource other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Observable startWith(@NonNull ObservableSource other) { + public final <@NonNull T> Observable startWith(@NonNull ObservableSource other) { Objects.requireNonNull(other, "other is null"); return Observable.wrap(other).concatWith(this.toObservable()); } @@ -2793,7 +2801,7 @@ public final Observable startWith(@NonNull ObservableSource other) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable startWith(@NonNull Publisher other) { + public final <@NonNull T> Flowable startWith(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return this.toFlowable().startWith(other); } @@ -2829,6 +2837,7 @@ public final Completable hide() { *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
*
* @return the new {@code Disposable} that can be used for disposing the subscription at any time + * @see #subscribe(Action, Consumer, DisposableContainer) */ @SchedulerSupport(SchedulerSupport.NONE) @NonNull @@ -2914,6 +2923,7 @@ public final void subscribe(@NonNull CompletableObserver observer) { * @param onError the {@link Consumer} that is called if this {@code Completable} emits an error * @return the new {@link Disposable} that can be used for disposing the subscription at any time * @throws NullPointerException if {@code onComplete} or {@code onError} is {@code null} + * @see #subscribe(Action, Consumer, DisposableContainer) */ @CheckReturnValue @NonNull @@ -2927,6 +2937,44 @@ public final Disposable subscribe(@NonNull Action onComplete, @NonNull Consumer< return observer; } + /** + * Wraps the given onXXX callbacks into a {@link Disposable} {@link CompletableObserver}, + * adds it to the given {@link DisposableContainer} and ensures, that if the upstream + * terminates or this particular {@code Disposable} is disposed, the {@code CompletableObserver} is removed + * from the given composite. + *

+ * The {@code CompletableObserver} will be removed after the callback for the terminal event has been invoked. + *

+ *
Scheduler:
+ *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param onError the callback for an upstream error + * @param onComplete the callback for an upstream completion + * @param container the {@code DisposableContainer} (such as {@link CompositeDisposable}) to add and remove the + * created {@code Disposable} {@code CompletableObserver} + * @return the {@code Disposable} that allows disposing the particular subscription. + * @throws NullPointerException + * if {@code onComplete}, {@code onError} + * or {@code container} is {@code null} + * @since 3.1.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Disposable subscribe( + @NonNull Action onComplete, + @NonNull Consumer onError, + @NonNull DisposableContainer container) { + Objects.requireNonNull(onComplete, "onComplete is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(container, "container is null"); + + DisposableAutoReleaseMultiObserver observer = new DisposableAutoReleaseMultiObserver<>( + container, Functions.emptyConsumer(), onError, onComplete); + container.add(observer); + subscribe(observer); + return observer; + } + /** * Subscribes to this {@code Completable} and calls the given {@link Action} when this {@code Completable} * completes normally. @@ -2943,16 +2991,13 @@ public final Disposable subscribe(@NonNull Action onComplete, @NonNull Consumer< * @param onComplete the {@code Action} called when this {@code Completable} completes normally * @return the new {@link Disposable} that can be used for disposing the subscription at any time * @throws NullPointerException if {@code onComplete} is {@code null} + * @see #subscribe(Action, Consumer, DisposableContainer) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) public final Disposable subscribe(@NonNull Action onComplete) { - Objects.requireNonNull(onComplete, "onComplete is null"); - - CallbackCompletableObserver observer = new CallbackCompletableObserver(onComplete); - subscribe(observer); - return observer; + return subscribe(onComplete, Functions.ON_ERROR_MISSING); } /** @@ -3166,7 +3211,7 @@ public final R to(@NonNull CompletableConverter converter) { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable toFlowable() { + public final <@NonNull T> Flowable toFlowable() { if (this instanceof FuseToFlowable) { return ((FuseToFlowable)this).fuseToFlowable(); } @@ -3211,7 +3256,7 @@ public final Future toFuture() { @SuppressWarnings("unchecked") @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Maybe toMaybe() { + public final <@NonNull T> Maybe toMaybe() { if (this instanceof FuseToMaybe) { return ((FuseToMaybe)this).fuseToMaybe(); } @@ -3234,7 +3279,7 @@ public final Maybe toMaybe() { @SuppressWarnings("unchecked") @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable toObservable() { + public final <@NonNull T> Observable toObservable() { if (this instanceof FuseToObservable) { return ((FuseToObservable)this).fuseToObservable(); } @@ -3366,7 +3411,7 @@ public final TestObserver test(boolean dispose) { * *

* Note that the operator takes an already instantiated, running or terminated {@code CompletionStage}. - * If the optional is to be created per consumer upon subscription, use {@link #defer(Supplier)} + * If the {@code CompletionStage} is to be created per consumer upon subscription, use {@link #defer(Supplier)} * around {@code fromCompletionStage}: *


      * Maybe.defer(() -> Completable.fromCompletionStage(createCompletionStage()));
@@ -3421,7 +3466,7 @@ public static Completable fromCompletionStage(@NonNull CompletionStage stage)
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final  CompletionStage toCompletionStage(@Nullable T defaultItem) {
+    public final <@Nullable T> CompletionStage toCompletionStage(T defaultItem) {
         return subscribeWith(new CompletionStageConsumer<>(true, defaultItem));
     }
 }
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableConverter.java b/src/main/java/io/reactivex/rxjava3/core/CompletableConverter.java
index 83e8f693eb5..a213c6f5abc 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableConverter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableConverter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableEmitter.java b/src/main/java/io/reactivex/rxjava3/core/CompletableEmitter.java
index 5ebb4e1877e..2c5a9811c4e 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableEmitter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableEmitter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableObserver.java b/src/main/java/io/reactivex/rxjava3/core/CompletableObserver.java
index 7c01ebfee1f..93393070477 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableObserver.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableObserver.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/core/CompletableOnSubscribe.java
index 70d79e62b69..e73fae2d5ce 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableOnSubscribe.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableOnSubscribe.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,13 +10,14 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
 
 /**
  * A functional interface that has a {@code subscribe()} method that receives
- * an instance of a {@link CompletableEmitter} instance that allows pushing
+ * a {@link CompletableEmitter} instance that allows pushing
  * an event in a cancellation-safe manner.
  */
 @FunctionalInterface
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableOperator.java b/src/main/java/io/reactivex/rxjava3/core/CompletableOperator.java
index e9b1df83cbb..f06a94f36a8 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableOperator.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableOperator.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableSource.java b/src/main/java/io/reactivex/rxjava3/core/CompletableSource.java
index 58edf9471c4..90d3853b8a1 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableSource.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableSource.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
diff --git a/src/main/java/io/reactivex/rxjava3/core/CompletableTransformer.java b/src/main/java/io/reactivex/rxjava3/core/CompletableTransformer.java
index 98a9e2aa19b..2887c4717c6 100644
--- a/src/main/java/io/reactivex/rxjava3/core/CompletableTransformer.java
+++ b/src/main/java/io/reactivex/rxjava3/core/CompletableTransformer.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/Emitter.java b/src/main/java/io/reactivex/rxjava3/core/Emitter.java
index e9ea2a18272..83410f056e0 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Emitter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Emitter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java
index ddf5b3cf7b6..39f3c63b43b 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import java.util.*;
@@ -19,12 +20,11 @@
 import org.reactivestreams.*;
 
 import io.reactivex.rxjava3.annotations.*;
-import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.disposables.*;
 import io.reactivex.rxjava3.exceptions.*;
 import io.reactivex.rxjava3.flowables.*;
 import io.reactivex.rxjava3.functions.*;
 import io.reactivex.rxjava3.internal.functions.*;
-import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier;
 import io.reactivex.rxjava3.internal.jdk8.*;
 import io.reactivex.rxjava3.internal.operators.flowable.*;
 import io.reactivex.rxjava3.internal.operators.maybe.MaybeToFlowable;
@@ -34,6 +34,7 @@
 import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler;
 import io.reactivex.rxjava3.internal.subscribers.*;
 import io.reactivex.rxjava3.internal.util.*;
+import io.reactivex.rxjava3.operators.ScalarSupplier;
 import io.reactivex.rxjava3.parallel.ParallelFlowable;
 import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import io.reactivex.rxjava3.schedulers.*;
@@ -53,7 +54,7 @@
  * 

* The documentation for this class makes use of marble diagrams. The following legend explains these diagrams: *

- * + * *

* The {@code Flowable} follows the protocol *


@@ -163,13 +164,21 @@ public abstract class Flowable<@NonNull T> implements Publisher {
      * Mirrors the one {@link Publisher} in an {@link Iterable} of several {@code Publisher}s that first either emits an item or sends
      * a termination notification.
      * 

- * + * + *

+ * When one of the {@code Publisher}s signal an item or terminates first, all subscriptions to the other + * {@code Publisher}s are canceled. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by the winning * {@code Publisher}'s backpressure behavior.
*
Scheduler:
*
{@code amb} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If any of the losing {@code Publisher}s signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param the common element type @@ -184,7 +193,7 @@ public abstract class Flowable<@NonNull T> implements Publisher { @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable amb(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable amb(@NonNull Iterable<@NonNull ? extends Publisher> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableAmb<>(null, sources)); } @@ -193,13 +202,21 @@ public static Flowable amb(@NonNull Iterable<@NonNull ? extends Publisher * Mirrors the one {@link Publisher} in an array of several {@code Publisher}s that first either emits an item or sends * a termination notification. *

- * + * + *

+ * When one of the {@code Publisher}s signal an item or terminates first, all subscriptions to the other + * {@code Publisher}s are canceled. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by the winning * {@code Publisher}'s backpressure behavior.
*
Scheduler:
*
{@code ambArray} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If any of the losing {@code Publisher}s signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param the common element type @@ -215,7 +232,7 @@ public static Flowable amb(@NonNull Iterable<@NonNull ? extends Publisher @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable ambArray(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable ambArray(@NonNull Publisher... sources) { Objects.requireNonNull(sources, "sources is null"); int len = sources.length; if (len == 0) { @@ -279,7 +296,7 @@ public static int bufferSize() { @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @NonNull - public static Flowable combineLatestArray(@NonNull Publisher<@NonNull ? extends T>[] sources, @NonNull Function combiner) { + public static <@NonNull T, @NonNull R> Flowable combineLatestArray(@NonNull Publisher[] sources, @NonNull Function combiner) { return combineLatestArray(sources, combiner, bufferSize()); } @@ -327,7 +344,7 @@ public static int bufferSize() { @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) - public static Flowable combineLatestArray(@NonNull Publisher<@NonNull ? extends T>[] sources, @NonNull Function combiner, int bufferSize) { + public static <@NonNull T, @NonNull R> Flowable combineLatestArray(@NonNull Publisher[] sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -378,7 +395,7 @@ public static Flowable combineLatestArray(@NonNull Publisher<@NonNull @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @NonNull - public static Flowable combineLatest(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, + public static <@NonNull T, @NonNull R> Flowable combineLatest(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function combiner) { return combineLatest(sources, combiner, bufferSize()); } @@ -427,7 +444,7 @@ public static Flowable combineLatestArray(@NonNull Publisher<@NonNull @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) - public static Flowable combineLatest(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, + public static <@NonNull T, @NonNull R> Flowable combineLatest(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -476,7 +493,7 @@ public static Flowable combineLatest(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @NonNull - public static Flowable combineLatestArrayDelayError(@NonNull Publisher<@NonNull ? extends T>[] sources, + public static <@NonNull T, @NonNull R> Flowable combineLatestArrayDelayError(@NonNull Publisher[] sources, @NonNull Function combiner) { return combineLatestArrayDelayError(sources, combiner, bufferSize()); } @@ -526,7 +543,7 @@ public static Flowable combineLatest(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) - public static Flowable combineLatestArrayDelayError(@NonNull Publisher<@NonNull ? extends T>[] sources, + public static <@NonNull T, @NonNull R> Flowable combineLatestArrayDelayError(@NonNull Publisher[] sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -579,7 +596,7 @@ public static Flowable combineLatest(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @NonNull - public static Flowable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, + public static <@NonNull T, @NonNull R> Flowable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function combiner) { return combineLatestDelayError(sources, combiner, bufferSize()); } @@ -629,7 +646,7 @@ public static Flowable combineLatest(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @NonNull - public static Flowable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, + public static <@NonNull T, @NonNull R> Flowable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -646,7 +663,7 @@ public static Flowable combineLatestDelayError(@NonNull Iterable<@NonN * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -674,8 +691,8 @@ public static Flowable combineLatestDelayError(@NonNull Iterable<@NonN @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, + public static <@NonNull T1, @NonNull T2, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiFunction combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -692,7 +709,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -723,9 +740,9 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Function3 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -743,7 +760,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -778,9 +795,9 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, @NonNull Function4 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -799,7 +816,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -837,10 +854,10 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, - @NonNull Publisher<@NonNull ? extends T5> source5, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, + @NonNull Publisher source5, @NonNull Function5 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -860,7 +877,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -901,10 +918,10 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, - @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, + @NonNull Publisher source5, @NonNull Publisher source6, @NonNull Function6 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -925,7 +942,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -970,11 +987,11 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, - @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, + @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Function7 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -996,7 +1013,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -1044,11 +1061,11 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, - @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, @NonNull Publisher<@NonNull ? extends T8> source8, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, + @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Publisher source8, @NonNull Function8 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -1071,7 +1088,7 @@ public static Flowable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated until that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Backpressure:
*
The returned {@code Publisher} honors backpressure from downstream. The source {@code Publisher}s @@ -1123,12 +1140,12 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable combineLatest( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, - @NonNull Publisher<@NonNull ? extends T3> source3, @NonNull Publisher<@NonNull ? extends T4> source4, - @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, @NonNull Publisher<@NonNull ? extends T8> source8, - @NonNull Publisher<@NonNull ? extends T9> source9, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Flowable combineLatest( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4, + @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Publisher source8, + @NonNull Publisher source9, @NonNull Function9 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -1147,7 +1164,7 @@ public static Flowable combineLatest( * Concatenates elements of each {@link Publisher} provided via an {@link Iterable} sequence into a single sequence * of elements without interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1167,7 +1184,7 @@ public static Flowable combineLatest( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concat(@NonNull Iterable<@NonNull ? extends Publisher> sources) { Objects.requireNonNull(sources, "sources is null"); // unlike general sources, fromIterable can only throw on a boundary because it is consumed only there return fromIterable(sources).concatMapDelayError((Function)Functions.identity(), false, 2); @@ -1177,7 +1194,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends Publis * Returns a {@code Flowable} that emits the items emitted by each of the {@link Publisher}s emitted by the source * {@code Publisher}, one after the other, without interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. Both the outer and inner {@code Publisher} @@ -1199,7 +1216,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends Publis @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return concat(sources, bufferSize()); } @@ -1207,7 +1224,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publi * Returns a {@code Flowable} that emits the items emitted by each of the {@link Publisher}s emitted by the source * {@code Publisher}, one after the other, without interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. Both the outer and inner {@code Publisher} @@ -1233,7 +1250,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publi @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int prefetch) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends Publisher> sources, int prefetch) { return fromPublisher(sources).concatMap((Function)Functions.identity(), prefetch); } @@ -1241,7 +1258,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publi * Returns a {@code Flowable} that emits the items emitted by two {@link Publisher}s, one after the other, without * interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1265,7 +1282,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Publi @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2) { + public static <@NonNull T> Flowable concat(@NonNull Publisher source1, @NonNull Publisher source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return concatArray(source1, source2); @@ -1275,7 +1292,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends T> so * Returns a {@code Flowable} that emits the items emitted by three {@link Publisher}s, one after the other, without * interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1301,9 +1318,9 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends T> so @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( - @NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, - @NonNull Publisher<@NonNull ? extends T> source3) { + public static <@NonNull T> Flowable concat( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -1314,7 +1331,7 @@ public static Flowable concat( * Returns a {@code Flowable} that emits the items emitted by four {@link Publisher}s, one after the other, without * interleaving them. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1342,9 +1359,9 @@ public static Flowable concat( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( - @NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, - @NonNull Publisher<@NonNull ? extends T> source3, @NonNull Publisher<@NonNull ? extends T> source4) { + public static <@NonNull T> Flowable concat( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -1357,7 +1374,7 @@ public static Flowable concat( *

* Note: named this way because of overload conflict with {@code concat(Publisher>}). *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1377,7 +1394,7 @@ public static Flowable concat( @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable concatArray(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArray(@NonNull Publisher... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -1392,7 +1409,7 @@ public static Flowable concatArray(@NonNull Publisher<@NonNull ? extends * Concatenates a variable number of {@link Publisher} sources and delays errors from any of them * till all terminate. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -1412,7 +1429,7 @@ public static Flowable concatArray(@NonNull Publisher<@NonNull ? extends @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable concatArrayDelayError(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArrayDelayError(@NonNull Publisher... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -1451,7 +1468,7 @@ public static Flowable concatArrayDelayError(@NonNull Publisher<@NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable concatArrayEager(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArrayEager(@NonNull Publisher... sources) { return concatArrayEager(bufferSize(), bufferSize(), sources); } @@ -1488,7 +1505,7 @@ public static Flowable concatArrayEager(@NonNull Publisher<@NonNull ? ext @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) @SafeVarargs - public static Flowable concatArrayEager(int maxConcurrency, int prefetch, @NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArrayEager(int maxConcurrency, int prefetch, @NonNull Publisher... sources) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1524,7 +1541,7 @@ public static Flowable concatArrayEager(int maxConcurrency, int prefetch, @BackpressureSupport(BackpressureKind.FULL) @SafeVarargs @NonNull - public static Flowable concatArrayEagerDelayError(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArrayEagerDelayError(@NonNull Publisher... sources) { return concatArrayEagerDelayError(bufferSize(), bufferSize(), sources); } @@ -1562,7 +1579,7 @@ public static Flowable concatArrayEagerDelayError(@NonNull Publisher<@Non @BackpressureSupport(BackpressureKind.FULL) @SafeVarargs @NonNull - public static Flowable concatArrayEagerDelayError(int maxConcurrency, int prefetch, @NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable concatArrayEagerDelayError(int maxConcurrency, int prefetch, @NonNull Publisher... sources) { return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, prefetch); } @@ -1590,7 +1607,7 @@ public static Flowable concatArrayEagerDelayError(int maxConcurrency, int @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources) { Objects.requireNonNull(sources, "sources is null"); return fromIterable(sources).concatMapDelayError((Function)Functions.identity()); } @@ -1615,7 +1632,7 @@ public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? exte @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return concatDelayError(sources, bufferSize(), true); } @@ -1644,7 +1661,7 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int prefetch, boolean tillTheEnd) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources, int prefetch, boolean tillTheEnd) { return fromPublisher(sources).concatMapDelayError((Function)Functions.identity(), tillTheEnd, prefetch); } @@ -1674,7 +1691,7 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher> sources) { return concatEager(sources, bufferSize(), bufferSize()); } @@ -1710,7 +1727,7 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends P @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1743,7 +1760,7 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends P @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return concatEager(sources, bufferSize(), bufferSize()); } @@ -1779,7 +1796,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends Publisher> sources, int maxConcurrency, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1813,7 +1830,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources) { return concatEagerDelayError(sources, bufferSize(), bufferSize()); } @@ -1850,7 +1867,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1884,7 +1901,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return concatEagerDelayError(sources, bufferSize(), bufferSize()); } @@ -1921,7 +1938,7 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources, int maxConcurrency, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1986,7 +2003,7 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @NonNull @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable create(@NonNull FlowableOnSubscribe source, @NonNull BackpressureStrategy mode) { + public static <@NonNull T> Flowable create(@NonNull FlowableOnSubscribe source, @NonNull BackpressureStrategy mode) { Objects.requireNonNull(source, "source is null"); Objects.requireNonNull(mode, "mode is null"); return RxJavaPlugins.onAssembly(new FlowableCreate<>(source, mode)); @@ -1997,7 +2014,7 @@ public static Flowable create(@NonNull FlowableOnSubscribe source, @No * that subscribes. That is, for each subscriber, the actual {@code Publisher} that subscriber observes is * determined by the factory function. *

- * + * *

* The defer {@code Subscriber} allows you to defer or delay emitting items from a {@code Publisher} until such time as a * {@code Subscriber} subscribes to the {@code Publisher}. This allows a {@code Subscriber} to easily obtain updates or a @@ -2023,7 +2040,7 @@ public static Flowable create(@NonNull FlowableOnSubscribe source, @No @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable defer(@NonNull Supplier> supplier) { + public static <@NonNull T> Flowable defer(@NonNull Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new FlowableDefer<>(supplier)); } @@ -2032,7 +2049,7 @@ public static Flowable defer(@NonNull Supplier - * + * *

*
Backpressure:
*
This source doesn't produce any elements and effectively ignores downstream backpressure.
@@ -2050,7 +2067,7 @@ public static Flowable defer(@NonNull Supplier Flowable empty() { + public static <@NonNull T> Flowable empty() { return RxJavaPlugins.onAssembly((Flowable) FlowableEmpty.INSTANCE); } @@ -2058,7 +2075,7 @@ public static Flowable empty() { * Returns a {@code Flowable} that invokes a {@link Subscriber}'s {@link Subscriber#onError onError} method when the * {@code Subscriber} subscribes to it. *

- * + * *

*
Backpressure:
*
This source doesn't produce any elements and effectively ignores downstream backpressure.
@@ -2078,7 +2095,7 @@ public static Flowable empty() { @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable error(@NonNull Supplier supplier) { + public static <@NonNull T> Flowable error(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new FlowableError<>(supplier)); } @@ -2087,7 +2104,7 @@ public static Flowable error(@NonNull Supplier suppl * Returns a {@code Flowable} that invokes a {@link Subscriber}'s {@link Subscriber#onError onError} method when the * {@code Subscriber} subscribes to it. *

- * + * *

*
Backpressure:
*
This source doesn't produce any elements and effectively ignores downstream backpressure.
@@ -2107,13 +2124,13 @@ public static Flowable error(@NonNull Supplier suppl @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable error(@NonNull Throwable throwable) { + public static <@NonNull T> Flowable error(@NonNull Throwable throwable) { Objects.requireNonNull(throwable, "throwable is null"); return error(Functions.justSupplier(throwable)); } /** - * Returns a {@code Flowable} instance that runs the given {@link Action} for each subscriber and + * Returns a {@code Flowable} instance that runs the given {@link Action} for each {@link Subscriber} and * emits either its exception or simply completes. *

* @@ -2131,7 +2148,7 @@ public static Flowable error(@NonNull Throwable throwable) { *

*
* @param the target type - * @param action the {@code Action} to run for each subscriber + * @param action the {@code Action} to run for each {@code Subscriber} * @return the new {@code Flowable} instance * @throws NullPointerException if {@code action} is {@code null} * @since 3.0.0 @@ -2140,7 +2157,7 @@ public static Flowable error(@NonNull Throwable throwable) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.PASS_THROUGH) - public static Flowable fromAction(@NonNull Action action) { + public static <@NonNull T> Flowable fromAction(@NonNull Action action) { Objects.requireNonNull(action, "action is null"); return RxJavaPlugins.onAssembly(new FlowableFromAction<>(action)); } @@ -2148,7 +2165,7 @@ public static Flowable fromAction(@NonNull Action action) { /** * Converts an array into a {@link Publisher} that emits the items in the array. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and iterates the given {@code array} @@ -2185,7 +2202,7 @@ public static Flowable fromAction(@NonNull Action action) { * Returns a {@code Flowable} that, when a {@link Subscriber} subscribes to it, invokes a function you specify and then * emits the value returned from that function. *

- * + * *

* This allows you to defer the execution of the function you specify until a {@code Subscriber} subscribes to the * {@link Publisher}. That is to say, it makes the function "lazy." @@ -2242,7 +2259,7 @@ public static Flowable fromAction(@NonNull Action action) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.PASS_THROUGH) - public static Flowable fromCompletable(@NonNull CompletableSource completableSource) { + public static <@NonNull T> Flowable fromCompletable(@NonNull CompletableSource completableSource) { Objects.requireNonNull(completableSource, "completableSource is null"); return RxJavaPlugins.onAssembly(new FlowableFromCompletable<>(completableSource)); } @@ -2250,7 +2267,7 @@ public static Flowable fromCompletable(@NonNull CompletableSource complet /** * Converts a {@link Future} into a {@link Publisher}. *

- * + * *

* The operator calls {@link Future#get()}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -2292,7 +2309,7 @@ public static Flowable fromCompletable(@NonNull CompletableSource complet /** * Converts a {@link Future} into a {@link Publisher}, with a timeout on the {@code Future}. *

- * + * *

* The operator calls {@link Future#get(long, TimeUnit)}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -2339,7 +2356,7 @@ public static Flowable fromCompletable(@NonNull CompletableSource complet /** * Converts an {@link Iterable} sequence into a {@link Publisher} that emits the items in the sequence. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and iterates the given {@code iterable} @@ -2362,7 +2379,7 @@ public static Flowable fromCompletable(@NonNull CompletableSource complet @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static <@NonNull T> Flowable fromIterable(@NonNull Iterable<@NonNull ? extends T> source) { + public static <@NonNull T> Flowable fromIterable(@NonNull Iterable source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new FlowableFromIterable<>(source)); } @@ -2389,7 +2406,7 @@ public static Flowable fromCompletable(@NonNull CompletableSource complet @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static Flowable fromMaybe(@NonNull MaybeSource maybe) { + public static <@NonNull T> Flowable fromMaybe(@NonNull MaybeSource maybe) { Objects.requireNonNull(maybe, "maybe is null"); return RxJavaPlugins.onAssembly(new MaybeToFlowable<>(maybe)); } @@ -2437,7 +2454,7 @@ public static Flowable fromMaybe(@NonNull MaybeSource maybe) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable fromObservable(@NonNull ObservableSource source, @NonNull BackpressureStrategy strategy) { + public static <@NonNull T> Flowable fromObservable(@NonNull ObservableSource source, @NonNull BackpressureStrategy strategy) { Objects.requireNonNull(source, "source is null"); Objects.requireNonNull(strategy, "strategy is null"); Flowable f = new FlowableFromObservable<>(source); @@ -2487,7 +2504,7 @@ public static Flowable fromObservable(@NonNull ObservableSource source @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings("unchecked") - public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extends T> publisher) { + public static <@NonNull T> Flowable fromPublisher(@NonNull Publisher publisher) { if (publisher instanceof Flowable) { return RxJavaPlugins.onAssembly((Flowable)publisher); } @@ -2497,17 +2514,22 @@ public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extend } /** - * Returns a {@code Flowable} instance that runs the given {@link Runnable} for each subscriber and - * emits either its exception or simply completes. + * Returns a {@code Flowable} instance that runs the given {@link Runnable} for each {@link Subscriber} and + * emits either its unchecked exception or simply completes. *

* + *

+ * If the code to be wrapped needs to throw a checked or more broader {@link Throwable} exception, that + * exception has to be converted to an unchecked exception by the wrapped code itself. Alternatively, + * use the {@link #fromAction(Action)} method which allows the wrapped code to throw any {@code Throwable} + * exception and will signal it to observers as-is. *

*
Backpressure:
*
This source doesn't produce any elements and effectively ignores downstream backpressure.
*
Scheduler:
*
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
*
Error handling:
- *
If the {@code Runnable} throws an exception, the respective {@link Throwable} is + *
If the {@code Runnable} throws an exception, the respective {@code Throwable} is * delivered to the downstream via {@link Subscriber#onError(Throwable)}, * except when the downstream has canceled the resulting {@code Flowable} source. * In this latter case, the {@code Throwable} is delivered to the global error handler via @@ -2515,16 +2537,17 @@ public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extend *
*
* @param the target type - * @param run the {@code Runnable} to run for each subscriber + * @param run the {@code Runnable} to run for each {@code Subscriber} * @return the new {@code Flowable} instance * @throws NullPointerException if {@code run} is {@code null} * @since 3.0.0 + * @see #fromAction(Action) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.PASS_THROUGH) - public static Flowable fromRunnable(@NonNull Runnable run) { + public static <@NonNull T> Flowable fromRunnable(@NonNull Runnable run) { Objects.requireNonNull(run, "run is null"); return RxJavaPlugins.onAssembly(new FlowableFromRunnable<>(run)); } @@ -2550,7 +2573,7 @@ public static Flowable fromRunnable(@NonNull Runnable run) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static Flowable fromSingle(@NonNull SingleSource source) { + public static <@NonNull T> Flowable fromSingle(@NonNull SingleSource source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new SingleToFlowable<>(source)); } @@ -2559,7 +2582,7 @@ public static Flowable fromSingle(@NonNull SingleSource source) { * Returns a {@code Flowable} that, when a {@link Subscriber} subscribes to it, invokes a supplier function you specify and then * emits the value returned from that function. *

- * + * *

* This allows you to defer the execution of the function you specify until a {@code Subscriber} subscribes to the * {@link Publisher}. That is to say, it makes the function "lazy." @@ -2623,7 +2646,7 @@ public static Flowable fromSingle(@NonNull SingleSource source) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable generate(@NonNull Consumer<@NonNull Emitter> generator) { + public static <@NonNull T> Flowable generate(@NonNull Consumer<@NonNull Emitter> generator) { Objects.requireNonNull(generator, "generator is null"); return generate(Functions.nullSupplier(), FlowableInternalHelper.simpleGenerator(generator), @@ -2658,7 +2681,7 @@ public static Flowable generate(@NonNull Consumer<@NonNull Emitter> ge @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator) { + public static <@NonNull T, @NonNull S> Flowable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator) { Objects.requireNonNull(generator, "generator is null"); return generate(initialState, FlowableInternalHelper.simpleBiGenerator(generator), Functions.emptyConsumer()); @@ -2694,7 +2717,7 @@ public static Flowable generate(@NonNull Supplier initialState, @No @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator, + public static <@NonNull T, @NonNull S> Flowable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator, @NonNull Consumer disposeState) { Objects.requireNonNull(generator, "generator is null"); return generate(initialState, FlowableInternalHelper.simpleBiGenerator(generator), disposeState); @@ -2729,7 +2752,7 @@ public static Flowable generate(@NonNull Supplier initialState, @No @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator) { + public static <@NonNull T, @NonNull S> Flowable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator) { return generate(initialState, generator, Functions.emptyConsumer()); } @@ -2764,7 +2787,7 @@ public static Flowable generate(@NonNull Supplier initialState, @No @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator, @NonNull Consumer disposeState) { + public static <@NonNull T, @NonNull S> Flowable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator, @NonNull Consumer disposeState) { Objects.requireNonNull(initialState, "initialState is null"); Objects.requireNonNull(generator, "generator is null"); Objects.requireNonNull(disposeState, "disposeState is null"); @@ -2775,7 +2798,7 @@ public static Flowable generate(@NonNull Supplier initialState, @No * Returns a {@code Flowable} that emits a {@code 0L} after the {@code initialDelay} and ever-increasing numbers * after each {@code period} of time thereafter. *

- * + * *

*
Backpressure:
*
The operator generates values based on time and ignores downstream backpressure which @@ -2808,7 +2831,7 @@ public static Flowable interval(long initialDelay, long period, @NonNull T * Returns a {@code Flowable} that emits a {@code 0L} after the {@code initialDelay} and ever-increasing numbers * after each {@code period} of time thereafter, on a specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator generates values based on time and ignores downstream backpressure which @@ -2844,7 +2867,7 @@ public static Flowable interval(long initialDelay, long period, @NonNull T /** * Returns a {@code Flowable} that emits a sequential number every specified interval of time. *

- * + * *

*
Backpressure:
*
The operator signals a {@link MissingBackpressureException} if the downstream @@ -2873,7 +2896,7 @@ public static Flowable interval(long period, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits a sequential number every specified interval of time, on a * specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator generates values based on time and ignores downstream backpressure which @@ -2921,11 +2944,12 @@ public static Flowable interval(long period, @NonNull TimeUnit unit, @NonN * @throws IllegalArgumentException * if {@code count} is less than zero, or if {@code start} + {@code count} − 1 exceeds * {@link Long#MAX_VALUE} + * @see #range(int, int) */ @CheckReturnValue + @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.COMPUTATION) - @NonNull public static Flowable intervalRange(long start, long count, long initialDelay, long period, @NonNull TimeUnit unit) { return intervalRange(start, count, initialDelay, period, unit, Schedulers.computation()); } @@ -2977,7 +3001,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Returns a {@code Flowable} that signals the given (constant reference) item and then completes. *

- * + * *

* Note that the item is taken and re-emitted as is and not computed by any means by {@code just}. Use {@link #fromCallable(Callable)} * to generate a single item on demand (when {@link Subscriber}s subscribe to it). @@ -3017,7 +3041,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts two items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3049,7 +3073,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts three items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3084,7 +3108,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts four items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3123,7 +3147,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts five items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3165,7 +3189,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts six items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3210,7 +3234,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts seven items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3259,7 +3283,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts eight items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3311,7 +3335,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts nine items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3366,7 +3390,7 @@ public static Flowable intervalRange(long start, long count, long initialD /** * Converts ten items into a {@link Publisher} that emits those items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals each value on-demand (i.e., when requested).
@@ -3426,7 +3450,7 @@ public static Flowable intervalRange(long start, long count, long initialD * Flattens an {@link Iterable} of {@link Publisher}s into one {@code Publisher}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code Publisher}s. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3470,7 +3494,7 @@ public static Flowable intervalRange(long start, long count, long initialD @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).flatMap((Function)Functions.identity(), false, maxConcurrency, bufferSize); } @@ -3478,7 +3502,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish * Flattens an array of {@link Publisher}s into one {@code Publisher}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code Publisher}s. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3523,14 +3547,14 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArray(int maxConcurrency, int bufferSize, @NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable mergeArray(int maxConcurrency, int bufferSize, @NonNull Publisher... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), false, maxConcurrency, bufferSize); } /** * Flattens an {@link Iterable} of {@link Publisher}s into one {@code Publisher}, without any transformation. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3568,7 +3592,7 @@ public static Flowable mergeArray(int maxConcurrency, int bufferSize, @No @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher> sources) { return fromIterable(sources).flatMap((Function)Functions.identity()); } @@ -3576,7 +3600,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish * Flattens an {@link Iterable} of {@link Publisher}s into one {@code Publisher}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code Publisher}s. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3618,7 +3642,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency) { + public static <@NonNull T> Flowable merge(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency) { return fromIterable(sources).flatMap((Function)Functions.identity(), maxConcurrency); } @@ -3626,7 +3650,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish * Flattens a {@link Publisher} that emits {@code Publisher}s into a single {@code Publisher} that emits the items emitted by * thos {@code Publisher}s , without any transformation. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3664,7 +3688,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends Publish @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable merge(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return merge(sources, bufferSize()); } @@ -3673,7 +3697,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends Publis * those {@code Publisher}s, without any transformation, while limiting the maximum number of concurrent * subscriptions to these {@code Publisher}s. *

- * + * *

* You can combine the items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3716,14 +3740,14 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends Publis @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency) { + public static <@NonNull T> Flowable merge(@NonNull Publisher<@NonNull ? extends Publisher> sources, int maxConcurrency) { return fromPublisher(sources).flatMap((Function)Functions.identity(), maxConcurrency); } /** * Flattens an array of {@link Publisher}s into one {@code Publisher}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3762,14 +3786,14 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends Publis @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArray(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable mergeArray(@NonNull Publisher... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), sources.length); } /** * Flattens two {@link Publisher}s into a single {@code Publisher}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3809,7 +3833,7 @@ public static Flowable mergeArray(@NonNull Publisher<@NonNull ? extends T @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2) { + public static <@NonNull T> Flowable merge(@NonNull Publisher source1, @NonNull Publisher source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return fromArray(source1, source2).flatMap((Function)Functions.identity(), false, 2); @@ -3818,7 +3842,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> sou /** * Flattens three {@link Publisher}s into a single {@code Publisher}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3860,7 +3884,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> sou @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, @NonNull Publisher<@NonNull ? extends T> source3) { + public static <@NonNull T> Flowable merge(@NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -3870,7 +3894,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> sou /** * Flattens four {@link Publisher}s into a single {@code Publisher}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code merge} method. @@ -3914,9 +3938,9 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends T> sou @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge( - @NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, - @NonNull Publisher<@NonNull ? extends T> source3, @NonNull Publisher<@NonNull ? extends T> source4) { + public static <@NonNull T> Flowable merge( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -3933,7 +3957,7 @@ public static Flowable merge( * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -3957,7 +3981,7 @@ public static Flowable merge( @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources) { return fromIterable(sources).flatMap((Function)Functions.identity(), true); } @@ -3970,7 +3994,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -3999,7 +4023,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).flatMap((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -4012,7 +4036,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4042,7 +4066,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArrayDelayError(int maxConcurrency, int bufferSize, @NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable mergeArrayDelayError(int maxConcurrency, int bufferSize, @NonNull Publisher... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -4055,7 +4079,7 @@ public static Flowable mergeArrayDelayError(int maxConcurrency, int buffe * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4082,7 +4106,7 @@ public static Flowable mergeArrayDelayError(int maxConcurrency, int buffe @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends Publisher> sources, int maxConcurrency) { return fromIterable(sources).flatMap((Function)Functions.identity(), true, maxConcurrency); } @@ -4095,7 +4119,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4119,7 +4143,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return mergeDelayError(sources, bufferSize()); } @@ -4133,7 +4157,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4161,7 +4185,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources, int maxConcurrency) { return fromPublisher(sources).flatMap((Function)Functions.identity(), true, maxConcurrency); } @@ -4174,7 +4198,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4199,7 +4223,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArrayDelayError(@NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T> Flowable mergeArrayDelayError(@NonNull Publisher... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), true, sources.length); } @@ -4212,7 +4236,7 @@ public static Flowable mergeArrayDelayError(@NonNull Publisher<@NonNull ? * notify of an error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from * propagating that error notification until all of the merged {@code Publisher}s have finished emitting items. *

- * + * *

* Even if both merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4238,7 +4262,7 @@ public static Flowable mergeArrayDelayError(@NonNull Publisher<@NonNull ? @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher source1, @NonNull Publisher source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return fromArray(source1, source2).flatMap((Function)Functions.identity(), true, 2); @@ -4254,7 +4278,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * from propagating that error notification until all of the merged {@code Publisher}s have finished emitting * items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4282,7 +4306,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, @NonNull Publisher<@NonNull ? extends T> source3) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -4299,7 +4323,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * will refrain from propagating that error notification until all of the merged {@code Publisher}s have finished * emitting items. *

- * + * *

* Even if multiple merged {@code Publisher}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Subscriber}s once. @@ -4329,9 +4353,9 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError( - @NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, - @NonNull Publisher<@NonNull ? extends T> source3, @NonNull Publisher<@NonNull ? extends T> source4) { + public static <@NonNull T> Flowable mergeDelayError( + @NonNull Publisher source1, @NonNull Publisher source2, + @NonNull Publisher source3, @NonNull Publisher source4) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); @@ -4342,7 +4366,7 @@ public static Flowable mergeDelayError( /** * Returns a {@code Flowable} that never sends any items or notifications to a {@link Subscriber}. *

- * + * *

* This {@link Publisher} is useful primarily for testing purposes. *

@@ -4362,14 +4386,14 @@ public static Flowable mergeDelayError( @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings("unchecked") @NonNull - public static Flowable never() { + public static <@NonNull T> Flowable never() { return RxJavaPlugins.onAssembly((Flowable) FlowableNever.INSTANCE); } /** * Returns a {@code Flowable} that emits a sequence of {@link Integer}s within a specified range. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals values on-demand (i.e., when requested).
@@ -4386,6 +4410,8 @@ public static Flowable never() { * if {@code count} is less than zero, or if {@code start} + {@code count} − 1 exceeds * {@link Integer#MAX_VALUE} * @see ReactiveX operators documentation: Range + * @see #rangeLong(long, long) + * @see #intervalRange(long, long, long, long, TimeUnit) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @@ -4410,7 +4436,7 @@ public static Flowable range(int start, int count) { /** * Returns a {@code Flowable} that emits a sequence of {@link Long}s within a specified range. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and signals values on-demand (i.e., when requested).
@@ -4457,7 +4483,7 @@ public static Flowable rangeLong(long start, long count) { * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link Publisher} sequences are the * same by comparing the items emitted by each {@code Publisher} pairwise. *

- * + * *

*
Backpressure:
*
This operator honors downstream backpressure and expects both of its sources @@ -4480,7 +4506,7 @@ public static Flowable rangeLong(long start, long count) { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2) { + public static <@NonNull T> Single sequenceEqual(@NonNull Publisher source1, @NonNull Publisher source2) { return sequenceEqual(source1, source2, ObjectHelper.equalsPredicate(), bufferSize()); } @@ -4489,7 +4515,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex * same by comparing the items emitted by each {@code Publisher} pairwise based on the results of a specified * equality function. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The source {@code Publisher}s are expected to honor @@ -4514,7 +4540,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, + public static <@NonNull T> Single sequenceEqual(@NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiPredicate isEqual) { return sequenceEqual(source1, source2, isEqual, bufferSize()); } @@ -4524,7 +4550,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex * same by comparing the items emitted by each {@code Publisher} pairwise based on the results of a specified * equality function. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The source {@code Publisher}s are expected to honor @@ -4552,7 +4578,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Single sequenceEqual(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, + public static <@NonNull T> Single sequenceEqual(@NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiPredicate isEqual, int bufferSize) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -4565,7 +4591,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link Publisher} sequences are the * same by comparing the items emitted by each {@code Publisher} pairwise. *

- * + * *

*
Backpressure:
*
This operator honors downstream backpressure and expects both of its sources @@ -4591,7 +4617,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull Publisher<@NonNull ? extends T> source1, @NonNull Publisher<@NonNull ? extends T> source2, int bufferSize) { + public static <@NonNull T> Single sequenceEqual(@NonNull Publisher source1, @NonNull Publisher source2, int bufferSize) { return sequenceEqual(source1, source2, ObjectHelper.equalsPredicate(), bufferSize); } @@ -4599,7 +4625,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex * Converts a {@link Publisher} that emits {@code Publisher}s into a {@code Publisher} that emits the items emitted by the * most recently emitted of those {@code Publisher}s. *

- * + * *

* {@code switchOnNext} subscribes to a {@code Publisher} that emits {@code Publisher}s. Each time it observes one of * these emitted {@code Publisher}s, the {@code Publisher} returned by {@code switchOnNext} begins emitting the items @@ -4633,7 +4659,7 @@ public static Single sequenceEqual(@NonNull Publisher<@NonNull ? ex @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int bufferSize) { + public static <@NonNull T> Flowable switchOnNext(@NonNull Publisher> sources, int bufferSize) { return fromPublisher(sources).switchMap((Function)Functions.identity(), bufferSize); } @@ -4641,7 +4667,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends * Converts a {@link Publisher} that emits {@code Publisher}s into a {@code Publisher} that emits the items emitted by the * most recently emitted of those {@code Publisher}s. *

- * + * *

* {@code switchOnNext} subscribes to a {@code Publisher} that emits {@code Publisher}s. Each time it observes one of * these emitted {@code Publisher}s, the {@code Publisher} returned by {@code switchOnNext} begins emitting the items @@ -4672,7 +4698,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return fromPublisher(sources).switchMap((Function)Functions.identity()); } @@ -4680,7 +4706,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends * Converts a {@link Publisher} that emits {@code Publisher}s into a {@code Publisher} that emits the items emitted by the * most recently emitted of those {@code Publisher}s and delays any exception until all {@code Publisher}s terminate. *

- * + * *

* {@code switchOnNext} subscribes to a {@code Publisher} that emits {@code Publisher}s. Each time it observes one of * these emitted {@code Publisher}s, the {@code Publisher} returned by {@code switchOnNext} begins emitting the items @@ -4712,7 +4738,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + public static <@NonNull T> Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources) { return switchOnNextDelayError(sources, bufferSize()); } @@ -4720,7 +4746,7 @@ public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull * Converts a {@link Publisher} that emits {@code Publisher}s into a {@code Publisher} that emits the items emitted by the * most recently emitted of those {@code Publisher}s and delays any exception until all {@code Publisher}s terminate. *

- * + * *

* {@code switchOnNext} subscribes to a {@code Publisher} that emits {@code Publisher}s. Each time it observes one of * these emitted {@code Publisher}s, the {@code Publisher} returned by {@code switchOnNext} begins emitting the items @@ -4755,14 +4781,14 @@ public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int prefetch) { - return fromPublisher(sources).switchMapDelayError(Functions.>identity(), prefetch); + public static <@NonNull T> Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends Publisher> sources, int prefetch) { + return fromPublisher(sources).switchMapDelayError(Functions.>identity(), prefetch); } /** * Returns a {@code Flowable} that emits {@code 0L} after a specified delay, and then completes. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. If the downstream needs a slower rate @@ -4791,7 +4817,7 @@ public static Flowable timer(long delay, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits {@code 0L} after a specified delay, on a specified {@link Scheduler}, and then * completes. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. If the downstream needs a slower rate @@ -4844,7 +4870,7 @@ public static Flowable timer(long delay, @NonNull TimeUnit unit, @NonNull @NonNull @BackpressureSupport(BackpressureKind.NONE) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable unsafeCreate(@NonNull Publisher onSubscribe) { + public static <@NonNull T> Flowable unsafeCreate(@NonNull Publisher onSubscribe) { Objects.requireNonNull(onSubscribe, "onSubscribe is null"); if (onSubscribe instanceof Flowable) { throw new IllegalArgumentException("unsafeCreate(Flowable) should be upgraded"); @@ -4857,7 +4883,7 @@ public static Flowable unsafeCreate(@NonNull Publisher onSubscribe) { * that resource and calls the provided {@code resourceDisposer} function if this inner source terminates or the * downstream cancels the flow. *

- * + * *

*
Backpressure:
*
The operator is a pass-through for backpressure and otherwise depends on the @@ -4882,9 +4908,9 @@ public static Flowable unsafeCreate(@NonNull Publisher onSubscribe) { @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable using( + public static <@NonNull T, @NonNull D> Flowable using( @NonNull Supplier resourceSupplier, - @NonNull Function> sourceSupplier, + @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup) { return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } @@ -4894,7 +4920,7 @@ public static Flowable using( * that resource and calls the provided {@code resourceDisposer} function if this inner source terminates or the * downstream disposes the flow; doing it before these end-states have been reached if {@code eager == true}, after otherwise. *

- * + * *

*
Backpressure:
*
The operator is a pass-through for backpressure and otherwise depends on the @@ -4925,9 +4951,9 @@ public static Flowable using( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable using( + public static <@NonNull T, @NonNull D> Flowable using( @NonNull Supplier resourceSupplier, - @NonNull Function> sourceSupplier, + @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); @@ -4960,7 +4986,7 @@ public static Flowable using( * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -4985,7 +5011,7 @@ public static Flowable using( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, @NonNull Function zipper) { + public static <@NonNull T, @NonNull R> Flowable zip(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function zipper) { Objects.requireNonNull(zipper, "zipper is null"); Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableZip<>(null, sources, zipper, bufferSize(), false)); @@ -5015,7 +5041,7 @@ public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publis * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -5046,7 +5072,7 @@ public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publis @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, + public static <@NonNull T, @NonNull R> Flowable zip(@NonNull Iterable<@NonNull ? extends Publisher> sources, @NonNull Function zipper, boolean delayError, int bufferSize) { Objects.requireNonNull(zipper, "zipper is null"); @@ -5059,7 +5085,7 @@ public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publis * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -5108,8 +5134,8 @@ public static Flowable zip(@NonNull Iterable<@NonNull ? extends Publis @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, + public static <@NonNull T1, @NonNull T2, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiFunction zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5121,7 +5147,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -5171,8 +5197,8 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, + public static <@NonNull T1, @NonNull T2, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiFunction zipper, boolean delayError) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5184,7 +5210,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -5236,8 +5262,8 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, + public static <@NonNull T1, @NonNull T2, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull BiFunction zipper, boolean delayError, int bufferSize) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5249,7 +5275,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * three items emitted, in sequence, by three other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -5302,8 +5328,8 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, @NonNull Function3 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5316,7 +5342,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * four items emitted, in sequence, by four other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -5373,9 +5399,9 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Function4 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5389,7 +5415,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * five items emitted, in sequence, by five other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -5449,9 +5475,9 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, @NonNull Publisher<@NonNull ? extends T5> source5, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Publisher source5, @NonNull Function5 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5466,7 +5492,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * six items emitted, in sequence, by six other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by each source {@code Publisher}, the @@ -5529,9 +5555,9 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Publisher source5, @NonNull Publisher source6, @NonNull Function6 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5547,7 +5573,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * seven items emitted, in sequence, by seven other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by each source {@code Publisher}, the @@ -5613,10 +5639,10 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Function7 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5633,7 +5659,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * eight items emitted, in sequence, by eight other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by each source {@code Publisher}, the @@ -5702,10 +5728,10 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, @NonNull Publisher<@NonNull ? extends T8> source8, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Publisher source8, @NonNull Function8 zipper) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -5723,7 +5749,7 @@ public static Flowable zip( * Returns a {@code Flowable} that emits the results of a specified combiner function applied to combinations of * nine items emitted, in sequence, by nine other {@link Publisher}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the new {@code Publisher} * will be the result of the function applied to the first item emitted by each source {@code Publisher}, the @@ -5796,10 +5822,10 @@ public static Flowable zip( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable zip( - @NonNull Publisher<@NonNull ? extends T1> source1, @NonNull Publisher<@NonNull ? extends T2> source2, @NonNull Publisher<@NonNull ? extends T3> source3, - @NonNull Publisher<@NonNull ? extends T4> source4, @NonNull Publisher<@NonNull ? extends T5> source5, @NonNull Publisher<@NonNull ? extends T6> source6, - @NonNull Publisher<@NonNull ? extends T7> source7, @NonNull Publisher<@NonNull ? extends T8> source8, @NonNull Publisher<@NonNull ? extends T9> source9, + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Flowable zip( + @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, + @NonNull Publisher source4, @NonNull Publisher source5, @NonNull Publisher source6, + @NonNull Publisher source7, @NonNull Publisher source8, @NonNull Publisher source9, @NonNull Function9 zipper) { Objects.requireNonNull(source1, "source1 is null"); @@ -5840,7 +5866,7 @@ public static Flowable zip( * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -5871,8 +5897,8 @@ public static Flowable zip( @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable zipArray(@NonNull Function zipper, - boolean delayError, int bufferSize, @NonNull Publisher<@NonNull ? extends T>... sources) { + public static <@NonNull T, @NonNull R> Flowable zipArray(@NonNull Function zipper, + boolean delayError, int bufferSize, @NonNull Publisher... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -5890,7 +5916,7 @@ public static Flowable zipArray(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -5918,13 +5944,22 @@ public final Single all(@NonNull Predicate predicate) { * Mirrors the {@link Publisher} (current or provided) that first either emits an item or sends a termination * notification. *

- * + * + *

+ * When the current {@code Flowable} signals an item or terminates first, the subscription to the other + * {@code Publisher} is canceled. If the other {@code Publisher} signals an item or terminates first, + * the subscription to the current {@code Flowable} is canceled. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by the winning * {@code Publisher}'s backpressure behavior.
*
Scheduler:
*
{@code ambWith} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If the losing {@code Publisher} signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param other @@ -5938,7 +5973,7 @@ public final Single all(@NonNull Predicate predicate) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable ambWith(@NonNull Publisher<@NonNull ? extends T> other) { + public final Flowable ambWith(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return ambArray(this, other); } @@ -5948,7 +5983,7 @@ public final Flowable ambWith(@NonNull Publisher<@NonNull ? extends T> other) * specified condition, otherwise {@code false}. Note: this always emits {@code false} if the * current {@code Flowable} is empty. *

- * + * *

* In Rx.Net this is the {@code any} operator but we renamed it in RxJava to better match Java naming * idioms. @@ -6047,7 +6082,7 @@ public final T blockingFirst(@NonNull T defaultItem) { * {@link Consumer} with each upstream item on the current thread until the * upstream terminates. *

- * + * *

* Note: the method will only return if the upstream terminates or the current * thread is interrupted. @@ -6088,7 +6123,7 @@ public final void blockingForEach(@NonNull Consumer onNext) { * {@link Consumer} with each upstream item on the current thread until the * upstream terminates. *

- * + * *

* Note: the method will only return if the upstream terminates or the current * thread is interrupted. @@ -6139,7 +6174,7 @@ public final void blockingForEach(@NonNull Consumer onNext, int buffe /** * Converts this {@code Flowable} into an {@link Iterable}. *

- * + * *

*
Backpressure:
*
The operator expects the upstream to honor backpressure otherwise the returned @@ -6162,7 +6197,7 @@ public final Iterable blockingIterable() { /** * Converts this {@code Flowable} into an {@link Iterable}. *

- * + * *

*
Backpressure:
*
The operator expects the upstream to honor backpressure otherwise the returned @@ -6190,7 +6225,7 @@ public final Iterable blockingIterable(int bufferSize) { * Returns the last item emitted by this {@code Flowable}, or throws * {@link NoSuchElementException} if this {@code Flowable} emits no items. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6226,7 +6261,7 @@ public final T blockingLast() { * Returns the last item emitted by this {@code Flowable}, or a default value if it emits no * items. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6289,7 +6324,7 @@ public final Iterable blockingLatest() { * Returns an {@link Iterable} that always returns the item most recently emitted by this * {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6318,7 +6353,7 @@ public final Iterable blockingMostRecent(@NonNull T initialItem) { * Returns an {@link Iterable} that blocks until this {@code Flowable} emits another item, then * returns that item. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6342,7 +6377,7 @@ public final Iterable blockingNext() { * If this {@code Flowable} completes after emitting a single item, return that item, otherwise * throw a {@link NoSuchElementException}. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6371,7 +6406,7 @@ public final T blockingSingle() { * more than one item, throw an {@link IllegalArgumentException}; if it emits no items, return a default * value. *

- * + * *

*
Backpressure:
*
The operator consumes the current {@code Flowable} in an unbounded manner @@ -6646,7 +6681,7 @@ public final void blockingSubscribe(@NonNull Consumer onNext, @NonNul */ @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public final void blockingSubscribe(@NonNull Subscriber<@NonNull ? super T> subscriber) { + public final void blockingSubscribe(@NonNull Subscriber subscriber) { Objects.requireNonNull(subscriber, "subscriber is null"); FlowableBlockingSubscribe.subscribe(this, subscriber); } @@ -6658,7 +6693,7 @@ public final void blockingSubscribe(@NonNull Subscriber<@NonNull ? super T> subs * current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and expects the current {@code Flowable} to honor it as @@ -6689,7 +6724,7 @@ public final Flowable> buffer(int count) { * current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and expects the current {@code Flowable} to honor it as @@ -6724,7 +6759,7 @@ public final Flowable> buffer(int count, int skip) { * current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and expects the current {@code Flowable} to honor it as @@ -6753,7 +6788,7 @@ public final Flowable> buffer(int count, int skip) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final > Flowable buffer(int count, int skip, @NonNull Supplier bufferSupplier) { + public final <@NonNull U extends Collection> Flowable buffer(int count, int skip, @NonNull Supplier bufferSupplier) { ObjectHelper.verifyPositive(count, "count"); ObjectHelper.verifyPositive(skip, "skip"); Objects.requireNonNull(bufferSupplier, "bufferSupplier is null"); @@ -6767,7 +6802,7 @@ public final > Flowable buffer(int count, int * current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and expects the current {@code Flowable} to honor it as @@ -6792,7 +6827,7 @@ public final > Flowable buffer(int count, int @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Flowable buffer(int count, @NonNull Supplier bufferSupplier) { + public final <@NonNull U extends Collection> Flowable buffer(int count, @NonNull Supplier bufferSupplier) { return buffer(count, count, bufferSupplier); } @@ -6804,7 +6839,7 @@ public final > Flowable buffer(int count, @No * current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -6840,7 +6875,7 @@ public final Flowable> buffer(long timespan, long timeskip, @NonNull Tim * notification the event is passed on immediately without first emitting the buffer it is in the process of * assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -6878,7 +6913,7 @@ public final Flowable> buffer(long timespan, long timeskip, @NonNull Tim * notification the event is passed on immediately without first emitting the buffer it is in the process of * assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -6907,7 +6942,7 @@ public final Flowable> buffer(long timespan, long timeskip, @NonNull Tim @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final > Flowable buffer(long timespan, long timeskip, @NonNull TimeUnit unit, + public final <@NonNull U extends Collection> Flowable buffer(long timespan, long timeskip, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Supplier bufferSupplier) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -6923,7 +6958,7 @@ public final > Flowable buffer(long timespan, * notification the event is passed on immediately without first emitting the buffer it is in the process of * assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -6957,7 +6992,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit) { * notification from the current {@code Flowable}. Note that if the current {@code Flowable} issues an {@code onError} notification the event * is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -6995,7 +7030,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, int * current {@code Flowable} issues an {@code onError} notification the event is passed on immediately without first emitting the * buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -7035,7 +7070,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, @No * current {@code Flowable} issues an {@code onError} notification the event is passed on immediately without first emitting the * buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -7068,7 +7103,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, @No @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final > Flowable buffer( + public final <@NonNull U extends Collection> Flowable buffer( long timespan, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, int count, @NonNull Supplier bufferSupplier, @@ -7088,7 +7123,7 @@ public final > Flowable buffer( * if the current {@code Flowable} issues an {@code onError} notification the event is passed on immediately without first emitting * the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time. It requests {@link Long#MAX_VALUE} @@ -7123,7 +7158,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, @No * {@code PFlowable}, {@code openingIndicator} or {@code closingIndicator} issues an {@code onError} notification the event is passed * on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it is instead controlled by the given {@code Publisher}s and @@ -7147,9 +7182,9 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, @No @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> buffer( - @NonNull Publisher<@NonNull ? extends TOpening> openingIndicator, - @NonNull Function> closingIndicator) { + public final <@NonNull TOpening, @NonNull TClosing> Flowable> buffer( + @NonNull Publisher openingIndicator, + @NonNull Function> closingIndicator) { return buffer(openingIndicator, closingIndicator, ArrayListSupplier.asSupplier()); } @@ -7160,7 +7195,7 @@ public final Flowable> buffer( * {@code Flowable}, {@code openingIndicator} or {@code closingIndicator} issues an {@code onError} notification the event is passed * on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it is instead controlled by the given {@code Publisher}s and @@ -7188,9 +7223,9 @@ public final Flowable> buffer( @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Flowable buffer( - @NonNull Publisher<@NonNull ? extends TOpening> openingIndicator, - @NonNull Function> closingIndicator, + public final <@NonNull TOpening, @NonNull TClosing, @NonNull U extends Collection> Flowable buffer( + @NonNull Publisher openingIndicator, + @NonNull Function> closingIndicator, @NonNull Supplier bufferSupplier) { Objects.requireNonNull(openingIndicator, "openingIndicator is null"); Objects.requireNonNull(closingIndicator, "closingIndicator is null"); @@ -7202,7 +7237,7 @@ public final > Flowable b * Returns a {@code Flowable} that emits non-overlapping buffered items from the current {@code Flowable} each time the * specified boundary {@link Publisher} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code Publisher} causes the returned {@code Publisher} to emit the * latest buffer and complete. If either the current {@code Flowable} or the boundary {@code Publisher} issues an {@code onError} notification @@ -7229,7 +7264,7 @@ public final > Flowable b @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> buffer(@NonNull Publisher boundaryIndicator) { + public final <@NonNull B> Flowable> buffer(@NonNull Publisher boundaryIndicator) { return buffer(boundaryIndicator, ArrayListSupplier.asSupplier()); } @@ -7237,7 +7272,7 @@ public final Flowable> buffer(@NonNull Publisher boundaryIndicato * Returns a {@code Flowable} that emits non-overlapping buffered items from the current {@code Flowable} each time the * specified boundary {@link Publisher} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code Publisher} causes the returned {@code Publisher} to emit the * latest buffer and complete. If either the current {@code Flowable} or the boundary {@code Publisher} issues an {@code onError} notification @@ -7267,7 +7302,7 @@ public final Flowable> buffer(@NonNull Publisher boundaryIndicato @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> buffer(@NonNull Publisher boundaryIndicator, int initialCapacity) { + public final <@NonNull B> Flowable> buffer(@NonNull Publisher boundaryIndicator, int initialCapacity) { ObjectHelper.verifyPositive(initialCapacity, "initialCapacity"); return buffer(boundaryIndicator, Functions.createArrayList(initialCapacity)); } @@ -7276,7 +7311,7 @@ public final Flowable> buffer(@NonNull Publisher boundaryIndicato * Returns a {@code Flowable} that emits non-overlapping buffered items from the current {@code Flowable} each time the * specified boundary {@link Publisher} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code Publisher} causes the returned {@code Publisher} to emit the * latest buffer and complete. If either the current {@code Flowable} or the boundary {@code Publisher} issues an {@code onError} notification @@ -7307,7 +7342,7 @@ public final Flowable> buffer(@NonNull Publisher boundaryIndicato @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Flowable buffer(@NonNull Publisher boundaryIndicator, @NonNull Supplier bufferSupplier) { + public final <@NonNull B, @NonNull U extends Collection> Flowable buffer(@NonNull Publisher boundaryIndicator, @NonNull Supplier bufferSupplier) { Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); Objects.requireNonNull(bufferSupplier, "bufferSupplier is null"); return RxJavaPlugins.onAssembly(new FlowableBufferExactBoundary<>(this, boundaryIndicator, bufferSupplier)); @@ -7317,7 +7352,7 @@ public final > Flowable buffer(@NonNull Pu * Returns a {@code Flowable} that subscribes to this {@link Publisher} lazily, caches all of its events * and replays them, in the same order as received, to all the downstream subscribers. *

- * + * *

* This is useful when you want a {@code Publisher} to cache responses and you can't control the * subscribe/cancel behavior of all the {@link Subscriber}s. @@ -7377,7 +7412,7 @@ public final Flowable cache() { * Returns a {@code Flowable} that subscribes to this {@link Publisher} lazily, caches all of its events * and replays them, in the same order as received, to all the downstream subscribers. *

- * + * *

* This is useful when you want a {@code Publisher} to cache responses and you can't control the * subscribe/cancel behavior of all the {@link Subscriber}s. @@ -7440,10 +7475,12 @@ public final Flowable cacheWithInitialCapacity(int initialCapacity) { } /** - * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable}, converted to the specified - * type. + * Returns a {@code Flowable} that emits the upstream items while + * they can be cast via {@link Class#cast(Object)} until the upstream terminates, + * or until the upstream signals an item which can't be cast, + * resulting in a {@link ClassCastException} to be signaled to the downstream. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -7454,8 +7491,7 @@ public final Flowable cacheWithInitialCapacity(int initialCapacity) { * * @param the output value type cast to * @param clazz - * the target class type that {@code cast} will cast the items emitted by the current {@code Flowable} - * into before emitting them from the resulting {@code Flowable} + * the target class to use to try and cast the upstream items into * @return the new {@code Flowable} instance * @throws NullPointerException if {@code clazz} is {@code null} * @see ReactiveX operators documentation: Map @@ -7464,7 +7500,7 @@ public final Flowable cacheWithInitialCapacity(int initialCapacity) { @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable cast(@NonNull Class clazz) { + public final <@NonNull U> Flowable cast(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return map(Functions.castFunction(clazz)); } @@ -7473,7 +7509,7 @@ public final Flowable cast(@NonNull Class clazz) { * Collects items emitted by the finite source {@link Publisher} into a single mutable data structure and returns * a {@link Single} that emits this structure. *

- * + * *

* This is a simplified version of {@code reduce} that does not need to return the state on each pass. *

@@ -7503,7 +7539,7 @@ public final Flowable cast(@NonNull Class clazz) { @NonNull @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) - public final Single collect(@NonNull Supplier initialItemSupplier, @NonNull BiConsumer collector) { + public final <@NonNull U> Single collect(@NonNull Supplier initialItemSupplier, @NonNull BiConsumer collector) { Objects.requireNonNull(initialItemSupplier, "initialItemSupplier is null"); Objects.requireNonNull(collector, "collector is null"); return RxJavaPlugins.onAssembly(new FlowableCollectSingle<>(this, initialItemSupplier, collector)); @@ -7513,7 +7549,7 @@ public final Single collect(@NonNull Supplier initialItemSup * Collects items emitted by the finite source {@link Publisher} into a single mutable data structure and returns * a {@link Single} that emits this structure. *

- * + * *

* This is a simplified version of {@code reduce} that does not need to return the state on each pass. *

@@ -7575,7 +7611,7 @@ public final Single collect(@NonNull Supplier initialItemSup @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable compose(@NonNull FlowableTransformer composer) { + public final <@NonNull R> Flowable compose(@NonNull FlowableTransformer composer) { return fromPublisher(((FlowableTransformer) Objects.requireNonNull(composer, "composer is null")).apply(this)); } @@ -7584,7 +7620,7 @@ public final Flowable compose(@NonNull FlowableTransformer - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -7612,7 +7648,7 @@ public final Flowable compose(@NonNull FlowableTransformer Flowable concatMap(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMap(@NonNull Function> mapper) { return concatMap(mapper, 2); } @@ -7621,7 +7657,7 @@ public final Flowable concatMap(@NonNull Function - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -7653,7 +7689,7 @@ public final Flowable concatMap(@NonNull Function Flowable concatMap(@NonNull Function> mapper, int prefetch) { + public final <@NonNull R> Flowable concatMap(@NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); if (this instanceof ScalarSupplier) { @@ -7672,7 +7708,7 @@ public final Flowable concatMap(@NonNull Function - * + * *

* The difference between {@link #concatMap(Function, int)} and this operator is that this operator guarantees the {@code mapper} * function is executed on the specified scheduler. @@ -7707,7 +7743,7 @@ public final Flowable concatMap(@NonNull Function Flowable concatMap(@NonNull Function> mapper, int prefetch, @NonNull Scheduler scheduler) { + public final <@NonNull R> Flowable concatMap(@NonNull Function> mapper, int prefetch, @NonNull Scheduler scheduler) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -7718,7 +7754,7 @@ public final Flowable concatMap(@NonNull Function - * + * *

*
Backpressure:
*
The operator expects the upstream to support backpressure. If this {@code Flowable} violates the rule, the operator will @@ -7747,7 +7783,7 @@ public final Completable concatMapCompletable(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure. If this {@code Flowable} violates the rule, the operator will @@ -7784,7 +7820,7 @@ public final Completable concatMapCompletable(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure. If this {@code Flowable} violates the rule, the operator will @@ -7814,7 +7850,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure. If this {@code Flowable} violates the rule, the operator will @@ -7850,7 +7886,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure. If this {@code Flowable} violates the rule, the operator will @@ -7918,7 +7954,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function Flowable concatMapDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapDelayError(@NonNull Function> mapper) { return concatMapDelayError(mapper, true, 2); } @@ -7959,7 +7995,7 @@ public final Flowable concatMapDelayError(@NonNull Function Flowable concatMapDelayError(@NonNull Function> mapper, + public final <@NonNull R> Flowable concatMapDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -8013,7 +8049,7 @@ public final Flowable concatMapDelayError(@NonNull Function Flowable concatMapDelayError(@NonNull Function> mapper, + public final <@NonNull R> Flowable concatMapDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch, @NonNull Scheduler scheduler) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -8046,7 +8082,7 @@ public final Flowable concatMapDelayError(@NonNull Function Flowable concatMapEager(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapEager(@NonNull Function> mapper) { return concatMapEager(mapper, bufferSize(), bufferSize()); } @@ -8078,7 +8114,7 @@ public final Flowable concatMapEager(@NonNull Function Flowable concatMapEager(@NonNull Function> mapper, + public final <@NonNull R> Flowable concatMapEager(@NonNull Function> mapper, int maxConcurrency, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -8114,7 +8150,7 @@ public final Flowable concatMapEager(@NonNull Function Flowable concatMapEagerDelayError(@NonNull Function> mapper, + public final <@NonNull R> Flowable concatMapEagerDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapEagerDelayError(mapper, tillTheEnd, bufferSize(), bufferSize()); } @@ -8152,7 +8188,7 @@ public final Flowable concatMapEagerDelayError(@NonNull Function Flowable concatMapEagerDelayError(@NonNull Function> mapper, + public final <@NonNull R> Flowable concatMapEagerDelayError(@NonNull Function> mapper, boolean tillTheEnd, int maxConcurrency, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -8186,7 +8222,7 @@ public final Flowable concatMapEagerDelayError(@NonNull Function Flowable concatMapIterable(@NonNull Function> mapper) { + public final <@NonNull U> Flowable concatMapIterable(@NonNull Function> mapper) { return concatMapIterable(mapper, 2); } @@ -8219,7 +8255,7 @@ public final Flowable concatMapIterable(@NonNull Function Flowable concatMapIterable(@NonNull Function> mapper, int prefetch) { + public final <@NonNull U> Flowable concatMapIterable(@NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableFlattenIterable<>(this, mapper, prefetch)); @@ -8230,7 +8266,7 @@ public final Flowable concatMapIterable(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8254,7 +8290,7 @@ public final Flowable concatMapIterable(@NonNull Function Flowable concatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapMaybe(@NonNull Function> mapper) { return concatMapMaybe(mapper, 2); } @@ -8263,7 +8299,7 @@ public final Flowable concatMapMaybe(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8292,7 +8328,7 @@ public final Flowable concatMapMaybe(@NonNull Function Flowable concatMapMaybe(@NonNull Function> mapper, int prefetch) { + public final <@NonNull R> Flowable concatMapMaybe(@NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapMaybe<>(this, mapper, ErrorMode.IMMEDIATE, prefetch)); @@ -8303,7 +8339,7 @@ public final Flowable concatMapMaybe(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8327,7 +8363,7 @@ public final Flowable concatMapMaybe(@NonNull Function Flowable concatMapMaybeDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapMaybeDelayError(@NonNull Function> mapper) { return concatMapMaybeDelayError(mapper, true, 2); } @@ -8336,7 +8372,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8366,7 +8402,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function Flowable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd) { + public final <@NonNull R> Flowable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapMaybeDelayError(mapper, tillTheEnd, 2); } @@ -8375,7 +8411,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8409,7 +8445,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function Flowable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch) { + public final <@NonNull R> Flowable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapMaybe<>(this, mapper, tillTheEnd ? ErrorMode.END : ErrorMode.BOUNDARY, prefetch)); @@ -8420,7 +8456,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8444,7 +8480,7 @@ public final Flowable concatMapMaybeDelayError(@NonNull Function Flowable concatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapSingle(@NonNull Function> mapper) { return concatMapSingle(mapper, 2); } @@ -8453,7 +8489,7 @@ public final Flowable concatMapSingle(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8482,7 +8518,7 @@ public final Flowable concatMapSingle(@NonNull Function Flowable concatMapSingle(@NonNull Function> mapper, int prefetch) { + public final <@NonNull R> Flowable concatMapSingle(@NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapSingle<>(this, mapper, ErrorMode.IMMEDIATE, prefetch)); @@ -8493,7 +8529,7 @@ public final Flowable concatMapSingle(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8517,7 +8553,7 @@ public final Flowable concatMapSingle(@NonNull Function Flowable concatMapSingleDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable concatMapSingleDelayError(@NonNull Function> mapper) { return concatMapSingleDelayError(mapper, true, 2); } @@ -8526,7 +8562,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8556,7 +8592,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function Flowable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd) { + public final <@NonNull R> Flowable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapSingleDelayError(mapper, tillTheEnd, 2); } @@ -8565,7 +8601,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator expects the upstream to support backpressure and honors @@ -8599,7 +8635,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function Flowable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch) { + public final <@NonNull R> Flowable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapSingle<>(this, mapper, tillTheEnd ? ErrorMode.END : ErrorMode.BOUNDARY, prefetch)); @@ -8609,7 +8645,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. Both this and the {@code other} {@link Publisher}s @@ -8629,7 +8665,7 @@ public final Flowable concatMapSingleDelayError(@NonNull Function concatWith(@NonNull Publisher<@NonNull ? extends T> other) { + public final Flowable concatWith(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return concat(this, other); } @@ -8638,7 +8674,7 @@ public final Flowable concatWith(@NonNull Publisher<@NonNull ? extends T> oth * Returns a {@code Flowable} that emits the items from this {@code Flowable} followed by the success item or error event * of the other {@link SingleSource}. *

- * + * *

*
Backpressure:
*
The operator supports backpressure and makes sure the success item of the other {@code SingleSource} @@ -8665,7 +8701,7 @@ public final Flowable concatWith(@NonNull SingleSource other) { * Returns a {@code Flowable} that emits the items from this {@code Flowable} followed by the success item or terminal events * of the other {@link MaybeSource}. *

- * + * *

*
Backpressure:
*
The operator supports backpressure and makes sure the success item of the other {@code MaybeSource} @@ -8692,7 +8728,7 @@ public final Flowable concatWith(@NonNull MaybeSource other) { * Returns a {@code Flowable} that emits items from this {@code Flowable} and when it completes normally, the * other {@link CompletableSource} is subscribed to and the returned {@code Flowable} emits its terminal events. *

- * + * *

*
Backpressure:
*
The operator does not interfere with backpressure between the current {@code Flowable} and the @@ -8721,7 +8757,7 @@ public final Flowable concatWith(@NonNull CompletableSource other) { * Returns a {@link Single} that emits a {@link Boolean} that indicates whether the current {@code Flowable} emitted a * specified item. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -8749,7 +8785,7 @@ public final Single contains(@NonNull Object item) { * Returns a {@link Single} that counts the total number of items emitted by the current {@code Flowable} and emits * this count as a 64-bit {@link Long}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -8773,7 +8809,7 @@ public final Single count() { * Returns a {@code Flowable} that mirrors the current {@code Flowable}, except that it drops items emitted by the * current {@code Flowable} that are followed by another item within a computed debounce duration. *

- * + * *

* The delivery of the item happens on the thread of the first {@code onNext} or {@code onComplete} * signal of the generated {@link Publisher} sequence, @@ -8803,7 +8839,7 @@ public final Single count() { @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable debounce(@NonNull Function> debounceIndicator) { + public final <@NonNull U> Flowable debounce(@NonNull Function> debounceIndicator) { Objects.requireNonNull(debounceIndicator, "debounceIndicator is null"); return RxJavaPlugins.onAssembly(new FlowableDebounce<>(this, debounceIndicator)); } @@ -8816,7 +8852,7 @@ public final Flowable debounce(@NonNull FunctionNote: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items * will be emitted by the resulting {@code Flowable}. *

- * + * *

* Delivery of the item after the grace period happens on the {@code computation} {@link Scheduler}'s * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the @@ -8859,7 +8895,7 @@ public final Flowable debounce(long timeout, @NonNull TimeUnit unit) { * Note: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items * will be emitted by the resulting {@code Flowable}. *

- * + * *

* Delivery of the item after the grace period happens on the given {@code Scheduler}'s * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the @@ -8895,14 +8931,66 @@ public final Flowable debounce(long timeout, @NonNull TimeUnit unit) { public final Flowable debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableDebounceTimed<>(this, timeout, unit, scheduler)); + return RxJavaPlugins.onAssembly(new FlowableDebounceTimed<>(this, timeout, unit, scheduler, null)); + } + + /** + * Returns a {@code Flowable} that mirrors the current {@code Flowable}, except that it drops items emitted by the + * current {@code Flowable} that are followed by newer items before a timeout value expires on a specified + * {@link Scheduler}. The timer resets on each emission. + *

+ * Note: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items + * will be emitted by the resulting {@code Flowable}. + *

+ * + *

+ * Delivery of the item after the grace period happens on the given {@code Scheduler}'s + * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the + * {@code Worker}'s task to get disposed, which may also interrupt any downstream blocking operation + * (yielding an {@code InterruptedException}). It is recommended processing items + * that may take long time to be moved to another thread via {@link #observeOn} applied after + * {@code debounce} itself. + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow.
+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param timeout + * the time each item has to be "the most recent" of those emitted by the current {@code Flowable} to + * ensure that it's not dropped + * @param unit + * the unit of time for the specified {@code timeout} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle the timeout for each + * item + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Debounce + * @see RxJava wiki: Backpressure + * @see #throttleWithTimeout(long, TimeUnit, Scheduler, Consumer) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @Experimental + public final Flowable debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new FlowableDebounceTimed<>(this, timeout, unit, scheduler, onDropped)); } /** * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} or a specified default item * if the current {@code Flowable} is empty. *

- * + * *

*
Backpressure:
*
If the current {@code Flowable} is empty, this operator is guaranteed to honor backpressure from downstream. @@ -8932,7 +9020,7 @@ public final Flowable defaultIfEmpty(@NonNull T defaultItem) { * Returns a {@code Flowable} that delays the emissions of the current {@code Flowable} via another {@link Publisher} on a * per-item basis. *

- * + * *

* Note: the resulting {@code Flowable} will immediately propagate any {@code onError} notification * from the current {@code Flowable}. @@ -8959,7 +9047,7 @@ public final Flowable defaultIfEmpty(@NonNull T defaultItem) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable delay(@NonNull Function> itemDelayIndicator) { + public final <@NonNull U> Flowable delay(@NonNull Function> itemDelayIndicator) { Objects.requireNonNull(itemDelayIndicator, "itemDelayIndicator is null"); return flatMap(FlowableInternalHelper.itemDelay(itemDelayIndicator)); } @@ -8968,7 +9056,7 @@ public final Flowable delay(@NonNull Function - * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -8996,7 +9084,7 @@ public final Flowable delay(long time, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} shifted forward in time by a * specified delay. If {@code delayError} is {@code true}, error notifications will also be delayed. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -9027,7 +9115,7 @@ public final Flowable delay(long time, @NonNull TimeUnit unit, boolean delayE * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} shifted forward in time by a * specified delay. The {@code onError} notification from the current {@code Flowable} is not delayed. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -9057,7 +9145,7 @@ public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Sched * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} shifted forward in time by a * specified delay. If {@code delayError} is {@code true}, error notifications will also be delayed. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -9093,7 +9181,7 @@ public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Sched * Returns a {@code Flowable} that delays the subscription to and emissions from the current {@code Flowable} via another * {@link Publisher} on a per-item basis. *

- * + * *

* Note: the resulting {@code Flowable} will immediately propagate any {@code onError} notification * from the current {@code Flowable}. @@ -9125,8 +9213,8 @@ public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Sched @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable delay(@NonNull Publisher subscriptionIndicator, - @NonNull Function> itemDelayIndicator) { + public final <@NonNull U, @NonNull V> Flowable delay(@NonNull Publisher subscriptionIndicator, + @NonNull Function> itemDelayIndicator) { return delaySubscription(subscriptionIndicator).delay(itemDelayIndicator); } @@ -9152,7 +9240,7 @@ public final Flowable delay(@NonNull Publisher subscriptionIndicato @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable delaySubscription(@NonNull Publisher subscriptionIndicator) { + public final <@NonNull U> Flowable delaySubscription(@NonNull Publisher subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new FlowableDelaySubscriptionOther<>(this, subscriptionIndicator)); } @@ -9160,7 +9248,7 @@ public final Flowable delaySubscription(@NonNull Publisher subscriptio /** * Returns a {@code Flowable} that delays the subscription to the current {@code Flowable} by a given amount of time. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -9188,7 +9276,7 @@ public final Flowable delaySubscription(long time, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that delays the subscription to the current {@code Flowable} by a given amount of time, * both waiting and subscribing on a given {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with the backpressure behavior which is determined by the current {@code Flowable}.
@@ -9219,7 +9307,7 @@ public final Flowable delaySubscription(long time, @NonNull TimeUnit unit, @N * {@link Notification} objects extracted from the source items via a selector function * into their respective {@link Subscriber} signal types. *

- * + * *

* The intended use of the {@code selector} function is to perform a * type-safe identity mapping (see example) on a source that is already of type @@ -9268,7 +9356,7 @@ public final Flowable delaySubscription(long time, @NonNull TimeUnit unit, @N @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.PASS_THROUGH) - public final Flowable dematerialize(@NonNull Function<@NonNull ? super T, @NonNull Notification> selector) { + public final <@NonNull R> Flowable dematerialize(@NonNull Function<@NonNull ? super T, @NonNull Notification> selector) { Objects.requireNonNull(selector, "selector is null"); return RxJavaPlugins.onAssembly(new FlowableDematerialize<>(this, selector)); } @@ -9277,7 +9365,7 @@ public final Flowable dematerialize(@NonNull Function<@NonNull ? super T, * Returns a {@code Flowable} that emits all items emitted by the current {@code Flowable} that are distinct * based on {@link Object#equals(Object)} comparison. *

- * + * *

* It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide * a meaningful comparison between items as the default Java implementation only considers reference equivalence. @@ -9319,7 +9407,7 @@ public final Flowable distinct() { * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects * returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide * a meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. @@ -9355,7 +9443,7 @@ public final Flowable distinct() { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable distinct(@NonNull Function keySelector) { + public final <@NonNull K> Flowable distinct(@NonNull Function keySelector) { return distinct(keySelector, Functions.createHashSet()); } @@ -9364,7 +9452,7 @@ public final Flowable distinct(@NonNull Function keySelecto * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects * returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide * a meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. @@ -9391,7 +9479,7 @@ public final Flowable distinct(@NonNull Function keySelecto @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable distinct(@NonNull Function keySelector, + public final <@NonNull K> Flowable distinct(@NonNull Function keySelector, @NonNull Supplier> collectionSupplier) { Objects.requireNonNull(keySelector, "keySelector is null"); Objects.requireNonNull(collectionSupplier, "collectionSupplier is null"); @@ -9402,7 +9490,7 @@ public final Flowable distinct(@NonNull Function keySelecto * Returns a {@code Flowable} that emits all items emitted by the current {@code Flowable} that are distinct from their * immediate predecessors based on {@link Object#equals(Object)} comparison. *

- * + * *

* It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} to provide * a meaningful comparison between items as the default Java implementation only considers reference equivalence. @@ -9444,7 +9532,7 @@ public final Flowable distinctUntilChanged() { * immediate predecessors, according to a key selector function and based on {@link Object#equals(Object)} comparison * of those objects returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} to provide * a meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. @@ -9482,7 +9570,7 @@ public final Flowable distinctUntilChanged() { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable distinctUntilChanged(@NonNull Function keySelector) { + public final <@NonNull K> Flowable distinctUntilChanged(@NonNull Function keySelector) { Objects.requireNonNull(keySelector, "keySelector is null"); return RxJavaPlugins.onAssembly(new FlowableDistinctUntilChanged<>(this, keySelector, ObjectHelper.equalsPredicate())); } @@ -9491,7 +9579,7 @@ public final Flowable distinctUntilChanged(@NonNull Function - * + * *

* Note that the operator always retains the latest item from upstream regardless of the comparison result * and uses it in the next comparison with the next upstream item. @@ -9591,7 +9679,7 @@ public final Flowable doAfterNext(@NonNull Consumer onAfterNext) { * Registers an {@link Action} to be called when this {@link Publisher} invokes either * {@link Subscriber#onComplete onComplete} or {@link Subscriber#onError onError}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -9619,7 +9707,7 @@ public final Flowable doAfterTerminate(@NonNull Action onAfterTerminate) { /** * Calls the cancel {@link Action} if the downstream cancels the sequence. *

- * + * *

* The action is shared between subscriptions and thus may be called concurrently from multiple * threads; the action must be thread-safe. @@ -9651,7 +9739,7 @@ public final Flowable doOnCancel(@NonNull Action onCancel) { /** * Invokes an {@link Action} just before the current {@code Flowable} calls {@code onComplete}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9679,7 +9767,7 @@ public final Flowable doOnComplete(@NonNull Action onComplete) { * Calls the appropriate onXXX consumer (shared between all subscribers) whenever a signal with the same type * passes through, before forwarding them to downstream. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9688,6 +9776,10 @@ public final Flowable doOnComplete(@NonNull Action onComplete) { *
{@code doOnEach} does not operate by default on a particular {@link Scheduler}.
*
* + * @param onNext the {@link Consumer} to invoke when the current {@code Flowable} calls {@code onNext} + * @param onError the {@code Consumer} to invoke when the current {@code Flowable} calls {@code onError} + * @param onComplete the {@link Action} to invoke when the current {@code Flowable} calls {@code onComplete} + * @param onAfterTerminate the {@code Action} to invoke when the current {@code Flowable} calls {@code onAfterTerminate} * @return the new {@code Flowable} instance * @throws NullPointerException if {@code onNext}, {@code onError}, {@code onComplete} or {@code onAfterTerminate} is {@code null} * @see ReactiveX operators documentation: Do @@ -9709,7 +9801,7 @@ private Flowable doOnEach(@NonNull Consumer onNext, @NonNull Consu * Invokes a {@link Consumer} with a {@link Notification} instances matching the signals emitted by the current {@code Flowable} * before they are forwarded to the downstream. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9747,7 +9839,7 @@ public final Flowable doOnEach(@NonNull Consumer<@NonNull ? super Notificatio * {@code onNext} or the {@code onComplete} method of the supplied {@code Subscriber} throws, the downstream will be * terminated and will receive this thrown exception. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9767,7 +9859,7 @@ public final Flowable doOnEach(@NonNull Consumer<@NonNull ? super Notificatio @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable doOnEach(@NonNull Subscriber<@NonNull ? super T> subscriber) { + public final Flowable doOnEach(@NonNull Subscriber subscriber) { Objects.requireNonNull(subscriber, "subscriber is null"); return doOnEach( FlowableInternalHelper.subscriberOnNext(subscriber), @@ -9783,7 +9875,7 @@ public final Flowable doOnEach(@NonNull Subscriber<@NonNull ? super T> subscr * In case the {@code onError} action throws, the downstream will receive a composite exception containing * the original exception and the exception thrown by {@code onError}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9811,7 +9903,7 @@ public final Flowable doOnError(@NonNull Consumer onError) * Calls the appropriate {@code onXXX} method (shared between all {@link Subscriber}s) for the lifecycle events of * the sequence (subscription, cancellation, requesting). *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9845,7 +9937,7 @@ public final Flowable doOnLifecycle(@NonNull Consumer o /** * Calls the given {@link Consumer} with the value emitted by the current {@code Flowable} before forwarding it to the downstream. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9906,7 +9998,7 @@ public final Flowable doOnRequest(@NonNull LongConsumer onRequest) { * subscription from the downstream before forwarding it to the subscriber's * {@link Subscriber#onSubscribe(Subscription) onSubscribe} method. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s @@ -9933,7 +10025,7 @@ public final Flowable doOnSubscribe(@NonNull Consumer o * Calls the given {@link Action} when the current {@code Flowable} completes normally or with an error before those signals * are forwarded to the downstream. *

- * + * *

* This differs from {@code doAfterTerminate} in that this happens before the {@code onComplete} or * {@code onError} notification. @@ -9965,7 +10057,7 @@ public final Flowable doOnTerminate(@NonNull Action onTerminate) { * Returns a {@link Maybe} that emits the single item at a specified index in a sequence of emissions from * this {@code Flowable} or completes if this {@code Flowable} sequence has fewer elements than index. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -9994,7 +10086,7 @@ public final Maybe elementAt(long index) { * Returns a {@link Single} that emits the item found at a specified index in a sequence of emissions from * this {@code Flowable}, or a default item if that index is out of range. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -10028,7 +10120,7 @@ public final Single elementAt(long index, @NonNull T defaultItem) { * Returns a {@link Single} that emits the item found at a specified index in a sequence of emissions from * this {@code Flowable} or signals a {@link NoSuchElementException} if this {@code Flowable} has fewer elements than index. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -10057,7 +10149,7 @@ public final Single elementAtOrError(long index) { /** * Filters items emitted by the current {@code Flowable} by only emitting those that satisfy a specified predicate. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -10109,7 +10201,7 @@ public final Maybe firstElement() { * Returns a {@link Single} that emits only the very first item emitted by this {@code Flowable}, or a default * item if this {@code Flowable} completes without emitting anything. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -10159,7 +10251,7 @@ public final Single firstOrError() { * by the current {@code Flowable}, where that function returns a {@link Publisher}, and then merging those resulting * {@code Publisher}s and emitting the results of this merger. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10182,7 +10274,7 @@ public final Single firstOrError() { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable flatMap(@NonNull Function> mapper) { + public final <@NonNull R> Flowable flatMap(@NonNull Function> mapper) { return flatMap(mapper, false, bufferSize(), bufferSize()); } @@ -10191,7 +10283,7 @@ public final Flowable flatMap(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10217,7 +10309,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, boolean delayErrors) { + public final <@NonNull R> Flowable flatMap(@NonNull Function> mapper, boolean delayErrors) { return flatMap(mapper, delayErrors, bufferSize(), bufferSize()); } @@ -10227,7 +10319,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10254,7 +10346,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, int maxConcurrency) { + public final <@NonNull R> Flowable flatMap(@NonNull Function> mapper, int maxConcurrency) { return flatMap(mapper, false, maxConcurrency, bufferSize()); } @@ -10264,7 +10356,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10294,7 +10386,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { + public final <@NonNull R> Flowable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { return flatMap(mapper, delayErrors, maxConcurrency, bufferSize()); } @@ -10304,7 +10396,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10336,7 +10428,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull R> Flowable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -10356,7 +10448,7 @@ public final Flowable flatMap(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10385,10 +10477,10 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap( - @NonNull Function> onNextMapper, - @NonNull Function> onErrorMapper, - @NonNull Supplier> onCompleteSupplier) { + public final <@NonNull R> Flowable flatMap( + @NonNull Function> onNextMapper, + @NonNull Function> onErrorMapper, + @NonNull Supplier> onCompleteSupplier) { Objects.requireNonNull(onNextMapper, "onNextMapper is null"); Objects.requireNonNull(onErrorMapper, "onErrorMapper is null"); Objects.requireNonNull(onCompleteSupplier, "onCompleteSupplier is null"); @@ -10400,7 +10492,7 @@ public final Flowable flatMap( * {@code Flowable} and then flattens the {@link Publisher}s returned from these functions and emits the resulting items, * while limiting the maximum number of concurrent subscriptions to these {@code Publisher}s. * - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10433,10 +10525,10 @@ public final Flowable flatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable flatMap( - @NonNull Function> onNextMapper, - @NonNull Function> onErrorMapper, - @NonNull Supplier> onCompleteSupplier, + public final <@NonNull R> Flowable flatMap( + @NonNull Function> onNextMapper, + @NonNull Function> onErrorMapper, + @NonNull Supplier> onCompleteSupplier, int maxConcurrency) { Objects.requireNonNull(onNextMapper, "onNextMapper is null"); Objects.requireNonNull(onErrorMapper, "onErrorMapper is null"); @@ -10449,7 +10541,7 @@ public final Flowable flatMap( * Returns a {@code Flowable} that emits the results of a specified function to the pair of values emitted by the * current {@code Flowable} and a specified collection {@link Publisher}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10477,7 +10569,7 @@ public final Flowable flatMap( @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Flowable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner) { return flatMap(mapper, combiner, false, bufferSize(), bufferSize()); } @@ -10486,7 +10578,7 @@ public final Flowable flatMap(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10517,7 +10609,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Flowable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors) { return flatMap(mapper, combiner, delayErrors, bufferSize(), bufferSize()); } @@ -10527,7 +10619,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10562,7 +10654,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Flowable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors, int maxConcurrency) { return flatMap(mapper, combiner, delayErrors, maxConcurrency, bufferSize()); } @@ -10572,7 +10664,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10609,7 +10701,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Flowable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -10623,7 +10715,7 @@ public final Flowable flatMap(@NonNull Function --> - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The upstream {@code Flowable} is consumed @@ -10655,7 +10747,7 @@ public final Flowable flatMap(@NonNull Function Flowable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Flowable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, int maxConcurrency) { return flatMap(mapper, combiner, false, maxConcurrency, bufferSize()); } @@ -10737,7 +10829,7 @@ public final Completable flatMapCompletable(@NonNull Function Flowable flatMapIterable(@NonNull Function> mapper) { + public final <@NonNull U> Flowable flatMapIterable(@NonNull Function> mapper) { return flatMapIterable(mapper, bufferSize()); } @@ -10771,7 +10863,7 @@ public final Flowable flatMapIterable(@NonNull Function Flowable flatMapIterable(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull U> Flowable flatMapIterable(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new FlowableFlattenIterable<>(this, mapper, bufferSize)); @@ -10810,7 +10902,7 @@ public final Flowable flatMapIterable(@NonNull Function Flowable flatMapIterable(@NonNull Function> mapper, + public final <@NonNull U, @NonNull V> Flowable flatMapIterable(@NonNull Function> mapper, @NonNull BiFunction combiner) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -10855,7 +10947,7 @@ public final Flowable flatMapIterable(@NonNull Function Flowable flatMapIterable(@NonNull Function> mapper, + public final <@NonNull U, @NonNull V> Flowable flatMapIterable(@NonNull Function> mapper, @NonNull BiFunction combiner, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -10865,6 +10957,8 @@ public final Flowable flatMapIterable(@NonNull Function + * *
*
Backpressure:
*
The operator consumes the upstream in an unbounded manner.
@@ -10880,7 +10974,7 @@ public final Flowable flatMapIterable(@NonNull Function Flowable flatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Flowable flatMapMaybe(@NonNull Function> mapper) { return flatMapMaybe(mapper, false, Integer.MAX_VALUE); } @@ -10888,6 +10982,8 @@ public final Flowable flatMapMaybe(@NonNull Function + * *
*
Backpressure:
*
If {@code maxConcurrency == }{@link Integer#MAX_VALUE} the operator consumes the upstream in an unbounded manner. @@ -10909,7 +11005,7 @@ public final Flowable flatMapMaybe(@NonNull Function Flowable flatMapMaybe(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { + public final <@NonNull R> Flowable flatMapMaybe(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new FlowableFlatMapMaybe<>(this, mapper, delayErrors, maxConcurrency)); @@ -10933,7 +11029,7 @@ public final Flowable flatMapMaybe(@NonNull Function Flowable flatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Flowable flatMapSingle(@NonNull Function> mapper) { return flatMapSingle(mapper, false, Integer.MAX_VALUE); } @@ -10962,7 +11058,7 @@ public final Flowable flatMapSingle(@NonNull Function Flowable flatMapSingle(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { + public final <@NonNull R> Flowable flatMapSingle(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new FlowableFlatMapSingle<>(this, mapper, delayErrors, maxConcurrency)); @@ -11101,7 +11197,7 @@ public final Disposable forEachWhile(@NonNull Predicate onNext, @NonN * source terminates, the next emission by the source having the same key will trigger a new * {@code GroupedFlowable} emission. *

- * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11148,7 +11244,7 @@ public final Disposable forEachWhile(@NonNull Predicate onNext, @NonN @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> groupBy(@NonNull Function keySelector) { + public final <@NonNull K> Flowable> groupBy(@NonNull Function keySelector) { return groupBy(keySelector, Functions.identity(), false, bufferSize()); } @@ -11159,7 +11255,7 @@ public final Flowable> groupBy(@NonNull Function - * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11207,7 +11303,7 @@ public final Flowable> groupBy(@NonNull Function Flowable> groupBy(@NonNull Function keySelector, boolean delayError) { + public final <@NonNull K> Flowable> groupBy(@NonNull Function keySelector, boolean delayError) { return groupBy(keySelector, Functions.identity(), delayError, bufferSize()); } @@ -11218,7 +11314,7 @@ public final Flowable> groupBy(@NonNull Function - * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11270,7 +11366,7 @@ public final Flowable> groupBy(@NonNull Function Flowable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Flowable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector) { return groupBy(keySelector, valueSelector, false, bufferSize()); } @@ -11282,7 +11378,7 @@ public final Flowable> groupBy(@NonNull Function - * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11335,7 +11431,7 @@ public final Flowable> groupBy(@NonNull Function Flowable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Flowable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector, boolean delayError) { return groupBy(keySelector, valueSelector, delayError, bufferSize()); } @@ -11347,7 +11443,7 @@ public final Flowable> groupBy(@NonNull Function - * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11402,7 +11498,7 @@ public final Flowable> groupBy(@NonNull Function Flowable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Flowable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector, boolean delayError, int bufferSize) { Objects.requireNonNull(keySelector, "keySelector is null"); @@ -11460,7 +11556,7 @@ public final Flowable> groupBy(@NonNull Function

* *

- * + * *

* Note: A {@code GroupedFlowable} will cache the items it is to emit until such time as it * is subscribed to. For this reason, in order to avoid memory leaks, you should not simply ignore those @@ -11523,7 +11619,7 @@ public final Flowable> groupBy(@NonNull Function Flowable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Flowable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector, boolean delayError, int bufferSize, @NonNull Function, ? extends Map> evictingMapFactory) { @@ -11541,7 +11637,7 @@ public final Flowable> groupBy(@NonNull Function - * + * *

*
Backpressure:
*
The operator doesn't support backpressure and consumes all participating {@code Publisher}s in @@ -11573,10 +11669,10 @@ public final Flowable> groupBy(@NonNull Function Flowable groupJoin( - @NonNull Publisher<@NonNull ? extends TRight> other, - @NonNull Function> leftEnd, - @NonNull Function> rightEnd, + public final <@NonNull TRight, @NonNull TLeftEnd, @NonNull TRightEnd, @NonNull R> Flowable groupJoin( + @NonNull Publisher other, + @NonNull Function> leftEnd, + @NonNull Function> rightEnd, @NonNull BiFunction, ? extends R> resultSelector) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(leftEnd, "leftEnd is null"); @@ -11613,7 +11709,7 @@ public final Flowable hide() { /** * Ignores all items emitted by the current {@code Flowable} and only calls {@code onComplete} or {@code onError}. *

- * + * *

*
Backpressure:
*
This operator ignores backpressure as it doesn't emit any elements and consumes the current {@code Flowable} @@ -11639,7 +11735,7 @@ public final Completable ignoreElements() { * In Rx.Net this is negated as the {@code any} {@link Subscriber} but we renamed this in RxJava to better match Java * naming idioms. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -11665,7 +11761,7 @@ public final Single isEmpty() { * There are no guarantees in what order the items get combined when multiple * items from one or both source {@code Publisher}s overlap. *

- * + * *

*
Backpressure:
*
The operator doesn't support backpressure and consumes all participating {@code Publisher}s in @@ -11697,10 +11793,10 @@ public final Single isEmpty() { @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable join( - @NonNull Publisher<@NonNull ? extends TRight> other, - @NonNull Function> leftEnd, - @NonNull Function> rightEnd, + public final <@NonNull TRight, @NonNull TLeftEnd, @NonNull TRightEnd, @NonNull R> Flowable join( + @NonNull Publisher other, + @NonNull Function> leftEnd, + @NonNull Function> rightEnd, @NonNull BiFunction resultSelector) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(leftEnd, "leftEnd is null"); @@ -11714,7 +11810,7 @@ public final Flowable join( * Returns a {@link Maybe} that emits the last item emitted by this {@code Flowable} or completes if * this {@code Flowable} is empty. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -11738,7 +11834,7 @@ public final Maybe lastElement() { * Returns a {@link Single} that emits only the last item emitted by this {@code Flowable}, or a default item * if this {@code Flowable} completes without emitting any items. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -11937,7 +12033,7 @@ public final Single lastOrError() { @NonNull @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable lift(@NonNull FlowableOperator lifter) { + public final <@NonNull R> Flowable lift(@NonNull FlowableOperator lifter) { Objects.requireNonNull(lifter, "lifter is null"); return RxJavaPlugins.onAssembly(new FlowableLift<>(this, lifter)); } @@ -11946,7 +12042,7 @@ public final Flowable lift(@NonNull FlowableOperator - * + * *
*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -11976,7 +12072,7 @@ public final Flowable lift(@NonNull FlowableOperatorand notifications from the current * {@code Flowable} into emissions marked with their original types within {@link Notification} objects. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and expects it from the current {@code Flowable}. @@ -12000,7 +12096,7 @@ public final Flowable> materialize() { /** * Flattens this and another {@link Publisher} into a single {@code Publisher}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code Publisher}s so that they appear as a single {@code Publisher}, by * using the {@code mergeWith} method. @@ -12022,7 +12118,7 @@ public final Flowable> materialize() { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable mergeWith(@NonNull Publisher<@NonNull ? extends T> other) { + public final Flowable mergeWith(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return merge(this, other); } @@ -12030,7 +12126,7 @@ public final Flowable mergeWith(@NonNull Publisher<@NonNull ? extends T> othe /** * Merges the sequence of items of this {@code Flowable} with the success value of the other {@link SingleSource}. *

- * + * *

* The success value of the other {@code SingleSource} can get interleaved at any point of this * {@code Flowable} sequence. @@ -12060,7 +12156,7 @@ public final Flowable mergeWith(@NonNull SingleSource other) { * Merges the sequence of items of this {@code Flowable} with the success value of the other {@link MaybeSource} * or waits for both to complete normally if the {@code MaybeSource} is empty. *

- * + * *

* The success value of the other {@code MaybeSource} can get interleaved at any point of this * {@code Flowable} sequence. @@ -12090,7 +12186,7 @@ public final Flowable mergeWith(@NonNull MaybeSource other) { * Relays the items of this {@code Flowable} and completes only when the other {@link CompletableSource} completes * as well. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -12120,7 +12216,7 @@ public final Flowable mergeWith(@NonNull CompletableSource other) { *

Note that {@code onError} notifications will cut ahead of {@code onNext} notifications on the emission thread if {@code Scheduler} is truly * asynchronous. If strict event ordering is required, consider using the {@link #observeOn(Scheduler, boolean)} overload. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s Worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -12168,7 +12264,7 @@ public final Flowable observeOn(@NonNull Scheduler scheduler) { * Signals the items and terminal signals of the current {@code Flowable} on the specified {@link Scheduler}, * asynchronously with a bounded buffer and optionally delays {@code onError} notifications. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s Worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -12220,7 +12316,7 @@ public final Flowable observeOn(@NonNull Scheduler scheduler, boolean delayEr * Signals the items and terminal signals of the current {@code Flowable} on the specified {@link Scheduler}, * asynchronously with a bounded buffer of configurable size and optionally delays {@code onError} notifications. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s Worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -12275,7 +12371,7 @@ public final Flowable observeOn(@NonNull Scheduler scheduler, boolean delayEr /** * Filters the items emitted by the current {@code Flowable}, only emitting those of the specified type. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -12295,7 +12391,7 @@ public final Flowable observeOn(@NonNull Scheduler scheduler, boolean delayEr @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable ofType(@NonNull Class clazz) { + public final <@NonNull U> Flowable ofType(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return filter(Functions.isInstanceOf(clazz)).cast(clazz); } @@ -12304,7 +12400,7 @@ public final Flowable ofType(@NonNull Class clazz) { * Buffers an unlimited number of items from the current {@code Flowable} and allows it to emit as fast it can while allowing the * downstream to consume the items at its own place. *

- * + * *

* An error from the current {@code Flowable} will cut ahead of any unconsumed item. Use {@link #onBackpressureBuffer(boolean)} * to have the operator keep the original signal order. @@ -12332,7 +12428,7 @@ public final Flowable onBackpressureBuffer() { * Buffers an unlimited number of items from the current {@code Flowable} and allows it to emit as fast it can while allowing the * downstream to consume the items at its own place, optionally delaying an error until all buffered items have been consumed. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12361,7 +12457,7 @@ public final Flowable onBackpressureBuffer(boolean delayError) { * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered * items, and canceling the flow. *

- * + * *

* An error from the current {@code Flowable} will cut ahead of any unconsumed item. Use {@link #onBackpressureBuffer(int, boolean)} * to have the operator keep the original signal order. @@ -12394,7 +12490,7 @@ public final Flowable onBackpressureBuffer(int capacity) { * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered * items, and canceling the flow. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12428,7 +12524,7 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError) * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered * items, and canceling the flow. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12455,7 +12551,7 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError) @NonNull public final Flowable onBackpressureBuffer(int capacity, boolean delayError, boolean unbounded) { ObjectHelper.verifyPositive(capacity, "capacity"); - return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBuffer<>(this, capacity, unbounded, delayError, Functions.EMPTY_ACTION)); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBuffer<>(this, capacity, unbounded, delayError, Functions.EMPTY_ACTION, Functions.emptyConsumer())); } /** @@ -12465,7 +12561,7 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError, * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered * items, canceling the flow and calling the {@code onOverflow} action. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12486,6 +12582,7 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError, * @throws NullPointerException if {@code onOverflow} is {@code null} * @throws IllegalArgumentException if {@code capacity} is non-positive * @see ReactiveX operators documentation: backpressure operators + * @see #onBackpressureBuffer(int, boolean, boolean, Action, Consumer) * @since 1.1.0 */ @CheckReturnValue @@ -12496,7 +12593,51 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError, @NonNull Action onOverflow) { Objects.requireNonNull(onOverflow, "onOverflow is null"); ObjectHelper.verifyPositive(capacity, "capacity"); - return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBuffer<>(this, capacity, unbounded, delayError, onOverflow)); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBuffer<>(this, capacity, unbounded, delayError, onOverflow, Functions.emptyConsumer())); + } + + /** + * Buffers an optionally unlimited number of items from the current {@code Flowable} and allows it to emit as fast it can while allowing the + * downstream to consume the items at its own place. + * If {@code unbounded} is {@code true}, the resulting {@code Flowable} will signal a + * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered + * items, canceling the flow and calling the {@code onOverflow} action. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded + * manner (i.e., not applying backpressure to it).
+ *
Scheduler:
+ *
{@code onBackpressureBuffer} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param capacity number of slots available in the buffer. + * @param delayError + * if {@code true}, an exception from the current {@code Flowable} is delayed until all buffered elements have been + * consumed by the downstream; if {@code false}, an exception is immediately signaled to the downstream, skipping + * any buffered element + * @param unbounded + * if {@code true}, the capacity value is interpreted as the internal "island" size of the unbounded buffer + * @param onOverflow action to execute if an item needs to be buffered, but there are no available slots. + * @param onDropped the {@link Consumer} to be called with the item that could not be buffered due to capacity constraints. + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code onOverflow} or {@code onDropped} is {@code null} + * @throws IllegalArgumentException if {@code capacity} is non-positive + * @see ReactiveX operators documentation: backpressure operators + * @since 3.1.7 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.SPECIAL) + @SchedulerSupport(SchedulerSupport.NONE) + @Experimental + public final Flowable onBackpressureBuffer(int capacity, boolean delayError, boolean unbounded, + @NonNull Action onOverflow, @NonNull Consumer onDropped) { + Objects.requireNonNull(onOverflow, "onOverflow is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + ObjectHelper.verifyPositive(capacity, "capacity"); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBuffer<>(this, capacity, unbounded, delayError, onOverflow, onDropped)); } /** @@ -12505,7 +12646,7 @@ public final Flowable onBackpressureBuffer(int capacity, boolean delayError, * {@link MissingBackpressureException} via {@code onError} as soon as the buffer's capacity is exceeded, dropping all undelivered * items, canceling the flow and calling the {@code onOverflow} action. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12546,7 +12687,7 @@ public final Flowable onBackpressureBuffer(int capacity, @NonNull Action onOv * * *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded @@ -12562,6 +12703,7 @@ public final Flowable onBackpressureBuffer(int capacity, @NonNull Action onOv * @throws NullPointerException if {@code onOverflow} or {@code overflowStrategy} is {@code null} * @throws IllegalArgumentException if {@code capacity} is non-positive * @see ReactiveX operators documentation: backpressure operators + * @see #onBackpressureBuffer(long, Action, BackpressureOverflowStrategy) * @since 2.0 */ @CheckReturnValue @@ -12571,14 +12713,60 @@ public final Flowable onBackpressureBuffer(int capacity, @NonNull Action onOv public final Flowable onBackpressureBuffer(long capacity, @Nullable Action onOverflow, @NonNull BackpressureOverflowStrategy overflowStrategy) { Objects.requireNonNull(overflowStrategy, "overflowStrategy is null"); ObjectHelper.verifyPositive(capacity, "capacity"); - return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBufferStrategy<>(this, capacity, onOverflow, overflowStrategy)); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBufferStrategy<>(this, capacity, onOverflow, overflowStrategy, null)); } + /** + * Buffers an optionally unlimited number of items from the current {@code Flowable} and allows it to emit as fast it can while allowing the + * downstream to consume the items at its own place. + * The resulting {@code Flowable} will behave as determined by {@code overflowStrategy} if the buffer capacity is exceeded: + *
    + *
  • {@link BackpressureOverflowStrategy#ERROR} (default) will call {@code onError} dropping all undelivered items, + * canceling the source, and notifying the producer with {@code onOverflow}.
  • + *
  • {@link BackpressureOverflowStrategy#DROP_LATEST} will drop any new items emitted by the producer while + * the buffer is full, without generating any {@code onError}. Each drop will, however, invoke {@code onOverflow} + * to signal the overflow to the producer.
  • + *
  • {@link BackpressureOverflowStrategy#DROP_OLDEST} will drop the oldest items in the buffer in order to make + * room for newly emitted ones. Overflow will not generate an {@code onError}, but each drop will invoke + * {@code onOverflow} to signal the overflow to the producer.
  • + *
+ * + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded + * manner (i.e., not applying backpressure to it).
+ *
Scheduler:
+ *
{@code onBackpressureBuffer} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param capacity number of slots available in the buffer. + * @param onOverflow action to execute if an item needs to be buffered, but there are no available slots, {@code null} is allowed. + * @param overflowStrategy how should the resulting {@code Flowable} react to buffer overflows, {@code null} is not allowed. + * @param onDropped the {@link Consumer} to be called with the item that could not be buffered due to capacity constraints. + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code onOverflow}, {@code overflowStrategy} or {@code onDropped} is {@code null} + * @throws IllegalArgumentException if {@code capacity} is non-positive + * @see ReactiveX operators documentation: backpressure operators + * @since 3.1.7 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.SPECIAL) + @SchedulerSupport(SchedulerSupport.NONE) + @Experimental + public final Flowable onBackpressureBuffer(long capacity, @Nullable Action onOverflow, @NonNull BackpressureOverflowStrategy overflowStrategy, @NonNull Consumer onDropped) { + Objects.requireNonNull(overflowStrategy, "overflowStrategy is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + ObjectHelper.verifyPositive(capacity, "capacity"); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureBufferStrategy<>(this, capacity, onOverflow, overflowStrategy, onDropped)); + } /** * Drops items from the current {@code Flowable} if the downstream is not ready to receive new items (indicated * by a lack of {@link Subscription#request(long)} calls from it). *

- * + * *

* If the downstream request count hits 0 then the resulting {@code Flowable} will refrain from calling {@code onNext} until * the {@link Subscriber} invokes {@code request(n)} again to increase the request count. @@ -12606,7 +12794,7 @@ public final Flowable onBackpressureDrop() { * by a lack of {@link Subscription#request(long)} calls from it) and calls the given {@link Consumer} with such * dropped items. *

- * + * *

* If the downstream request count hits 0 then the resulting {@code Flowable} will refrain from calling {@code onNext} until * the {@link Subscriber} invokes {@code request(n)} again to increase the request count. @@ -12638,7 +12826,7 @@ public final Flowable onBackpressureDrop(@NonNull Consumer onDrop) * new items (indicated by a lack of {@link Subscription#request(long)} calls from it) and emits this latest * item when the downstream becomes ready. *

- * + * *

* Its behavior is logically equivalent to {@code blockingLatest()} with the exception that * the downstream is not blocking while requesting more values. @@ -12664,7 +12852,127 @@ public final Flowable onBackpressureDrop(@NonNull Consumer onDrop) @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Flowable onBackpressureLatest() { - return RxJavaPlugins.onAssembly(new FlowableOnBackpressureLatest<>(this)); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureLatest<>(this, null)); + } + + /** + * Drops all but the latest item emitted by the current {@code Flowable} if the downstream is not ready to receive + * new items (indicated by a lack of {@link Subscription#request(long)} calls from it) and emits this latest + * item when the downstream becomes ready. + *

+ * + *

+ * Its behavior is logically equivalent to {@code blockingLatest()} with the exception that + * the downstream is not blocking while requesting more values. + *

+ * Note that if the current {@code Flowable} does support backpressure, this operator ignores that capability + * and doesn't propagate any backpressure requests from downstream. + *

+ * Note that due to the nature of how backpressure requests are propagated through subscribeOn/observeOn, + * requesting more than 1 from downstream doesn't guarantee a continuous delivery of {@code onNext} events. + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded + * manner (i.e., not applying backpressure to it).
+ *
Scheduler:
+ *
{@code onBackpressureLatest} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @throws NullPointerException if {@code onDropped} is {@code null} + * @return the new {@code Flowable} instance + * @since 3.1.7 + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + @Experimental + public final Flowable onBackpressureLatest(@NonNull Consumer onDropped) { + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureLatest<>(this, onDropped)); + } + + /** + * Reduces a sequence of two not emitted values via a function into a single value if the downstream is not ready to receive + * new items (indicated by a lack of {@link Subscription#request(long)} calls from it) and emits this latest + * item when the downstream becomes ready. + *

+ * + *

+ * Note that if the current {@code Flowable} does support backpressure, this operator ignores that capability + * and doesn't propagate any backpressure requests from downstream. + *

+ * Note that due to the nature of how backpressure requests are propagated through subscribeOn/observeOn, + * requesting more than 1 from downstream doesn't guarantee a continuous delivery of {@code onNext} events. + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded + * manner (i.e., not applying backpressure to it).
+ *
Scheduler:
+ *
{@code onBackpressureReduce} does not operate by default on a particular {@link Scheduler}.
+ *
+ *

History: 3.0.9 - experimental + * @param reducer the bi-function to call when there is more than one non-emitted value to downstream, + * the first argument of the bi-function is previous item and the second one is currently + * emitting from upstream + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code reducer} is {@code null} + * @since 3.1.0 + * @see #onBackpressureReduce(Supplier, BiFunction) + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Flowable onBackpressureReduce(@NonNull BiFunction reducer) { + Objects.requireNonNull(reducer, "reducer is null"); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureReduce<>(this, reducer)); + } + + /** + * Reduces upstream values into an aggregate value, provided by a supplier and combined via a reducer function, + * while the downstream is not ready to receive items, then emits this aggregate value when the downstream becomes ready. + *

+ * + *

+ * Note that even if the downstream is ready to receive an item, the upstream item will always be aggregated into the output type, + * calling both the supplier and the reducer to produce the output value. + *

+ * Note that if the current {@code Flowable} does support backpressure, this operator ignores that capability + * and doesn't propagate any backpressure requests from downstream. + *

+ * Note that due to the nature of how backpressure requests are propagated through subscribeOn/observeOn, + * requesting more than 1 from downstream doesn't guarantee a continuous delivery of {@code onNext} events. + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an unbounded + * manner (i.e., not applying backpressure to it).
+ *
Scheduler:
+ *
{@code onBackpressureReduce} does not operate by default on a particular {@link Scheduler}.
+ *
+ *

History: 3.0.9 - experimental + * @param the aggregate type emitted when the downstream requests more items + * @param supplier the factory to call to create new item of type R to pass it as the first argument to {@code reducer}. + * It is called when previous returned value by {@code reducer} already sent to + * downstream or the very first update from upstream received. + * @param reducer the bi-function to call to reduce excessive updates which downstream is not ready to receive. + * The first argument of type R is the object returned by {@code supplier} or result of previous + * {@code reducer} invocation. The second argument of type T is the current update from upstream. + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code supplier} or {@code reducer} is {@code null} + * @see #onBackpressureReduce(BiFunction) + * @since 3.1.0 + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final <@NonNull R> Flowable onBackpressureReduce(@NonNull Supplier supplier, @NonNull BiFunction reducer) { + Objects.requireNonNull(supplier, "supplier is null"); + Objects.requireNonNull(reducer, "reducer is null"); + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureReduceWith<>(this, supplier, reducer)); } /** @@ -12722,7 +13030,7 @@ public final Flowable onErrorComplete(@NonNull Predicate p * Resumes the flow with a {@link Publisher} returned for the failure {@link Throwable} of the current {@code Flowable} by a * function instead of signaling the error via {@code onError}. *

- * + * *

* By default, when a {@code Publisher} encounters an error that prevents it from emitting the expected item to * its {@link Subscriber}, the {@code Publisher} invokes its {@code Subscriber}'s {@code onError} method, and then quits @@ -12758,7 +13066,7 @@ public final Flowable onErrorComplete(@NonNull Predicate p @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable onErrorResumeNext(@NonNull Function> fallbackSupplier) { + public final Flowable onErrorResumeNext(@NonNull Function> fallbackSupplier) { Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); return RxJavaPlugins.onAssembly(new FlowableOnErrorNext<>(this, fallbackSupplier)); } @@ -12767,7 +13075,7 @@ public final Flowable onErrorResumeNext(@NonNull Function - * + * *

* By default, when a {@code Publisher} encounters an error that prevents it from emitting the expected item to * its {@link Subscriber}, the {@code Publisher} invokes its {@code Subscriber}'s {@code onError} method, and then quits @@ -12803,7 +13111,7 @@ public final Flowable onErrorResumeNext(@NonNull Function onErrorResumeWith(@NonNull Publisher<@NonNull ? extends T> fallback) { + public final Flowable onErrorResumeWith(@NonNull Publisher fallback) { Objects.requireNonNull(fallback, "fallback is null"); return onErrorResumeNext(Functions.justFunction(fallback)); } @@ -12812,7 +13120,7 @@ public final Flowable onErrorResumeWith(@NonNull Publisher<@NonNull ? extends * Ends the flow with a last item returned by a function for the {@link Throwable} error signaled by the current * {@code Flowable} instead of signaling the error via {@code onError}. *

- * + * *

* By default, when a {@link Publisher} encounters an error that prevents it from emitting the expected item to * its {@link Subscriber}, the {@code Publisher} invokes its {@code Subscriber}'s {@code onError} method, and then quits @@ -12852,7 +13160,7 @@ public final Flowable onErrorReturn(@NonNull Function - * + * *

* By default, when a {@link Publisher} encounters an error that prevents it from emitting the expected item to * its {@link Subscriber}, the {@code Publisher} invokes its {@code Subscriber}'s {@code onError} method, and then quits @@ -13012,7 +13320,7 @@ public final ParallelFlowable parallel(int parallelism, int prefetch) { * {@link ConnectableFlowable#connect connect} method is called before it begins emitting items to those * {@link Subscriber}s that have subscribed to it. *

- * + * *

*
Backpressure:
*
The returned {@code ConnectableFlowable} honors backpressure for each of its {@code Subscriber}s @@ -13037,7 +13345,7 @@ public final ConnectableFlowable publish() { * Returns a {@code Flowable} that emits the results of invoking a specified selector on items emitted by a * {@link ConnectableFlowable} that shares a single subscription to the underlying sequence. *

- * + * *

*
Backpressure:
*
The operator expects the current {@code Flowable} to honor backpressure and if this expectation is @@ -13063,7 +13371,7 @@ public final ConnectableFlowable publish() { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable publish(@NonNull Function, ? extends Publisher> selector) { + public final <@NonNull R> Flowable publish(@NonNull Function, @NonNull ? extends Publisher> selector) { return publish(selector, bufferSize()); } @@ -13071,7 +13379,7 @@ public final Flowable publish(@NonNull Function, ? ex * Returns a {@code Flowable} that emits the results of invoking a specified selector on items emitted by a * {@link ConnectableFlowable} that shares a single subscription to the underlying sequence. *

- * + * *

*
Backpressure:
*
The operator expects the current {@code Flowable} to honor backpressure and if this expectation is @@ -13100,7 +13408,7 @@ public final Flowable publish(@NonNull Function, ? ex @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable publish(@NonNull Function, ? extends Publisher<@NonNull ? extends R>> selector, int prefetch) { + public final <@NonNull R> Flowable publish(@NonNull Function, @NonNull ? extends Publisher> selector, int prefetch) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowablePublishMulticast<>(this, selector, prefetch, false)); @@ -13111,7 +13419,7 @@ public final Flowable publish(@NonNull Function, ? ex * {@link ConnectableFlowable#connect connect} method is called before it begins emitting items to those * {@link Subscriber}s that have subscribed to it. *

- * + * *

*
Backpressure:
*
The returned {@code ConnectableFlowable} honors backpressure for each of its {@code Subscriber}s @@ -13169,7 +13477,7 @@ public final Flowable rebatchRequests(int n) { * {@code Flowable} into the same function, and so on until all items have been emitted by the current and finite {@code Flowable}, * and emits the final result from the final call to your function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate," "fold," "accumulate," * "compress," or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -13209,7 +13517,7 @@ public final Maybe reduce(@NonNull BiFunction reducer) { * emitted by the current {@code Flowable} into the same function, and so on until all items have been emitted by the * current and finite {@code Flowable}, emitting the final result from the final call to your function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate," "fold," "accumulate," * "compress," or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -13273,7 +13581,7 @@ public final Maybe reduce(@NonNull BiFunction reducer) { * all items have been emitted by the current and finite {@code Flowable}, emitting the final result from the final call to your * function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate", "fold", "accumulate", * "compress", or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -13314,7 +13622,7 @@ public final Maybe reduce(@NonNull BiFunction reducer) { /** * Returns a {@code Flowable} that repeats the sequence of items emitted by the current {@code Flowable} indefinitely. *

- * + * *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -13338,7 +13646,7 @@ public final Flowable repeat() { * Returns a {@code Flowable} that repeats the sequence of items emitted by the current {@code Flowable} at most * {@code count} times. *

- * + * *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -13373,7 +13681,7 @@ public final Flowable repeat(long times) { * Returns a {@code Flowable} that repeats the sequence of items emitted by the current {@code Flowable} until * the provided stop function returns {@code true}. *

- * + * *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -13407,7 +13715,7 @@ public final Flowable repeatUntil(@NonNull BooleanSupplier stop) { * call {@code onComplete} or {@code onError} on the child subscription. Otherwise, this {@code Publisher} will * resubscribe to the current {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -13426,7 +13734,7 @@ public final Flowable repeatUntil(@NonNull BooleanSupplier stop) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable repeatWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Flowable repeatWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { Objects.requireNonNull(handler, "handler is null"); return RxJavaPlugins.onAssembly(new FlowableRepeatWhen<>(this, handler)); } @@ -13437,7 +13745,7 @@ public final Flowable repeatWhen(@NonNull Function, * {@code Flowable} resembles an ordinary {@code Flowable}, except that it does not begin emitting items when it is * subscribed to, but only when its {@code connect} method is called. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13462,7 +13770,7 @@ public final ConnectableFlowable replay() { * Returns a {@code Flowable} that emits items that are the results of invoking a specified selector on the items * emitted by a {@link ConnectableFlowable} that shares a single subscription to the current {@code Flowable}. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13485,7 +13793,7 @@ public final ConnectableFlowable replay() { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector) { Objects.requireNonNull(selector, "selector is null"); return FlowableReplay.multicastSelector(FlowableInternalHelper.replaySupplier(this), selector); } @@ -13498,7 +13806,7 @@ public final Flowable replay(@NonNull Function, ? ext * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13525,7 +13833,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, int bufferSize) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, int bufferSize) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return FlowableReplay.multicastSelector(FlowableInternalHelper.replaySupplier(this, bufferSize, false), selector); @@ -13539,7 +13847,7 @@ public final Flowable replay(@NonNull Function, ? ext * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13568,7 +13876,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, int bufferSize, boolean eagerTruncate) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, int bufferSize, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return FlowableReplay.multicastSelector(FlowableInternalHelper.replaySupplier(this, bufferSize, eagerTruncate), selector); @@ -13582,7 +13890,7 @@ public final Flowable replay(@NonNull Function, ? ext * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13612,7 +13920,7 @@ public final Flowable replay(@NonNull Function, ? ext @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit) { return replay(selector, bufferSize, time, unit, Schedulers.computation()); } @@ -13624,7 +13932,7 @@ public final Flowable replay(@NonNull Function, ? ext * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13658,7 +13966,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); @@ -13675,7 +13983,7 @@ public final Flowable replay(@NonNull Function, ? ext * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13711,7 +14019,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); @@ -13725,7 +14033,7 @@ public final Flowable replay(@NonNull Function, ? ext * emitted by a {@link ConnectableFlowable} that shares a single subscription to the current {@code Flowable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13752,7 +14060,7 @@ public final Flowable replay(@NonNull Function, ? ext @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, long time, @NonNull TimeUnit unit) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, long time, @NonNull TimeUnit unit) { return replay(selector, time, unit, Schedulers.computation()); } @@ -13761,7 +14069,7 @@ public final Flowable replay(@NonNull Function, ? ext * emitted by a {@link ConnectableFlowable} that shares a single subscription to the current {@code Flowable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13791,7 +14099,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -13803,7 +14111,7 @@ public final Flowable replay(@NonNull Function, ? ext * emitted by a {@link ConnectableFlowable} that shares a single subscription to the current {@code Flowable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13835,7 +14143,7 @@ public final Flowable replay(@NonNull Function, ? ext @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable replay(@NonNull Function, ? extends Publisher> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { + public final <@NonNull R> Flowable replay(@NonNull Function, @NonNull ? extends Publisher> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -13853,7 +14161,7 @@ public final Flowable replay(@NonNull Function, ? ext * To ensure no beyond-bufferSize items are referenced, * use the {@link #replay(int, boolean)} overload with {@code eagerTruncate = true}. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -13884,7 +14192,7 @@ public final ConnectableFlowable replay(int bufferSize) { * an ordinary {@code Flowable}, except that it does not begin emitting items when it is subscribed to, but only * when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -13923,7 +14231,7 @@ public final ConnectableFlowable replay(int bufferSize, boolean eagerTruncate * {@code Flowable} resembles an ordinary {@code Flowable}, except that it does not begin emitting items when it is * subscribed to, but only when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -13964,7 +14272,7 @@ public final ConnectableFlowable replay(int bufferSize, long time, @NonNull T * connectable {@code Flowable} resembles an ordinary {@code Flowable}, except that it does not begin emitting items * when it is subscribed to, but only when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -14014,7 +14322,7 @@ public final ConnectableFlowable replay(int bufferSize, long time, @NonNull T * {@code bufferSize} source emissions. To ensure no out-of-date or beyond-bufferSize items * are referenced, set {@code eagerTruncate = true}. *

- * + * *

*
Backpressure:
*
This operator supports backpressure. Note that the upstream requests are determined by the child @@ -14058,7 +14366,7 @@ public final ConnectableFlowable replay(int bufferSize, long time, @NonNull T * resembles an ordinary {@code Flowable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

* Note that the internal buffer may retain strong references to the oldest item. To ensure no out-of-date items * are referenced, use the {@link #replay(long, TimeUnit, Scheduler, boolean)} overload with {@code eagerTruncate = true}. @@ -14093,7 +14401,7 @@ public final ConnectableFlowable replay(long time, @NonNull TimeUnit unit) { * resembles an ordinary {@code Flowable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

* Note that the internal buffer may retain strong references to the oldest item. To ensure no out-of-date items * are referenced, use the {@link #replay(long, TimeUnit, Scheduler, boolean)} overload with {@code eagerTruncate = true}. @@ -14133,7 +14441,7 @@ public final ConnectableFlowable replay(long time, @NonNull TimeUnit unit, @N * resembles an ordinary {@code Flowable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

* Note that the internal buffer may retain strong references to the oldest item. To ensure no out-of-date items * are referenced, set {@code eagerTruncate = true}. @@ -14173,7 +14481,7 @@ public final ConnectableFlowable replay(long time, @NonNull TimeUnit unit, @N * Returns a {@code Flowable} that mirrors the current {@code Flowable}, resubscribing to it if it calls {@code onError} * (infinite retry count). *

- * + * *

* If the current {@code Flowable} calls {@link Subscriber#onError}, this method will resubscribe to the current * {@code Flowable} rather than propagating the {@code onError} call. @@ -14205,7 +14513,7 @@ public final Flowable retry() { * Returns a {@code Flowable} that mirrors the current {@code Flowable}, resubscribing to it if it calls {@code onError} * and the predicate returns {@code true} for that specific exception and retry count. *

- * + * *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -14236,7 +14544,7 @@ public final Flowable retry(@NonNull BiPredicate<@NonNull ? super Integer, @N * Returns a {@code Flowable} that mirrors the current {@code Flowable}, resubscribing to it if it calls {@code onError} * up to a specified number of retries. *

- * + * *

* If the current {@code Flowable} calls {@link Subscriber#onError}, this method will resubscribe to the current * {@code Flowable} for a maximum of {@code count} resubscriptions rather than propagating the @@ -14349,7 +14657,7 @@ public final Flowable retryUntil(@NonNull BooleanSupplier stop) { * {@code onComplete} or {@code onError} on the child subscription. Otherwise, this {@code Publisher} will * resubscribe to the current {@code Flowable}. *

- * + * *

* Example: * @@ -14424,7 +14732,7 @@ public final Flowable retryUntil(@NonNull BooleanSupplier stop) { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) public final Flowable retryWhen( - @NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + @NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { Objects.requireNonNull(handler, "handler is null"); return RxJavaPlugins.onAssembly(new FlowableRetryWhen<>(this, handler)); @@ -14446,10 +14754,10 @@ public final Flowable retryWhen( */ @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final void safeSubscribe(@NonNull Subscriber<@NonNull ? super T> subscriber) { + public final void safeSubscribe(@NonNull Subscriber subscriber) { Objects.requireNonNull(subscriber, "subscriber is null"); if (subscriber instanceof SafeSubscriber) { - subscribe((SafeSubscriber<@NonNull ? super T>)subscriber); + subscribe((SafeSubscriber)subscriber); } else { subscribe(new SafeSubscriber<>(subscriber)); } @@ -14459,7 +14767,7 @@ public final void safeSubscribe(@NonNull Subscriber<@NonNull ? super T> subscrib * Returns a {@code Flowable} that emits the most recently emitted item (if any) emitted by the current {@code Flowable} * within periodic time intervals. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -14525,7 +14833,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, boolean emi * Returns a {@code Flowable} that emits the most recently emitted item (if any) emitted by the current {@code Flowable} * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler}. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -14552,7 +14860,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, boolean emi public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableSampleTimed<>(this, period, unit, scheduler, false)); + return RxJavaPlugins.onAssembly(new FlowableSampleTimed<>(this, period, unit, scheduler, false, null)); } /** @@ -14593,7 +14901,51 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Sc public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableSampleTimed<>(this, period, unit, scheduler, emitLast)); + return RxJavaPlugins.onAssembly(new FlowableSampleTimed<>(this, period, unit, scheduler, emitLast, null)); + } + + /** + * Returns a {@code Flowable} that emits the most recently emitted item (if any) emitted by the current {@code Flowable} + * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler} + * and optionally emit the very last upstream item when the upstream completes. + *

+ * + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow.
+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param period + * the sampling rate + * @param unit + * the {@link TimeUnit} in which {@code period} is defined + * @param scheduler + * the {@code Scheduler} to use when sampling + * @param emitLast + * if {@code true} and the upstream completes while there is still an unsampled item available, + * that item is emitted to downstream before completion + * if {@code false}, an unsampled last item is ignored. + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @see RxJava wiki: Backpressure + * @see #throttleLast(long, TimeUnit, Scheduler) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @Experimental + public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new FlowableSampleTimed<>(this, period, unit, scheduler, emitLast, onDropped)); } /** @@ -14622,7 +14974,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Sc @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable sample(@NonNull Publisher sampler) { + public final <@NonNull U> Flowable sample(@NonNull Publisher sampler) { Objects.requireNonNull(sampler, "sampler is null"); return RxJavaPlugins.onAssembly(new FlowableSamplePublisher<>(this, sampler, false)); } @@ -14660,18 +15012,17 @@ public final Flowable sample(@NonNull Publisher sampler) { @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable sample(@NonNull Publisher sampler, boolean emitLast) { + public final <@NonNull U> Flowable sample(@NonNull Publisher sampler, boolean emitLast) { Objects.requireNonNull(sampler, "sampler is null"); return RxJavaPlugins.onAssembly(new FlowableSamplePublisher<>(this, sampler, emitLast)); } /** - * Returns a {@code Flowable} that applies a specified accumulator function to the first item emitted by the current - * {@code Flowable}, then feeds the result of that function along with the second item emitted by the current - * {@code Floawble} into the same function, and so on until all items have been emitted by the current {@code Flowable}, - * emitting the result of each of these iterations. + * Returns a {@code Flowable} that emits the first value emitted by the current {@code Flowable}, then emits one value + * for each subsequent value emitted by the current {@code Flowable}. Each emission after the first is the result of + * applying the specified accumulator function to the previous emission and the corresponding value from the current {@code Flowable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -14700,12 +15051,11 @@ public final Flowable scan(@NonNull BiFunction accumulator) { } /** - * Returns a {@code Flowable} that applies a specified accumulator function to the first item emitted by the current - * {@code Flowable} and a seed value, then feeds the result of that function along with the second item emitted by - * the current {@code Flowable} into the same function, and so on until all items have been emitted by the current - * {@code Flowable}, emitting the result of each of these iterations. + * Returns a {@code Flowable} that emits the provided initial (seed) value, then emits one value for each value emitted + * by the current {@code Flowable}. Each emission after the first is the result of applying the specified accumulator + * function to the previous emission and the corresponding value from the current {@code Flowable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -14728,7 +15078,9 @@ public final Flowable scan(@NonNull BiFunction accumulator) { *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. - * Violating this expectation, a {@link MissingBackpressureException} may get signaled somewhere downstream.
+ * Violating this expectation, a {@link MissingBackpressureException} may get signaled somewhere downstream. + * The downstream request pattern is not preserved across this operator. + * The upstream is requested {@link #bufferSize()} - 1 upfront and 75% of {@link #bufferSize()} thereafter.
*
Scheduler:
*
{@code scan} does not operate by default on a particular {@link Scheduler}.
*
@@ -14754,12 +15106,11 @@ public final Flowable scan(@NonNull BiFunction accumulator) { } /** - * Returns a {@code Flowable} that applies a specified accumulator function to the first item emitted by the current - * {@code Flowable} and a seed value, then feeds the result of that function along with the second item emitted by - * the current {@code Flowable} into the same function, and so on until all items have been emitted by the current - * {@code Flowable}, emitting the result of each of these iterations. + * Returns a {@code Flowable} that emits the provided initial (seed) value, then emits one value for each value emitted + * by the current {@code Flowable}. Each emission after the first is the result of applying the specified accumulator + * function to the previous emission and the corresponding value from the current {@code Flowable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -14768,7 +15119,9 @@ public final Flowable scan(@NonNull BiFunction accumulator) { *

*
Backpressure:
*
The operator honors downstream backpressure and expects the current {@code Flowable} to honor backpressure as well. - * Violating this expectation, a {@link MissingBackpressureException} may get signaled somewhere downstream.
+ * Violating this expectation, a {@link MissingBackpressureException} may get signaled somewhere downstream. + * The downstream request pattern is not preserved across this operator. + * The upstream is requested {@link #bufferSize()} - 1 upfront and 75% of {@link #bufferSize()} thereafter.
*
Scheduler:
*
{@code scanWith} does not operate by default on a particular {@link Scheduler}.
*
@@ -14804,7 +15157,7 @@ public final Flowable scan(@NonNull BiFunction accumulator) { * {@code onNext} from two different threads concurrently. You can force such a {@code Publisher} to be * well-behaved and sequential by applying the {@code serialize} method to it. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -14831,7 +15184,7 @@ public final Flowable serialize() { *

* This is an alias for {@link #publish()}.{@link ConnectableFlowable#refCount() refCount()}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure and expects the current {@code Flowable} to honor backpressure as well. @@ -14857,7 +15210,7 @@ public final Flowable share() { * signals exactly one item or signals an {@link IllegalArgumentException} if this {@code Flowable} signals * more than one item. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -14882,7 +15235,7 @@ public final Maybe singleElement() { * emits only a single item, or a default item if the current {@code Flowable} emits no items. If the current * {@code Flowable} emits more than one item, an {@link IllegalArgumentException} is signaled instead. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -14936,7 +15289,7 @@ public final Single singleOrError() { * Returns a {@code Flowable} that skips the first {@code count} items emitted by the current {@code Flowable} and emits * the remainder. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -14969,7 +15322,7 @@ public final Flowable skip(long count) { * Returns a {@code Flowable} that skips values emitted by the current {@code Flowable} before a specified time window * elapses. *

- * + * *

*
Backpressure:
*
The operator doesn't support backpressure as it uses time to skip an arbitrary number of elements and @@ -14999,7 +15352,7 @@ public final Flowable skip(long time, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that skips values emitted by the current {@code Flowable} before a specified time window * on a specified {@link Scheduler} elapses. *

- * + * *

*
Backpressure:
*
The operator doesn't support backpressure as it uses time to skip an arbitrary number of elements and @@ -15030,7 +15383,7 @@ public final Flowable skip(long time, @NonNull TimeUnit unit, @NonNull Schedu * Returns a {@code Flowable} that drops a specified number of items from the end of the sequence emitted by the * current {@code Flowable}. *

- * + * *

* This {@link Subscriber} accumulates a queue long enough to store the first {@code count} items. As more items are * received, items are taken from the front of the queue and emitted by the resulting {@code Flowable}. This causes @@ -15068,7 +15421,7 @@ public final Flowable skipLast(int count) { * Returns a {@code Flowable} that drops items emitted by the current {@code Flowable} during a specified time window * before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -15100,7 +15453,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that drops items emitted by the current {@code Flowable} during a specified time window * before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -15135,7 +15488,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit, boolean del * Returns a {@code Flowable} that drops items emitted by the current {@code Flowable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -15168,7 +15521,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit, @NonNull Sc * Returns a {@code Flowable} that drops items emitted by the current {@code Flowable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -15204,7 +15557,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit, @NonNull Sc * Returns a {@code Flowable} that drops items emitted by the current {@code Flowable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -15248,7 +15601,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit, @NonNull Sc * Returns a {@code Flowable} that skips items emitted by the current {@code Flowable} until a second {@link Publisher} emits * an item. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -15269,7 +15622,7 @@ public final Flowable skipLast(long time, @NonNull TimeUnit unit, @NonNull Sc @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable skipUntil(@NonNull Publisher other) { + public final <@NonNull U> Flowable skipUntil(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new FlowableSkipUntil<>(this, other)); } @@ -15278,7 +15631,7 @@ public final Flowable skipUntil(@NonNull Publisher other) { * Returns a {@code Flowable} that skips all items emitted by the current {@code Flowable} as long as a specified * condition holds {@code true}, but emits all further source items as soon as the condition becomes {@code false}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -15364,7 +15717,7 @@ public final Flowable sorted(@NonNull Comparator<@NonNull ? super T> comparat * Returns a {@code Flowable} that emits the items in a specified {@link Iterable} before it begins to emit items * emitted by the current {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The Current {@code Flowable} @@ -15387,7 +15740,7 @@ public final Flowable sorted(@NonNull Comparator<@NonNull ? super T> comparat @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable startWithIterable(@NonNull Iterable<@NonNull ? extends T> items) { + public final Flowable startWithIterable(@NonNull Iterable items) { return concatArray(fromIterable(items), this); } @@ -15470,7 +15823,7 @@ public final Flowable startWith(@NonNull MaybeSource other) { * Returns a {@code Flowable} that emits the items in a specified {@link Publisher} before it begins to emit * items emitted by the current {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. Both this and the {@code other} {@code Publisher}s @@ -15490,7 +15843,7 @@ public final Flowable startWith(@NonNull MaybeSource other) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable startWith(@NonNull Publisher<@NonNull ? extends T> other) { + public final Flowable startWith(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return concatArray(other, this); } @@ -15499,7 +15852,7 @@ public final Flowable startWith(@NonNull Publisher<@NonNull ? extends T> othe * Returns a {@code Flowable} that emits a specified item before it begins to emit items emitted by the current * {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The current {@code Flowable} @@ -15531,7 +15884,7 @@ public final Flowable startWithItem(@NonNull T item) { * Returns a {@code Flowable} that emits the specified items before it begins to emit items emitted by the current * {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The current {@code Flowable} @@ -15578,6 +15931,7 @@ public final Flowable startWithArray(@NonNull T... items) { * * @return the new {@link Disposable} instance that allows cancelling the flow * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) @@ -15606,6 +15960,7 @@ public final Disposable subscribe() { * @throws NullPointerException * if {@code onNext} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @@ -15632,9 +15987,10 @@ public final Disposable subscribe(@NonNull Consumer onNext) { * the {@code Consumer} you have designed to accept any error notification from the * current {@code Flowable} * @return the new {@link Disposable} instance that allows cancelling the flow - * @see ReactiveX operators documentation: Subscribe * @throws NullPointerException * if {@code onNext} or {@code onError} is {@code null} + * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @@ -15667,6 +16023,7 @@ public final Disposable subscribe(@NonNull Consumer onNext, @NonNull * @throws NullPointerException * if {@code onNext}, {@code onError} or {@code onComplete} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @@ -15685,12 +16042,57 @@ public final Disposable subscribe(@NonNull Consumer onNext, @NonNull return ls; } + /** + * Wraps the given onXXX callbacks into a {@link Disposable} {@link Subscriber}, + * adds it to the given {@link DisposableContainer} and ensures, that if the upstream + * terminates or this particular {@code Disposable} is disposed, the {@code Subscriber} is removed + * from the given container. + *

+ * The {@code Subscriber} will be removed after the callback for the terminal event has been invoked. + *

+ *
Backpressure:
+ *
The operator consumes the current {@code Flowable} in an unbounded manner (i.e., no + * backpressure is applied to it).
+ *
Scheduler:
+ *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param onNext the callback for upstream items + * @param onError the callback for an upstream error if any + * @param onComplete the callback for the upstream completion if any + * @param container the {@code DisposableContainer} (such as {@link CompositeDisposable}) to add and remove the + * created {@code Disposable} {@code Subscriber} + * @return the {@code Disposable} that allows disposing the particular subscription. + * @throws NullPointerException + * if {@code onNext}, {@code onError}, + * {@code onComplete} or {@code container} is {@code null} + * @since 3.1.0 + */ + @BackpressureSupport(BackpressureKind.SPECIAL) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Disposable subscribe( + @NonNull Consumer onNext, + @NonNull Consumer onError, + @NonNull Action onComplete, + @NonNull DisposableContainer container) { + Objects.requireNonNull(onNext, "onNext is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(onComplete, "onComplete is null"); + Objects.requireNonNull(container, "container is null"); + + DisposableAutoReleaseSubscriber subscriber = new DisposableAutoReleaseSubscriber<>( + container, onNext, onError, onComplete); + container.add(subscriber); + subscribe(subscriber); + return subscriber; + } + @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) @Override - public final void subscribe(@NonNull Subscriber<@NonNull ? super T> subscriber) { + public final void subscribe(@NonNull Subscriber subscriber) { if (subscriber instanceof FlowableSubscriber) { - subscribe((FlowableSubscriber<@NonNull ? super T>)subscriber); + subscribe((FlowableSubscriber)subscriber); } else { Objects.requireNonNull(subscriber, "subscriber is null"); subscribe(new StrictSubscriber<>(subscriber)); @@ -15737,10 +16139,10 @@ public final void subscribe(@NonNull Subscriber<@NonNull ? super T> subscriber) */ @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public final void subscribe(@NonNull FlowableSubscriber<@NonNull ? super T> subscriber) { + public final void subscribe(@NonNull FlowableSubscriber subscriber) { Objects.requireNonNull(subscriber, "subscriber is null"); try { - Subscriber<@NonNull ? super T> flowableSubscriber = RxJavaPlugins.onSubscribe(this, subscriber); + Subscriber flowableSubscriber = RxJavaPlugins.onSubscribe(this, subscriber); Objects.requireNonNull(flowableSubscriber, "The RxJavaPlugins.onSubscribe hook returned a null FlowableSubscriber. Please check the handler provided to RxJavaPlugins.setOnFlowableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins"); @@ -15767,7 +16169,7 @@ public final void subscribe(@NonNull FlowableSubscriber<@NonNull ? super T> subs * applied by {@link #subscribe(Subscriber)} before this method gets called. * @param subscriber the incoming {@code Subscriber}, never {@code null} */ - protected abstract void subscribeActual(@NonNull Subscriber<@NonNull ? super T> subscriber); + protected abstract void subscribeActual(@NonNull Subscriber subscriber); /** * Subscribes a given {@link Subscriber} (subclass) to this {@code Flowable} and returns the given @@ -15800,7 +16202,7 @@ public final void subscribe(@NonNull FlowableSubscriber<@NonNull ? super T> subs @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final <@NonNull E extends Subscriber<@NonNull ? super T>> E subscribeWith(E subscriber) { + public final <@NonNull E extends Subscriber> E subscribeWith(E subscriber) { subscribe(subscriber); return subscriber; } @@ -15812,7 +16214,7 @@ public final void subscribe(@NonNull FlowableSubscriber<@NonNull ? super T> subs * chain, it is recommended to use {@code subscribeOn(scheduler, false)} instead * to avoid same-pool deadlock because requests may pile up behind an eager/blocking emitter. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -15847,7 +16249,7 @@ public final Flowable subscribeOn(@NonNull Scheduler scheduler) { * chain, it is recommended to have {@code requestOn} {@code false} to avoid same-pool deadlock * because requests may pile up behind an eager/blocking emitter. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -15903,7 +16305,7 @@ public final Flowable subscribeOn(@NonNull Scheduler scheduler, boolean reque @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable switchIfEmpty(@NonNull Publisher<@NonNull ? extends T> other) { + public final Flowable switchIfEmpty(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchIfEmpty<>(this, other)); } @@ -15916,7 +16318,7 @@ public final Flowable switchIfEmpty(@NonNull Publisher<@NonNull ? extends T> * The resulting {@code Flowable} completes if both the current {@code Flowable} and the last inner {@code Publisher}, if any, complete. * If the current {@code Flowable} signals an {@code onError}, the inner {@code Publisher} is canceled and the error delivered in-sequence. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The outer {@code Publisher} is consumed in an @@ -15940,7 +16342,7 @@ public final Flowable switchIfEmpty(@NonNull Publisher<@NonNull ? extends T> @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable switchMap(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMap(@NonNull Function> mapper) { return switchMap(mapper, bufferSize()); } @@ -15952,7 +16354,7 @@ public final Flowable switchMap(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The outer {@code Publisher} is consumed in an @@ -15979,7 +16381,7 @@ public final Flowable switchMap(@NonNull Function Flowable switchMap(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Flowable switchMap(@NonNull Function> mapper, int bufferSize) { return switchMap0(mapper, bufferSize, false); } @@ -16087,7 +16489,7 @@ public final Completable switchMapCompletableDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The outer {@code Publisher} is consumed in an @@ -16112,7 +16514,7 @@ public final Completable switchMapCompletableDelayError(@NonNull Function Flowable switchMapDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMapDelayError(@NonNull Function> mapper) { return switchMapDelayError(mapper, bufferSize()); } @@ -16125,7 +16527,7 @@ public final Flowable switchMapDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The outer {@code Publisher} is consumed in an @@ -16153,11 +16555,11 @@ public final Flowable switchMapDelayError(@NonNull Function Flowable switchMapDelayError(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Flowable switchMapDelayError(@NonNull Function> mapper, int bufferSize) { return switchMap0(mapper, bufferSize, true); } - Flowable switchMap0(Function> mapper, int bufferSize, boolean delayError) { + Flowable switchMap0(Function> mapper, int bufferSize, boolean delayError) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); if (this instanceof ScalarSupplier) { @@ -16177,7 +16579,7 @@ Flowable switchMap0(Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The main {@code Flowable} is consumed in an @@ -16208,7 +16610,7 @@ Flowable switchMap0(Function Flowable switchMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMapMaybe(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapMaybe<>(this, mapper, false)); } @@ -16218,7 +16620,7 @@ public final Flowable switchMapMaybe(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The main {@code Flowable} is consumed in an @@ -16240,7 +16642,7 @@ public final Flowable switchMapMaybe(@NonNull Function Flowable switchMapMaybeDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMapMaybeDelayError(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapMaybe<>(this, mapper, true)); } @@ -16251,7 +16653,7 @@ public final Flowable switchMapMaybeDelayError(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The main {@code Flowable} is consumed in an @@ -16282,7 +16684,7 @@ public final Flowable switchMapMaybeDelayError(@NonNull Function Flowable switchMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMapSingle(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapSingle<>(this, mapper, false)); } @@ -16292,7 +16694,7 @@ public final Flowable switchMapSingle(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The main {@code Flowable} is consumed in an @@ -16314,16 +16716,16 @@ public final Flowable switchMapSingle(@NonNull Function Flowable switchMapSingleDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Flowable switchMapSingleDelayError(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapSingle<>(this, mapper, true)); } /** - * Returns a {@code Flowable} that emits only the first {@code count} items emitted by the current {@code Flowable}. If the source emits fewer than - * {@code count} items then all of its items are emitted. + * Returns a {@code Flowable} that emits only the first {@code count} items emitted by the current {@code Flowable}. + * If the source emits fewer than {@code count} items then all of its items are emitted. *

- * + * *

* This method returns a {@code Flowable} that will invoke a subscribing {@link Subscriber}'s * {@link Subscriber#onNext onNext} function a maximum of {@code count} times before invoking @@ -16334,15 +16736,15 @@ public final Flowable switchMapSingleDelayError(@NonNull Function * The operator requests at most the given {@code count} of items from upstream even - * if the downstream requests more than that. For example, given a {@code limit(5)}, + * if the downstream requests more than that. For example, given a {@code take(5)}, * if the downstream requests 1, a request of 1 is submitted to the upstream * and the operator remembers that only 4 items can be requested now on. A request * of 5 at this point will request 4 from the upstream and any subsequent requests will * be ignored. *

- * Note that requests are negotiated on an operator boundary and {@code limit}'s amount + * Note that requests are negotiated on an operator boundary and {@code take}'s amount * may not be preserved further upstream. For example, - * {@code source.observeOn(Schedulers.computation()).limit(5)} will still request the + * {@code source.observeOn(Schedulers.computation()).take(5)} will still request the * default (128) elements from the given {@code source}. *

*
Backpressure:
@@ -16377,7 +16779,7 @@ public final Flowable take(long count) { * If time runs out before the {@code Flowable} completes normally, the {@code onComplete} event will be * signaled on the default {@code computation} {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -16409,7 +16811,7 @@ public final Flowable take(long time, @NonNull TimeUnit unit) { * If time runs out before the {@code Flowable} completes normally, the {@code onComplete} event will be * signaled on the provided {@code Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -16440,7 +16842,7 @@ public final Flowable take(long time, @NonNull TimeUnit unit, @NonNull Schedu * Returns a {@code Flowable} that emits at most the last {@code count} items emitted by the current {@code Flowable}. If the source emits fewer than * {@code count} items then all of its items are emitted. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream if the {@code count} is non-zero; ignores @@ -16478,7 +16880,7 @@ public final Flowable takeLast(int count) { * Returns a {@code Flowable} that emits at most a specified number of items from the current {@code Flowable} that were * emitted in a specified window of time before the current {@code Flowable} completed. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16512,7 +16914,7 @@ public final Flowable takeLast(long count, long time, @NonNull TimeUnit unit) * emitted in a specified window of time before the current {@code Flowable} completed, where the timing information is * provided by a given {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16548,7 +16950,7 @@ public final Flowable takeLast(long count, long time, @NonNull TimeUnit unit, * emitted in a specified window of time before the current {@code Flowable} completed, where the timing information is * provided by a given {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16594,7 +16996,7 @@ public final Flowable takeLast(long count, long time, @NonNull TimeUnit unit, * Returns a {@code Flowable} that emits the items from the current {@code Flowable} that were emitted in a specified * window of time before the current {@code Flowable} completed. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16625,7 +17027,7 @@ public final Flowable takeLast(long time, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits the items from the current {@code Flowable} that were emitted in a specified * window of time before the current {@code Flowable} completed. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16660,7 +17062,7 @@ public final Flowable takeLast(long time, @NonNull TimeUnit unit, boolean del * window of time before the current {@code Flowable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16694,7 +17096,7 @@ public final Flowable takeLast(long time, @NonNull TimeUnit unit, @NonNull Sc * window of time before the current {@code Flowable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16731,7 +17133,7 @@ public final Flowable takeLast(long time, @NonNull TimeUnit unit, @NonNull Sc * window of time before the current {@code Flowable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -16770,7 +17172,7 @@ public final Flowable takeLast(long time, @NonNull TimeUnit unit, @NonNull Sc * Returns a {@code Flowable} that emits items emitted by the current {@code Flowable}, checks the specified predicate * for each item, and then completes when the condition is satisfied. *

- * + * *

* The difference between this operator and {@link #takeWhile(Predicate)} is that here, the condition is * evaluated after the item is emitted. @@ -16802,9 +17204,9 @@ public final Flowable takeUntil(@NonNull Predicate stopPredicate) /** * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} until a second {@link Publisher} - * emits an item. + * emits an item or completes. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -16814,7 +17216,7 @@ public final Flowable takeUntil(@NonNull Predicate stopPredicate) *
* * @param other - * the {@code Publisher} whose first emitted item will cause {@code takeUntil} to stop emitting items + * the {@code Publisher} whose first emitted item or completion will cause {@code takeUntil} to stop emitting items * from the current {@code Flowable} * @param * the type of items emitted by {@code other} @@ -16826,7 +17228,7 @@ public final Flowable takeUntil(@NonNull Predicate stopPredicate) @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable takeUntil(@NonNull Publisher other) { + public final <@NonNull U> Flowable takeUntil(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new FlowableTakeUntil<>(this, other)); } @@ -16835,7 +17237,7 @@ public final Flowable takeUntil(@NonNull Publisher other) { * Returns a {@code Flowable} that emits items emitted by the current {@code Flowable} so long as each item satisfied a * specified condition, and then completes as soon as this condition is not satisfied. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -16867,7 +17269,7 @@ public final Flowable takeWhile(@NonNull Predicate predicate) { * This differs from {@link #throttleLast} in that this only tracks the passage of time whereas * {@link #throttleLast} ticks at scheduled intervals. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -16899,7 +17301,7 @@ public final Flowable throttleFirst(long windowDuration, @NonNull TimeUnit un * This differs from {@link #throttleLast} in that this only tracks the passage of time whereas * {@link #throttleLast} ticks at scheduled intervals. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -16926,7 +17328,50 @@ public final Flowable throttleFirst(long windowDuration, @NonNull TimeUnit un public final Flowable throttleFirst(long skipDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableThrottleFirstTimed<>(this, skipDuration, unit, scheduler)); + return RxJavaPlugins.onAssembly(new FlowableThrottleFirstTimed<>(this, skipDuration, unit, scheduler, null)); + } + + /** + * Returns a {@code Flowable} that emits only the first item emitted by the current {@code Flowable} during sequential + * time windows of a specified duration, where the windows are managed by a specified {@link Scheduler}. + *

+ * This differs from {@link #throttleLast} in that this only tracks the passage of time whereas + * {@link #throttleLast} ticks at scheduled intervals. + *

+ * + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow.
+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param skipDuration + * time to wait before emitting another item after emitting the last item + * @param unit + * the unit of time of {@code skipDuration} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle timeout for each + * event + * @param onDropped + * called when an item doesn't get delivered to the downstream + * + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @see RxJava wiki: Backpressure + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @Experimental + public final Flowable throttleFirst(long skipDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new FlowableThrottleFirstTimed<>(this, skipDuration, unit, scheduler, onDropped)); } /** @@ -16936,7 +17381,7 @@ public final Flowable throttleFirst(long skipDuration, @NonNull TimeUnit unit * This differs from {@link #throttleFirst} in that this ticks along at a scheduled interval whereas * {@link #throttleFirst} does not tick, it just tracks the passage of time. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -16970,7 +17415,7 @@ public final Flowable throttleLast(long intervalDuration, @NonNull TimeUnit u * This differs from {@link #throttleFirst(long, TimeUnit, Scheduler)} in that this ticks along at a scheduled interval whereas * {@code throttleFirst} does not tick, it just tracks the passage of time. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -17000,6 +17445,47 @@ public final Flowable throttleLast(long intervalDuration, @NonNull TimeUnit u return sample(intervalDuration, unit, scheduler); } + /** + * Returns a {@code Flowable} that emits only the last item emitted by the current {@code Flowable} during sequential + * time windows of a specified duration, where the duration is governed by a specified {@link Scheduler}. + *

+ * This differs from {@link #throttleFirst(long, TimeUnit, Scheduler)} in that this ticks along at a scheduled interval whereas + * {@code throttleFirst} does not tick, it just tracks the passage of time. + *

+ * + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow.
+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param intervalDuration + * duration of windows within which the last item emitted by the current {@code Flowable} will be + * emitted + * @param unit + * the unit of time of {@code intervalDuration} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle timeout for each + * event + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @see RxJava wiki: Backpressure + * @see #sample(long, TimeUnit, Scheduler) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Flowable throttleLast(long intervalDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + return sample(intervalDuration, unit, scheduler, false, onDropped); + } + /** * Throttles items from the upstream {@code Flowable} by first emitting the next * item from upstream, then periodically emitting the latest item (if any) when @@ -17157,7 +17643,61 @@ public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, @N public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableThrottleLatest<>(this, timeout, unit, scheduler, emitLast)); + return RxJavaPlugins.onAssembly(new FlowableThrottleLatest<>(this, timeout, unit, scheduler, emitLast, null)); + } + + /** + * Throttles items from the upstream {@code Flowable} by first emitting the next + * item from upstream, then periodically emitting the latest item (if any) when + * the specified timeout elapses between them, invoking the consumer for any dropped item. + *

+ * + *

+ * If no items were emitted from the upstream during this timeout phase, the next + * upstream item is emitted immediately and the timeout window starts from then. + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow. + * If the downstream is not ready to receive items, a + * {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException MissingBackpressureException} + * will be signaled.
+ *
Scheduler:
+ *
You specify which {@link Scheduler} this operator will use.
+ *
Error handling:
+ *
+ * If the upstream signals an {@code onError} or {@code onDropped} callback crashes, + * the error is delivered immediately to the downstream. If both happen, a {@link CompositeException} + * is created, containing both the upstream and the callback error. + * If the {@code onDropped} callback crashes during cancellation, the exception is forwarded + * to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
+ *
+ * @param timeout the time to wait after an item emission towards the downstream + * before trying to emit the latest item from upstream again + * @param unit the time unit + * @param scheduler the {@code Scheduler} where the timed wait and latest item + * emission will be performed + * @param emitLast If {@code true}, the very last item from the upstream will be emitted + * immediately when the upstream completes, regardless if there is + * a timeout window active or not. If {@code false}, the very last + * upstream item is ignored and the flow terminates. + * @param onDropped called when an item is replaced by a newer item that doesn't get delivered + * to the downstream, including the very last item if {@code emitLast} is {@code false} + * and the current undelivered item when the sequence gets canceled. + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code onDropped} is {@code null} + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @Experimental + public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new FlowableThrottleLatest<>(this, timeout, unit, scheduler, emitLast, onDropped)); } /** @@ -17168,7 +17708,7 @@ public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, @N * Note: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items * will be emitted by the resulting {@code Flowable}. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -17204,7 +17744,7 @@ public final Flowable throttleWithTimeout(long timeout, @NonNull TimeUnit uni * Note: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items * will be emitted by the resulting {@code Flowable}. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -17235,11 +17775,54 @@ public final Flowable throttleWithTimeout(long timeout, @NonNull TimeUnit uni return debounce(timeout, unit, scheduler); } + /** + * Returns a {@code Flowable} that mirrors the current {@code Flowable}, except that it drops items emitted by the + * current {@code Flowable} that are followed by newer items before a timeout value expires on a specified + * {@link Scheduler}. The timer resets on each emission (alias to {@link #debounce(long, TimeUnit, Scheduler, Consumer)}). + *

+ * Note: If items keep being emitted by the current {@code Flowable} faster than the timeout then no items + * will be emitted by the resulting {@code Flowable}. + *

+ * + *

+ *
Backpressure:
+ *
This operator does not support backpressure as it uses time to control data flow.
+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param timeout + * the length of the window of time that must pass after the emission of an item from the current + * {@code Flowable} in which it emits no items in order for the item to be emitted by the + * resulting {@code Flowable} + * @param unit + * the unit of time for the specified {@code timeout} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle the timeout for each + * item + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Debounce + * @see RxJava wiki: Backpressure + * @see #debounce(long, TimeUnit, Scheduler, Consumer) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.ERROR) + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Flowable throttleWithTimeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + return debounce(timeout, unit, scheduler, onDropped); + } + /** * Returns a {@code Flowable} that emits records of the time interval between consecutive items emitted by the * current {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17264,7 +17847,7 @@ public final Flowable> timeInterval() { * Returns a {@code Flowable} that emits records of the time interval between consecutive items emitted by the * current {@code Flowable}, where this interval is computed on a specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17292,7 +17875,7 @@ public final Flowable> timeInterval(@NonNull Scheduler scheduler) { * Returns a {@code Flowable} that emits records of the time interval between consecutive items emitted by the * current {@code Flowable}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17319,7 +17902,7 @@ public final Flowable> timeInterval(@NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits records of the time interval between consecutive items emitted by the * current {@code Flowable}, where this interval is computed on a specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17352,7 +17935,7 @@ public final Flowable> timeInterval(@NonNull TimeUnit unit, @NonNull Sc * time after the emission of the previous item, where that period of time is measured by a {@link Publisher} that * is a function of the previous item. *

- * + * *

* Note: The arrival of the first source item is never timed out. *

@@ -17378,7 +17961,7 @@ public final Flowable> timeInterval(@NonNull TimeUnit unit, @NonNull Sc @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable timeout(@NonNull Function> itemTimeoutIndicator) { + public final <@NonNull V> Flowable timeout(@NonNull Function> itemTimeoutIndicator) { return timeout0(null, itemTimeoutIndicator, null); } @@ -17388,7 +17971,7 @@ public final Flowable timeout(@NonNull Function - * + * *

* Note: The arrival of the first source item is never timed out. *

@@ -17416,7 +17999,7 @@ public final Flowable timeout(@NonNull Function Flowable timeout(@NonNull Function> itemTimeoutIndicator, @NonNull Publisher<@NonNull ? extends T> fallback) { + public final <@NonNull V> Flowable timeout(@NonNull Function> itemTimeoutIndicator, @NonNull Publisher fallback) { Objects.requireNonNull(fallback, "fallback is null"); return timeout0(null, itemTimeoutIndicator, fallback); } @@ -17426,7 +18009,7 @@ public final Flowable timeout(@NonNull Function - * + * *
*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17456,7 +18039,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit) { * item. If the next item isn't emitted within the specified timeout duration starting from its predecessor, * the current {@code Flowable} is disposed and the resulting {@code Flowable} begins instead to mirror a fallback {@link Publisher}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -17481,7 +18064,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit) { @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) - public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Publisher<@NonNull ? extends T> fallback) { + public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Publisher fallback) { Objects.requireNonNull(fallback, "fallback is null"); return timeout0(timeout, unit, fallback, Schedulers.computation()); } @@ -17492,7 +18075,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * starting from its predecessor, the current {@code Flowable} is disposed and the resulting {@code Flowable} begins * instead to mirror a fallback {@link Publisher}. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -17519,7 +18102,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Publisher<@NonNull ? extends T> fallback) { + public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Publisher fallback) { Objects.requireNonNull(fallback, "fallback is null"); return timeout0(timeout, unit, fallback, scheduler); } @@ -17530,7 +18113,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * specified timeout duration starting from its predecessor, the resulting {@code Flowable} terminates and * notifies {@link Subscriber}s of a {@link TimeoutException}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17562,7 +18145,7 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * {@link TimeoutException} if either the first item emitted by the current {@code Flowable} or any subsequent item * doesn't arrive within time windows defined by other {@link Publisher}s. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. Both this and the returned {@code Publisher}s @@ -17591,8 +18174,8 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable timeout(@NonNull Publisher firstTimeoutIndicator, - @NonNull Function> itemTimeoutIndicator) { + public final <@NonNull U, @NonNull V> Flowable timeout(@NonNull Publisher firstTimeoutIndicator, + @NonNull Function> itemTimeoutIndicator) { Objects.requireNonNull(firstTimeoutIndicator, "firstTimeoutIndicator is null"); return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, null); } @@ -17602,7 +18185,7 @@ public final Flowable timeout(@NonNull Publisher firstTimeoutIndica * the first item emitted by the current {@code Flowable} or any subsequent item doesn't arrive within time windows * defined by other {@code Publisher}s. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream. The {@code Publisher} @@ -17634,26 +18217,26 @@ public final Flowable timeout(@NonNull Publisher firstTimeoutIndica @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable timeout( + public final <@NonNull U, @NonNull V> Flowable timeout( @NonNull Publisher firstTimeoutIndicator, - @NonNull Function> itemTimeoutIndicator, - @NonNull Publisher<@NonNull ? extends T> fallback) { + @NonNull Function> itemTimeoutIndicator, + @NonNull Publisher fallback) { Objects.requireNonNull(firstTimeoutIndicator, "firstTimeoutIndicator is null"); Objects.requireNonNull(fallback, "fallback is null"); return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, fallback); } - private Flowable timeout0(long timeout, TimeUnit unit, Publisher<@NonNull ? extends T> fallback, + private Flowable timeout0(long timeout, TimeUnit unit, Publisher fallback, Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); return RxJavaPlugins.onAssembly(new FlowableTimeoutTimed<>(this, timeout, unit, scheduler, fallback)); } - private Flowable timeout0( + private <@NonNull U, @NonNull V> Flowable timeout0( Publisher firstTimeoutIndicator, - Function> itemTimeoutIndicator, - Publisher<@NonNull ? extends T> fallback) { + Function> itemTimeoutIndicator, + Publisher fallback) { Objects.requireNonNull(itemTimeoutIndicator, "itemTimeoutIndicator is null"); return RxJavaPlugins.onAssembly(new FlowableTimeout<>(this, firstTimeoutIndicator, itemTimeoutIndicator, fallback)); } @@ -17662,7 +18245,7 @@ private Flowable timeout0( * Returns a {@code Flowable} that emits each item emitted by the current {@code Flowable}, wrapped in a * {@link Timed} object. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17687,7 +18270,7 @@ public final Flowable> timestamp() { * Returns a {@code Flowable} that emits each item emitted by the current {@code Flowable}, wrapped in a * {@link Timed} object whose timestamps are provided by a specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17715,7 +18298,7 @@ public final Flowable> timestamp(@NonNull Scheduler scheduler) { * Returns a {@code Flowable} that emits each item emitted by the current {@code Flowable}, wrapped in a * {@link Timed} object. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17742,7 +18325,7 @@ public final Flowable> timestamp(@NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits each item emitted by the current {@code Flowable}, wrapped in a * {@link Timed} object whose timestamps are provided by a specified {@link Scheduler}. *

- * + * *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure @@ -17789,7 +18372,7 @@ public final Flowable> timestamp(@NonNull TimeUnit unit, @NonNull Sched @CheckReturnValue @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public final R to(@NonNull FlowableConverter converter) { + public final <@NonNull R> R to(@NonNull FlowableConverter converter) { return Objects.requireNonNull(converter, "converter is null").apply(this); } @@ -17797,7 +18380,7 @@ public final R to(@NonNull FlowableConverter converter) { * Returns a {@link Single} that emits a single item, a list composed of all the items emitted by the * finite upstream source {@link Publisher}. *

- * + * *

* Normally, a {@code Publisher} that returns multiple items will do so by invoking its {@link Subscriber}'s * {@link Subscriber#onNext onNext} method for each such item. You can change this behavior by having the @@ -17831,7 +18414,7 @@ public final Single> toList() { * Returns a {@link Single} that emits a single item, a list composed of all the items emitted by the * finite source {@link Publisher}. *

- * + * *

* Normally, a {@code Publisher} that returns multiple items will do so by invoking its {@link Subscriber}'s * {@link Subscriber#onNext onNext} method for each such item. You can change this behavior by having the @@ -17869,7 +18452,7 @@ public final Single> toList(int capacityHint) { * Returns a {@link Single} that emits a single item, a list composed of all the items emitted by the * finite source {@link Publisher}. *

- * + * *

* Normally, a {@code Publisher} that returns multiple items will do so by invoking its {@link Subscriber}'s * {@link Subscriber#onNext onNext} method for each such item. You can change this behavior by having the @@ -17899,7 +18482,7 @@ public final Single> toList(int capacityHint) { @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Single toList(@NonNull Supplier collectionSupplier) { + public final <@NonNull U extends Collection> Single toList(@NonNull Supplier collectionSupplier) { Objects.requireNonNull(collectionSupplier, "collectionSupplier is null"); return RxJavaPlugins.onAssembly(new FlowableToListSingle<>(this, collectionSupplier)); } @@ -17908,7 +18491,7 @@ public final > Single toList(@NonNull Supplie * Returns a {@link Single} that emits a single {@link HashMap} containing all items emitted by the finite source {@link Publisher}, * mapped by the keys returned by a specified {@code keySelector} function. *

- * + * *

* If more than one source item maps to the same key, the {@code HashMap} will contain the latest of those items. *

@@ -17934,7 +18517,7 @@ public final > Single toList(@NonNull Supplie @NonNull @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) - public final Single> toMap(@NonNull Function keySelector) { + public final <@NonNull K> Single> toMap(@NonNull Function keySelector) { Objects.requireNonNull(keySelector, "keySelector is null"); return collect(HashMapSupplier.asSupplier(), Functions.toMapKeySelector(keySelector)); } @@ -17943,7 +18526,7 @@ public final Single> toMap(@NonNull Function - * + * *

* If more than one source item maps to the same key, the {@code HashMap} will contain a single entry that * corresponds to the latest of those items. @@ -17973,7 +18556,7 @@ public final Single> toMap(@NonNull Function Single> toMap(@NonNull Function keySelector, @NonNull Function valueSelector) { + public final <@NonNull K, @NonNull V> Single> toMap(@NonNull Function keySelector, @NonNull Function valueSelector) { Objects.requireNonNull(keySelector, "keySelector is null"); Objects.requireNonNull(valueSelector, "valueSelector is null"); return collect(HashMapSupplier.asSupplier(), Functions.toMapKeyValueSelector(keySelector, valueSelector)); @@ -17983,7 +18566,7 @@ public final Single> toMap(@NonNull Function - * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18012,7 +18595,7 @@ public final Single> toMap(@NonNull Function Single> toMap(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Single> toMap(@NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier> mapSupplier) { Objects.requireNonNull(keySelector, "keySelector is null"); @@ -18024,7 +18607,7 @@ public final Single> toMap(@NonNull Function - * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18047,7 +18630,7 @@ public final Single> toMap(@NonNull Function Single>> toMultimap(@NonNull Function keySelector) { + public final <@NonNull K> Single>> toMultimap(@NonNull Function keySelector) { Function valueSelector = Functions.identity(); Supplier>> mapSupplier = HashMapSupplier.asSupplier(); Function> collectionFactory = ArrayListSupplier.asFunction(); @@ -18059,7 +18642,7 @@ public final Single>> toMultimap(@NonNull Function - * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18086,7 +18669,7 @@ public final Single>> toMultimap(@NonNull Function Single>> toMultimap(@NonNull Function keySelector, @NonNull Function valueSelector) { + public final <@NonNull K, @NonNull V> Single>> toMultimap(@NonNull Function keySelector, @NonNull Function valueSelector) { Supplier>> mapSupplier = HashMapSupplier.asSupplier(); Function> collectionFactory = ArrayListSupplier.asFunction(); return toMultimap(keySelector, valueSelector, mapSupplier, collectionFactory); @@ -18097,7 +18680,7 @@ public final Single>> toMultimap(@NonNull Function - * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18128,7 +18711,7 @@ public final Single>> toMultimap(@NonNull Function Single>> toMultimap( + public final <@NonNull K, @NonNull V> Single>> toMultimap( @NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier>> mapSupplier, @@ -18145,7 +18728,7 @@ public final Single>> toMultimap( * contains an {@link ArrayList} of values, extracted by a specified {@code valueSelector} function from items * emitted by the finite source {@link Publisher} and keyed by the {@code keySelector} function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18174,7 +18757,7 @@ public final Single>> toMultimap( @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single>> toMultimap( + public final <@NonNull K, @NonNull V> Single>> toMultimap( @NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier>> mapSupplier @@ -18211,7 +18794,7 @@ public final Observable toObservable() { * all other items emitted by this {@code Flowable}, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated list to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18238,7 +18821,7 @@ public final Single> toSortedList() { * Returns a {@link Single} that emits a {@link List} that contains the items emitted by the finite source {@link Publisher}, in a * sorted order based on a specified comparison function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated list to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18271,7 +18854,7 @@ public final Single> toSortedList(@NonNull Comparator compara * Returns a {@link Single} that emits a {@link List} that contains the items emitted by the finite source {@link Publisher}, in a * sorted order based on a specified comparison function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated list to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18313,7 +18896,7 @@ public final Single> toSortedList(@NonNull Comparator compara * all other items emitted by this {@code Flowable}, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated list to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -18377,7 +18960,7 @@ public final Flowable unsubscribeOn(@NonNull Scheduler scheduler) { * {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the current window and * propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window will only contain one element. The behavior is @@ -18410,7 +18993,7 @@ public final Flowable> window(long count) { * the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the current window * and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18447,7 +19030,7 @@ public final Flowable> window(long count, long skip) { * the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the current window * and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18490,7 +19073,7 @@ public final Flowable> window(long count, long skip, int bufferSize) * {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18532,7 +19115,7 @@ public final Flowable> window(long timespan, long timeskip, @NonNull * {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18576,7 +19159,7 @@ public final Flowable> window(long timespan, long timeskip, @NonNull * {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18627,7 +19210,7 @@ public final Flowable> window(long timespan, long timeskip, @NonNull * {@code timespan} argument. When the current {@code Flowable} completes or encounters an error, the resulting * {@code Flowable} emits the current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18667,7 +19250,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit) * reached first). When the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} * emits the current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18711,7 +19294,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit, * reached first). When the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} * emits the current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18756,7 +19339,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit, * {@code timespan} argument. When the current {@code Flowable} completes or encounters an error, the resulting * {@code Flowable} emits the current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18800,7 +19383,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit, * first). When the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18846,7 +19429,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit, * first). When the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18894,7 +19477,7 @@ public final Flowable> window(long timespan, @NonNull TimeUnit unit, * first). When the current {@code Flowable} completes or encounters an error, the resulting {@code Flowable} emits the * current window and propagates the notification from the current {@code Flowable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18947,7 +19530,7 @@ public final Flowable> window( * where the boundary of each window is determined by the items emitted from a specified boundary-governing * {@link Publisher}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -18973,7 +19556,7 @@ public final Flowable> window( @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> window(@NonNull Publisher boundaryIndicator) { + public final <@NonNull B> Flowable> window(@NonNull Publisher boundaryIndicator) { return window(boundaryIndicator, bufferSize()); } @@ -18982,7 +19565,7 @@ public final Flowable> window(@NonNull Publisher boundaryIndi * where the boundary of each window is determined by the items emitted from a specified boundary-governing * {@link Publisher}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -19011,7 +19594,7 @@ public final Flowable> window(@NonNull Publisher boundaryIndi @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable> window(@NonNull Publisher boundaryIndicator, int bufferSize) { + public final <@NonNull B> Flowable> window(@NonNull Publisher boundaryIndicator, int bufferSize) { Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new FlowableWindowBoundary<>(this, boundaryIndicator, bufferSize)); @@ -19023,7 +19606,7 @@ public final Flowable> window(@NonNull Publisher boundaryIndi * the {@code windowOpenings} {@link Publisher} emits an item and when the {@code Publisher} returned by * {@code closingSelector} emits an item. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -19054,9 +19637,9 @@ public final Flowable> window(@NonNull Publisher boundaryIndi @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable> window( + public final <@NonNull U, @NonNull V> Flowable> window( @NonNull Publisher openingIndicator, - @NonNull Function> closingIndicator) { + @NonNull Function> closingIndicator) { return window(openingIndicator, closingIndicator, bufferSize()); } @@ -19066,7 +19649,7 @@ public final Flowable> window( * the {@code windowOpenings} {@link Publisher} emits an item and when the {@code Publisher} returned by * {@code closingSelector} emits an item. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -19100,9 +19683,9 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.ERROR) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable> window( + public final <@NonNull U, @NonNull V> Flowable> window( @NonNull Publisher openingIndicator, - @NonNull Function> closingIndicator, int bufferSize) { + @NonNull Function> closingIndicator, int bufferSize) { Objects.requireNonNull(openingIndicator, "openingIndicator is null"); Objects.requireNonNull(closingIndicator, "closingIndicator is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); @@ -19112,8 +19695,15 @@ public final Flowable> window( /** * Merges the specified {@link Publisher} into the current {@code Flowable} sequence by using the {@code resultSelector} * function only when the current {@code Flowable} (this instance) emits an item. + * + *

Note that this operator doesn't emit anything until the other source has produced at + * least one value. The resulting emission only happens when the current {@code Flowable} emits (and + * not when the other source emits, unlike combineLatest). + * If the other source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before the other source has produced at least one value, the sequence completes + * without emission. *

- * + * * *

*
Backpressure:
@@ -19140,7 +19730,7 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable withLatestFrom(@NonNull Publisher<@NonNull ? extends U> other, + public final <@NonNull U, @NonNull R> Flowable withLatestFrom(@NonNull Publisher other, @NonNull BiFunction combiner) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -19156,6 +19746,8 @@ public final Flowable> window( * least one value. The resulting emission only happens when the current {@code Flowable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. * *
*
Backpressure:
@@ -19179,7 +19771,7 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable withLatestFrom(@NonNull Publisher source1, @NonNull Publisher source2, + public final <@NonNull T1, @NonNull T2, @NonNull R> Flowable withLatestFrom(@NonNull Publisher source1, @NonNull Publisher source2, @NonNull Function3 combiner) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -19196,6 +19788,8 @@ public final Flowable> window( * least one value. The resulting emission only happens when the current {@code Flowable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. * *
*
Backpressure:
@@ -19221,7 +19815,7 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable withLatestFrom( + public final <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Flowable withLatestFrom( @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, @NonNull Function4 combiner) { @@ -19241,6 +19835,8 @@ public final Flowable> window( * least one value. The resulting emission only happens when the current {@code Flowable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. * *
*
Backpressure:
@@ -19269,7 +19865,7 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable withLatestFrom( + public final <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Flowable withLatestFrom( @NonNull Publisher source1, @NonNull Publisher source2, @NonNull Publisher source3, @NonNull Publisher source4, @NonNull Function5 combiner) { @@ -19290,6 +19886,8 @@ public final Flowable> window( * least one value. The resulting emission only happens when the current {@code Flowable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. * *
*
Backpressure:
@@ -19324,6 +19922,8 @@ public final Flowable> window( * least one value. The resulting emission only happens when the current {@code Flowable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. * *
*
Backpressure:
@@ -19344,7 +19944,7 @@ public final Flowable> window( @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ?>> others, @NonNull Function combiner) { + public final <@NonNull R> Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ?>> others, @NonNull Function combiner) { Objects.requireNonNull(others, "others is null"); Objects.requireNonNull(combiner, "combiner is null"); return RxJavaPlugins.onAssembly(new FlowableWithLatestFromMany<>(this, others, combiner)); @@ -19354,7 +19954,7 @@ public final Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends * Returns a {@code Flowable} that emits items that are the result of applying a specified function to pairs of * values, one each from the current {@code Flowable} and a specified {@link Iterable} sequence. *

- * + * *

* Note that the {@code other} {@code Iterable} is evaluated as items are observed from the current {@code Flowable}; it is * not pre-consumed. This allows you to zip infinite streams on either side. @@ -19384,7 +19984,7 @@ public final Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final <@NonNull U, R> Flowable zipWith(@NonNull Iterable other, @NonNull BiFunction zipper) { + public final <@NonNull U, @NonNull R> Flowable zipWith(@NonNull Iterable other, @NonNull BiFunction zipper) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(zipper, "zipper is null"); return RxJavaPlugins.onAssembly(new FlowableZipIterable<>(this, other, zipper)); @@ -19406,7 +20006,7 @@ public final Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -19433,7 +20033,7 @@ public final Flowable withLatestFrom(@NonNull Iterable<@NonNull ? extends @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> other, @NonNull BiFunction zipper) { + public final <@NonNull U, @NonNull R> Flowable zipWith(@NonNull Publisher other, @NonNull BiFunction zipper) { Objects.requireNonNull(other, "other is null"); return zip(this, other, zipper); } @@ -19454,7 +20054,7 @@ public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -19484,7 +20084,7 @@ public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> other, + public final <@NonNull U, @NonNull R> Flowable zipWith(@NonNull Publisher other, @NonNull BiFunction zipper, boolean delayError) { return zip(this, other, zipper, delayError); } @@ -19505,7 +20105,7 @@ public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> * use {@link #doOnCancel(Action)} as well or use {@code using()} to do cleanup in case of completion * or cancellation. *

- * + * *

*
Backpressure:
*
The operator expects backpressure from the sources and honors backpressure from the downstream. @@ -19538,7 +20138,7 @@ public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable zipWith(@NonNull Publisher<@NonNull ? extends U> other, + public final <@NonNull U, @NonNull R> Flowable zipWith(@NonNull Publisher other, @NonNull BiFunction zipper, boolean delayError, int bufferSize) { return zip(this, other, zipper, delayError, bufferSize); } @@ -19653,7 +20253,7 @@ public final TestSubscriber test(long initialRequest, boolean cancel) { // No @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable<@NonNull T> fromOptional(@NonNull Optional optional) { + public static <@NonNull T> Flowable<@NonNull T> fromOptional(@NonNull Optional optional) { Objects.requireNonNull(optional, "optional is null"); return optional.map(Flowable::just).orElseGet(Flowable::empty); } @@ -19664,7 +20264,7 @@ public final TestSubscriber test(long initialRequest, boolean cancel) { // No * *

* Note that the operator takes an already instantiated, running or terminated {@code CompletionStage}. - * If the optional is to be created per consumer upon subscription, use {@link #defer(Supplier)} + * If the {@code CompletionStage} is to be created per consumer upon subscription, use {@link #defer(Supplier)} * around {@code fromCompletionStage}: *


      * Flowable.defer(() -> Flowable.fromCompletionStage(createCompletionStage()));
@@ -19691,7 +20291,7 @@ public final TestSubscriber test(long initialRequest, boolean cancel) { // No
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Flowable<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
+    public static <@NonNull T> Flowable<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
         Objects.requireNonNull(stage, "stage is null");
         return RxJavaPlugins.onAssembly(new FlowableFromCompletionStage<>(stage));
     }
@@ -19738,7 +20338,7 @@ public final TestSubscriber test(long initialRequest, boolean cancel) { // No
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Flowable<@NonNull T> fromStream(@NonNull Stream stream) {
+    public static <@NonNull T> Flowable<@NonNull T> fromStream(@NonNull Stream stream) {
         Objects.requireNonNull(stream, "stream is null");
         return RxJavaPlugins.onAssembly(new FlowableFromStream<>(stream));
     }
@@ -19799,7 +20399,7 @@ public final TestSubscriber test(long initialRequest, boolean cancel) { // No
     @BackpressureSupport(BackpressureKind.UNBOUNDED_IN)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R, A> Single collect(@NonNull Collector collector) {
+    public final <@NonNull R, @Nullable A> Single collect(@NonNull Collector collector) {
         Objects.requireNonNull(collector, "collector is null");
         return RxJavaPlugins.onAssembly(new FlowableCollectWithCollectorSingle<>(this, collector));
     }
@@ -20125,7 +20725,7 @@ public final Stream blockingStream(int prefetch) {
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Flowable concatMapStream(@NonNull Function> mapper) {
+    public final <@NonNull R> Flowable concatMapStream(@NonNull Function> mapper) {
         return flatMapStream(mapper, bufferSize());
     }
 
@@ -20180,7 +20780,7 @@ public final Stream blockingStream(int prefetch) {
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Flowable concatMapStream(@NonNull Function> mapper, int prefetch) {
+    public final <@NonNull R> Flowable concatMapStream(@NonNull Function> mapper, int prefetch) {
         Objects.requireNonNull(mapper, "mapper is null");
         ObjectHelper.verifyPositive(prefetch, "prefetch");
         return RxJavaPlugins.onAssembly(new FlowableFlatMapStream<>(this, mapper, prefetch));
@@ -20236,7 +20836,7 @@ public final Stream blockingStream(int prefetch) {
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Flowable flatMapStream(@NonNull Function> mapper) {
+    public final <@NonNull R> Flowable flatMapStream(@NonNull Function> mapper) {
         return flatMapStream(mapper, bufferSize());
     }
 
@@ -20291,7 +20891,7 @@ public final Stream blockingStream(int prefetch) {
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Flowable flatMapStream(@NonNull Function> mapper, int prefetch) {
+    public final <@NonNull R> Flowable flatMapStream(@NonNull Function> mapper, int prefetch) {
         Objects.requireNonNull(mapper, "mapper is null");
         ObjectHelper.verifyPositive(prefetch, "prefetch");
         return RxJavaPlugins.onAssembly(new FlowableFlatMapStream<>(this, mapper, prefetch));
diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableConverter.java b/src/main/java/io/reactivex/rxjava3/core/FlowableConverter.java
index d0b1814fb8f..1db19b9144f 100644
--- a/src/main/java/io/reactivex/rxjava3/core/FlowableConverter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/FlowableConverter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableEmitter.java b/src/main/java/io/reactivex/rxjava3/core/FlowableEmitter.java
index 8304edca71e..5ad6850389b 100644
--- a/src/main/java/io/reactivex/rxjava3/core/FlowableEmitter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/FlowableEmitter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/core/FlowableOnSubscribe.java
index 129c6ac7b6a..6c5263b779c 100644
--- a/src/main/java/io/reactivex/rxjava3/core/FlowableOnSubscribe.java
+++ b/src/main/java/io/reactivex/rxjava3/core/FlowableOnSubscribe.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,13 +10,14 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
 
 /**
  * A functional interface that has a {@code subscribe()} method that receives
- * an instance of a {@link FlowableEmitter} instance that allows pushing
+ * a {@link FlowableEmitter} instance that allows pushing
  * events in a backpressure-safe and cancellation-safe manner.
  *
  * @param  the value type pushed
diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableOperator.java b/src/main/java/io/reactivex/rxjava3/core/FlowableOperator.java
index aed58cff89f..aa2d5ff0e7c 100644
--- a/src/main/java/io/reactivex/rxjava3/core/FlowableOperator.java
+++ b/src/main/java/io/reactivex/rxjava3/core/FlowableOperator.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableSubscriber.java b/src/main/java/io/reactivex/rxjava3/core/FlowableSubscriber.java
index 38b5bf34590..f97eadbd37b 100644
--- a/src/main/java/io/reactivex/rxjava3/core/FlowableSubscriber.java
+++ b/src/main/java/io/reactivex/rxjava3/core/FlowableSubscriber.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -18,8 +18,10 @@
 import io.reactivex.rxjava3.annotations.NonNull;
 
 /**
- * Represents a Reactive-Streams inspired {@link Subscriber} that is RxJava 2 only
- * and weakens rules §1.3 and §3.9 of the specification for gaining performance.
+ * Represents a Reactive-Streams inspired {@link Subscriber} that is RxJava 3 only
+ * and weakens the Reactive Streams rules §1.3
+ * and §3.9 of the specification
+ * for gaining performance.
  *
  * 

History: 2.0.7 - experimental; 2.1 - beta * @param the value type diff --git a/src/main/java/io/reactivex/rxjava3/core/FlowableTransformer.java b/src/main/java/io/reactivex/rxjava3/core/FlowableTransformer.java index 8aa444afccc..fe51a2d5d7e 100644 --- a/src/main/java/io/reactivex/rxjava3/core/FlowableTransformer.java +++ b/src/main/java/io/reactivex/rxjava3/core/FlowableTransformer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 784343922da..8ae4137c839 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,8 +20,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; -import io.reactivex.rxjava3.core.Observable; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.*; @@ -111,7 +110,7 @@ * @since 2.0 * @see io.reactivex.rxjava3.observers.DisposableMaybeObserver */ -public abstract class Maybe implements MaybeSource { +public abstract class Maybe<@NonNull T> implements MaybeSource { /** * Runs multiple {@link MaybeSource}s provided by an {@link Iterable} sequence and @@ -131,7 +130,7 @@ public abstract class Maybe implements MaybeSource { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe amb(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Maybe amb(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new MaybeAmb<>(null, sources)); } @@ -155,7 +154,7 @@ public static Maybe amb(@NonNull Iterable<@NonNull ? extends MaybeSource< @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Maybe ambArray(@NonNull MaybeSource... sources) { + public static <@NonNull T> Maybe ambArray(@NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -188,7 +187,7 @@ public static Maybe ambArray(@NonNull MaybeSource... sources @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concat(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new MaybeConcatIterable<>(sources)); } @@ -217,7 +216,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends MaybeS @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { + public static <@NonNull T> Flowable concat(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return concatArray(source1, source2); @@ -249,7 +248,7 @@ public static Flowable concat(@NonNull MaybeSource source1, @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( + public static <@NonNull T> Flowable concat( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -285,7 +284,7 @@ public static Flowable concat( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( + public static <@NonNull T> Flowable concat( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -316,7 +315,7 @@ public static Flowable concat( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concat(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return concat(sources, 2); } @@ -344,7 +343,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Maybe @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapMaybePublisher<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, prefetch)); @@ -371,7 +370,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Maybe @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable concatArray(@NonNull MaybeSource... sources) { + public static <@NonNull T> Flowable concatArray(@NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return Flowable.empty(); @@ -405,7 +404,7 @@ public static Flowable concatArray(@NonNull MaybeSource... s @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable concatArrayDelayError(@NonNull MaybeSource... sources) { + public static <@NonNull T> Flowable concatArrayDelayError(@NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return Flowable.empty(); @@ -443,7 +442,7 @@ public static Flowable concatArrayDelayError(@NonNull MaybeSource Flowable concatArrayEager(@NonNull MaybeSource... sources) { + public static <@NonNull T> Flowable concatArrayEager(@NonNull MaybeSource... sources) { return Flowable.fromArray(sources).concatMapEager((Function)MaybeToPublisher.instance()); } /** @@ -472,7 +471,7 @@ public static Flowable concatArrayEager(@NonNull MaybeSource @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Flowable concatArrayEagerDelayError(@NonNull MaybeSource... sources) { + public static <@NonNull T> Flowable concatArrayEagerDelayError(@NonNull MaybeSource... sources) { return Flowable.fromArray(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); } @@ -498,7 +497,7 @@ public static Flowable concatArrayEagerDelayError(@NonNull MaybeSource Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { return Flowable.fromIterable(sources).concatMapMaybeDelayError(Functions.identity()); } @@ -524,7 +523,7 @@ public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return Flowable.fromPublisher(sources).concatMapMaybeDelayError(Functions.identity()); } /** @@ -549,12 +548,13 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext * @return the new {@code Flowable} with the concatenating behavior * @throws NullPointerException if {@code sources} is {@code null} * @throws IllegalArgumentException if {@code prefetch} is non-positive + * @since 3.0.0 */ @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { return Flowable.fromPublisher(sources).concatMapMaybeDelayError(Functions.identity(), true, prefetch); } @@ -582,7 +582,7 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), false); } @@ -615,7 +615,7 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends M @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), false, maxConcurrency, 1); } @@ -645,7 +645,7 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends M @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return Flowable.fromPublisher(sources).concatMapEager((Function)MaybeToPublisher.instance()); } @@ -680,7 +680,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { return Flowable.fromPublisher(sources).concatMapEager((Function)MaybeToPublisher.instance(), maxConcurrency, 1); } @@ -710,7 +710,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); } @@ -744,7 +744,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true, maxConcurrency, 1); } @@ -776,7 +776,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return Flowable.fromPublisher(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); } @@ -812,7 +812,7 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { return Flowable.fromPublisher(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true, maxConcurrency, 1); } @@ -866,7 +866,7 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe create(@NonNull MaybeOnSubscribe onSubscribe) { + public static <@NonNull T> Maybe create(@NonNull MaybeOnSubscribe onSubscribe) { Objects.requireNonNull(onSubscribe, "onSubscribe is null"); return RxJavaPlugins.onAssembly(new MaybeCreate<>(onSubscribe)); } @@ -889,7 +889,7 @@ public static Maybe create(@NonNull MaybeOnSubscribe onSubscribe) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe defer(@NonNull Supplier> supplier) { + public static <@NonNull T> Maybe defer(@NonNull Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new MaybeDefer<>(supplier)); } @@ -898,7 +898,7 @@ public static Maybe defer(@NonNull Supplier - * + * *

*
Scheduler:
*
{@code empty} does not operate by default on a particular {@link Scheduler}.
@@ -910,7 +910,7 @@ public static Maybe defer(@NonNull Supplier Maybe empty() { + public static <@NonNull T> Maybe empty() { return RxJavaPlugins.onAssembly((Maybe)MaybeEmpty.INSTANCE); } @@ -935,7 +935,7 @@ public static Maybe empty() { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe error(@NonNull Throwable throwable) { + public static <@NonNull T> Maybe error(@NonNull Throwable throwable) { Objects.requireNonNull(throwable, "throwable is null"); return RxJavaPlugins.onAssembly(new MaybeError<>(throwable)); } @@ -961,13 +961,13 @@ public static Maybe error(@NonNull Throwable throwable) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe error(@NonNull Supplier supplier) { + public static <@NonNull T> Maybe error(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new MaybeErrorCallable<>(supplier)); } /** - * Returns a {@code Maybe} instance that runs the given {@link Action} for each observer and + * Returns a {@code Maybe} instance that runs the given {@link Action} for each {@link MaybeObserver} and * emits either its exception or simply completes. *

* @@ -983,14 +983,14 @@ public static Maybe error(@NonNull Supplier supplier *

*
* @param the target type - * @param action the {@code Action} to run for each observer + * @param action the {@code Action} to run for each {@code MaybeObserver} * @return the new {@code Maybe} instance * @throws NullPointerException if {@code action} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromAction(@NonNull Action action) { + public static <@NonNull T> Maybe fromAction(@NonNull Action action) { Objects.requireNonNull(action, "action is null"); return RxJavaPlugins.onAssembly(new MaybeFromAction<>(action)); } @@ -1011,7 +1011,7 @@ public static Maybe fromAction(@NonNull Action action) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromCompletable(@NonNull CompletableSource completableSource) { + public static <@NonNull T> Maybe fromCompletable(@NonNull CompletableSource completableSource) { Objects.requireNonNull(completableSource, "completableSource is null"); return RxJavaPlugins.onAssembly(new MaybeFromCompletable<>(completableSource)); } @@ -1032,7 +1032,7 @@ public static Maybe fromCompletable(@NonNull CompletableSource completabl @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromSingle(@NonNull SingleSource single) { + public static <@NonNull T> Maybe fromSingle(@NonNull SingleSource single) { Objects.requireNonNull(single, "single is null"); return RxJavaPlugins.onAssembly(new MaybeFromSingle<>(single)); } @@ -1079,7 +1079,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static <@NonNull T> Maybe fromCallable(@NonNull Callable callable) { + public static Maybe<@NonNull T> fromCallable(@NonNull Callable callable) { Objects.requireNonNull(callable, "callable is null"); return RxJavaPlugins.onAssembly(new MaybeFromCallable<>(callable)); } @@ -1109,6 +1109,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { * @return the new {@code Maybe} instance * @throws NullPointerException if {@code future} is {@code null} * @see ReactiveX operators documentation: From + * @see #fromCompletionStage(CompletionStage) */ @CheckReturnValue @NonNull @@ -1147,6 +1148,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { * @return the new {@code Maybe} instance * @throws NullPointerException if {@code future} or {@code unit} is {@code null} * @see ReactiveX operators documentation: From + * @see #fromCompletionStage(CompletionStage) */ @CheckReturnValue @NonNull @@ -1175,7 +1177,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromObservable(@NonNull ObservableSource source) { + public static <@NonNull T> Maybe fromObservable(@NonNull ObservableSource source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new ObservableElementAtMaybe<>(source, 0L)); } @@ -1202,29 +1204,42 @@ public static Maybe fromObservable(@NonNull ObservableSource source) { @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) - public static Maybe fromPublisher(@NonNull Publisher source) { + public static <@NonNull T> Maybe fromPublisher(@NonNull Publisher source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new FlowableElementAtMaybePublisher<>(source, 0L)); } /** - * Returns a {@code Maybe} instance that runs the given {@link Runnable} for each observer and - * emits either its exception or simply completes. + * Returns a {@code Maybe} instance that runs the given {@link Runnable} for each {@link MaybeObserver} and + * emits either its unchecked exception or simply completes. *

* + *

+ * If the code to be wrapped needs to throw a checked or more broader {@link Throwable} exception, that + * exception has to be converted to an unchecked exception by the wrapped code itself. Alternatively, + * use the {@link #fromAction(Action)} method which allows the wrapped code to throw any {@code Throwable} + * exception and will signal it to observers as-is. *

*
Scheduler:
*
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the {@code Runnable} throws an exception, the respective {@code Throwable} is + * delivered to the downstream via {@link MaybeObserver#onError(Throwable)}, + * except when the downstream has disposed this {@code Maybe} source. + * In this latter case, the {@code Throwable} is delivered to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. + *
*
* @param the target type - * @param run the {@code Runnable} to run for each observer + * @param run the {@code Runnable} to run for each {@code MaybeObserver} * @return the new {@code Maybe} instance * @throws NullPointerException if {@code run} is {@code null} + * @see #fromAction(Action) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromRunnable(@NonNull Runnable run) { + public static <@NonNull T> Maybe fromRunnable(@NonNull Runnable run) { Objects.requireNonNull(run, "run is null"); return RxJavaPlugins.onAssembly(new MaybeFromRunnable<>(run)); } @@ -1239,7 +1254,7 @@ public static Maybe fromRunnable(@NonNull Runnable run) { * subscribes to the returned {@code Maybe}. In other terms, this source operator evaluates the given * {@code Supplier} "lazily". *

- * + * *

* Note that the {@code null} handling of this operator differs from the similar source operators in the other * {@link io.reactivex.rxjava3.core base reactive classes}. Those operators signal a {@link NullPointerException} if the value returned by their @@ -1272,7 +1287,7 @@ public static Maybe fromRunnable(@NonNull Runnable run) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static <@NonNull T> Maybe fromSupplier(@NonNull Supplier supplier) { + public static Maybe<@NonNull T> fromSupplier(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new MaybeFromSupplier<>(supplier)); } @@ -1339,7 +1354,7 @@ public static Maybe fromRunnable(@NonNull Runnable run) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable merge(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { return Flowable.fromIterable(sources).flatMapMaybe(Functions.identity(), false, Integer.MAX_VALUE); } @@ -1377,7 +1392,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends MaybeSo @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return merge(sources, Integer.MAX_VALUE); } @@ -1417,7 +1432,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeS @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new FlowableFlatMapMaybePublisher<>(sources, Functions.identity(), false, maxConcurrency)); @@ -1450,7 +1465,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeS @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Maybe merge(@NonNull MaybeSource> source) { + public static <@NonNull T> Maybe merge(@NonNull MaybeSource> source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new MaybeFlatten(source, Functions.identity())); } @@ -1496,7 +1511,7 @@ public static Maybe merge(@NonNull MaybeSource Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull MaybeSource source1, @NonNull MaybeSource source2 ) { Objects.requireNonNull(source1, "source1 is null"); @@ -1547,7 +1562,7 @@ public static Flowable merge( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3 ) { @@ -1602,7 +1617,7 @@ public static Flowable merge( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4 ) { @@ -1648,7 +1663,7 @@ public static Flowable merge( @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable mergeArray(MaybeSource... sources) { + public static <@NonNull T> Flowable mergeArray(MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return Flowable.empty(); @@ -1693,7 +1708,7 @@ public static Flowable mergeArray(MaybeSource... sources) { @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArrayDelayError(@NonNull MaybeSource... sources) { + public static <@NonNull T> Flowable mergeArrayDelayError(@NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); return Flowable.fromArray(sources).flatMapMaybe(Functions.identity(), true, Math.max(1, sources.length)); } @@ -1731,7 +1746,7 @@ public static Flowable mergeArrayDelayError(@NonNull MaybeSource Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { return Flowable.fromIterable(sources).flatMapMaybe(Functions.identity(), true, Integer.MAX_VALUE); } @@ -1767,7 +1782,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { return mergeDelayError(sources, Integer.MAX_VALUE); } @@ -1806,7 +1821,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new FlowableFlatMapMaybePublisher<>(sources, Functions.identity(), true, maxConcurrency)); @@ -1845,7 +1860,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return mergeArrayDelayError(source1, source2); @@ -1887,7 +1902,7 @@ public static Flowable mergeDelayError(@NonNull MaybeSource @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull MaybeSource source1, + public static <@NonNull T> Flowable mergeDelayError(@NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -1933,7 +1948,7 @@ public static Flowable mergeDelayError(@NonNull MaybeSource @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError( + public static <@NonNull T> Flowable mergeDelayError( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4) { Objects.requireNonNull(source1, "source1 is null"); @@ -1946,7 +1961,7 @@ public static Flowable mergeDelayError( /** * Returns a {@code Maybe} that never sends any items or notifications to a {@link MaybeObserver}. *

- * + * *

* This {@code Maybe} is useful primarily for testing purposes. *

@@ -1963,7 +1978,7 @@ public static Flowable mergeDelayError( @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings("unchecked") @NonNull - public static Maybe never() { + public static <@NonNull T> Maybe never() { return RxJavaPlugins.onAssembly((Maybe)MaybeNever.INSTANCE); } @@ -1990,7 +2005,7 @@ public static Maybe never() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { + public static <@NonNull T> Single sequenceEqual(@NonNull MaybeSource source1, @NonNull MaybeSource source2) { return sequenceEqual(source1, source2, ObjectHelper.equalsPredicate()); } @@ -2020,7 +2035,7 @@ public static Single sequenceEqual(@NonNull MaybeSource Single sequenceEqual(@NonNull MaybeSource source1, @NonNull MaybeSource source2, + public static <@NonNull T> Single sequenceEqual(@NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull BiPredicate isEqual) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -2057,7 +2072,7 @@ public static Single sequenceEqual(@NonNull MaybeSource Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapMaybePublisher<>(sources, Functions.identity(), false)); } @@ -2092,7 +2107,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + public static <@NonNull T> Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapMaybePublisher<>(sources, Functions.identity(), true)); } @@ -2168,7 +2183,7 @@ public static Maybe timer(long delay, @NonNull TimeUnit unit, @NonNull Sch @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { + public static <@NonNull T> Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { if (onSubscribe instanceof Maybe) { throw new IllegalArgumentException("unsafeCreate(Maybe) should be upgraded"); } @@ -2201,7 +2216,7 @@ public static Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Maybe using(@NonNull Supplier resourceSupplier, + public static <@NonNull T, @NonNull D> Maybe using(@NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup) { return using(resourceSupplier, sourceSupplier, resourceCleanup, true); @@ -2240,7 +2255,7 @@ public static Maybe using(@NonNull Supplier resourceSuppl @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe using(@NonNull Supplier resourceSupplier, + public static <@NonNull T, @NonNull D> Maybe using(@NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); @@ -2266,7 +2281,7 @@ public static Maybe using(@NonNull Supplier resourceSuppl @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe wrap(@NonNull MaybeSource source) { + public static <@NonNull T> Maybe wrap(@NonNull MaybeSource source) { if (source instanceof Maybe) { return RxJavaPlugins.onAssembly((Maybe)source); } @@ -2305,7 +2320,7 @@ public static Maybe wrap(@NonNull MaybeSource source) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, @NonNull Function zipper) { + public static <@NonNull T, @NonNull R> Maybe zip(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, @NonNull Function zipper) { Objects.requireNonNull(zipper, "zipper is null"); Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new MaybeZipIterable<>(sources, zipper)); @@ -2341,7 +2356,7 @@ public static Maybe zip(@NonNull Iterable<@NonNull ? extends MaybeSour @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull BiFunction zipper) { Objects.requireNonNull(source1, "source1 is null"); @@ -2383,7 +2398,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull Function3 zipper) { Objects.requireNonNull(source1, "source1 is null"); @@ -2430,7 +2445,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull Function4 zipper) { @@ -2482,7 +2497,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull MaybeSource source5, @NonNull Function5 zipper) { @@ -2538,7 +2553,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull MaybeSource source5, @NonNull MaybeSource source6, @NonNull Function6 zipper) { @@ -2599,7 +2614,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull MaybeSource source5, @NonNull MaybeSource source6, @NonNull MaybeSource source7, @@ -2665,7 +2680,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull MaybeSource source5, @NonNull MaybeSource source6, @NonNull MaybeSource source7, @NonNull MaybeSource source8, @@ -2734,7 +2749,7 @@ public static Maybe zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Maybe zip( @NonNull MaybeSource source1, @NonNull MaybeSource source2, @NonNull MaybeSource source3, @NonNull MaybeSource source4, @NonNull MaybeSource source5, @NonNull MaybeSource source6, @NonNull MaybeSource source7, @NonNull MaybeSource source8, @NonNull MaybeSource source9, @@ -2785,7 +2800,7 @@ public static Maybe zip( @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Maybe zipArray(@NonNull Function zipper, + public static <@NonNull T, @NonNull R> Maybe zipArray(@NonNull Function zipper, @NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { @@ -3045,7 +3060,7 @@ public final Maybe cache() { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe cast(@NonNull Class clazz) { + public final <@NonNull U> Maybe cast(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return map(Functions.castFunction(clazz)); } @@ -3075,7 +3090,7 @@ public final Maybe cast(@NonNull Class clazz) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Maybe compose(@NonNull MaybeTransformer transformer) { + public final <@NonNull R> Maybe compose(@NonNull MaybeTransformer transformer) { return wrap(((MaybeTransformer) Objects.requireNonNull(transformer, "transformer is null")).apply(this)); } @@ -3100,7 +3115,7 @@ public final Maybe compose(@NonNull MaybeTransformer Maybe concatMap(@NonNull Function> mapper) { + public final <@NonNull R> Maybe concatMap(@NonNull Function> mapper) { return flatMap(mapper); } @@ -3156,7 +3171,7 @@ public final Completable concatMapCompletable(@NonNull Function Maybe concatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Maybe concatMapSingle(@NonNull Function> mapper) { return flatMapSingle(mapper); } @@ -3431,7 +3446,7 @@ public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Schedule @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) - public final Maybe delay(@NonNull Publisher delayIndicator) { + public final <@NonNull U> Maybe delay(@NonNull Publisher delayIndicator) { Objects.requireNonNull(delayIndicator, "delayIndicator is null"); return RxJavaPlugins.onAssembly(new MaybeDelayOtherPublisher<>(this, delayIndicator)); } @@ -3458,7 +3473,7 @@ public final Maybe delay(@NonNull Publisher delayIndicator) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe delaySubscription(@NonNull Publisher subscriptionIndicator) { + public final <@NonNull U> Maybe delaySubscription(@NonNull Publisher subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new MaybeDelaySubscriptionOtherPublisher<>(this, subscriptionIndicator)); } @@ -3628,7 +3643,7 @@ public final Maybe doOnDispose(@NonNull Action onDispose) { /** * Invokes an {@link Action} just before the current {@code Maybe} calls {@code onComplete}. *

- * + * *

*
Scheduler:
*
{@code doOnComplete} does not operate by default on a particular {@link Scheduler}.
@@ -3658,7 +3673,7 @@ public final Maybe doOnComplete(@NonNull Action onComplete) { * Calls the shared {@link Consumer} with the error sent via {@code onError} for each * {@link MaybeObserver} that subscribes to the current {@code Maybe}. *

- * + * *

*
Scheduler:
*
{@code doOnError} does not operate by default on a particular {@link Scheduler}.
@@ -3793,7 +3808,7 @@ public final Maybe doOnTerminate(@NonNull Action onTerminate) { * Calls the shared {@link Consumer} with the success value sent via {@code onSuccess} for each * {@link MaybeObserver} that subscribes to the current {@code Maybe}. *

- * + * *

*
Scheduler:
*
{@code doOnSuccess} does not operate by default on a particular {@link Scheduler}.
@@ -3862,7 +3877,7 @@ public final Maybe filter(@NonNull Predicate predicate) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe flatMap(@NonNull Function> mapper) { + public final <@NonNull R> Maybe flatMap(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatten<>(this, mapper)); } @@ -3892,7 +3907,7 @@ public final Maybe flatMap(@NonNull Function Maybe flatMap( + public final <@NonNull R> Maybe flatMap( @NonNull Function> onSuccessMapper, @NonNull Function> onErrorMapper, @NonNull Supplier> onCompleteSupplier) { @@ -3928,7 +3943,7 @@ public final Maybe flatMap( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Maybe flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -3961,7 +3976,7 @@ public final Maybe flatMap(@NonNull Function Flowable flattenAsFlowable(@NonNull Function> mapper) { + public final <@NonNull U> Flowable flattenAsFlowable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatMapIterableFlowable<>(this, mapper)); } @@ -3988,7 +4003,7 @@ public final Flowable flattenAsFlowable(@NonNull Function Observable flattenAsObservable(@NonNull Function> mapper) { + public final <@NonNull U> Observable flattenAsObservable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatMapIterableObservable<>(this, mapper)); } @@ -4013,7 +4028,7 @@ public final Observable flattenAsObservable(@NonNull Function Observable flatMapObservable(@NonNull Function> mapper) { + public final <@NonNull R> Observable flatMapObservable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatMapObservable<>(this, mapper)); } @@ -4042,7 +4057,7 @@ public final Observable flatMapObservable(@NonNull Function Flowable flatMapPublisher(@NonNull Function> mapper) { + public final <@NonNull R> Flowable flatMapPublisher(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatMapPublisher<>(this, mapper)); } @@ -4071,7 +4086,7 @@ public final Flowable flatMapPublisher(@NonNull Function Maybe flatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Maybe flatMapSingle(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeFlatMapSingle<>(this, mapper)); } @@ -4311,7 +4326,7 @@ public final Single isEmpty() { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe lift(@NonNull MaybeOperator lift) { + public final <@NonNull R> Maybe lift(@NonNull MaybeOperator lift) { Objects.requireNonNull(lift, "lift is null"); return RxJavaPlugins.onAssembly(new MaybeLift<>(this, lift)); } @@ -4336,7 +4351,7 @@ public final Maybe lift(@NonNull MaybeOperator li @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe map(@NonNull Function mapper) { + public final <@NonNull R> Maybe map(@NonNull Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new MaybeMap<>(this, mapper)); } @@ -4345,7 +4360,7 @@ public final Maybe map(@NonNull Function mapper) * Maps the signal types of this {@code Maybe} into a {@link Notification} of the same kind * and emits it as a {@link Single}'s {@code onSuccess} value to downstream. *

- * + * *

*
Scheduler:
*
{@code materialize} does not operate by default on a particular {@link Scheduler}.
@@ -4438,7 +4453,7 @@ public final Maybe observeOn(@NonNull Scheduler scheduler) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe ofType(@NonNull Class clazz) { + public final <@NonNull U> Maybe ofType(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return filter(Functions.isInstanceOf(clazz)).cast(clazz); } @@ -4830,7 +4845,7 @@ public final Flowable repeatUntil(@NonNull BooleanSupplier stop) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable repeatWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Flowable repeatWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return toFlowable().repeatWhen(handler); } @@ -5048,7 +5063,7 @@ public final Maybe retryUntil(@NonNull BooleanSupplier stop) { @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Maybe retryWhen( - @NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + @NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return toFlowable().retryWhen(handler).singleElement(); } @@ -5213,6 +5228,7 @@ public final Flowable startWith(@NonNull Publisher other) { * * @return the new {@link Disposable} instance that can be used for disposing the subscription at any time * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @SchedulerSupport(SchedulerSupport.NONE) @NonNull @@ -5237,6 +5253,7 @@ public final Disposable subscribe() { * @throws NullPointerException * if {@code onSuccess} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -5259,10 +5276,11 @@ public final Disposable subscribe(@NonNull Consumer onSuccess) { * the {@code Consumer} you have designed to accept any error notification from the * {@code Maybe} * @return the new {@link Disposable} instance that can be used for disposing the subscription at any time - * @see ReactiveX operators documentation: Subscribe * @throws NullPointerException * if {@code onSuccess} is {@code null}, or * if {@code onError} is {@code null} + * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -5292,6 +5310,7 @@ public final Disposable subscribe(@NonNull Consumer onSuccess, @NonNu * if {@code onSuccess}, {@code onError} or * {@code onComplete} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @NonNull @@ -5304,6 +5323,47 @@ public final Disposable subscribe(@NonNull Consumer onSuccess, @NonNu return subscribeWith(new MaybeCallbackObserver<>(onSuccess, onError, onComplete)); } + /** + * Wraps the given onXXX callbacks into a {@link Disposable} {@link MaybeObserver}, + * adds it to the given {@link DisposableContainer} and ensures, that if the upstream + * terminates or this particular {@code Disposable} is disposed, the {@code MaybeObserver} is removed + * from the given composite. + *

+ * The {@code MaybeObserver} will be removed after the callback for the terminal event has been invoked. + *

+ *
Scheduler:
+ *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param onSuccess the callback for upstream items + * @param onError the callback for an upstream error + * @param onComplete the callback for an upstream completion without any value or error + * @param container the {@code DisposableContainer} (such as {@link CompositeDisposable}) to add and remove the + * created {@code Disposable} {@code MaybeObserver} + * @return the {@code Disposable} that allows disposing the particular subscription. + * @throws NullPointerException + * if {@code onSuccess}, {@code onError}, + * {@code onComplete} or {@code container} is {@code null} + * @since 3.1.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Disposable subscribe( + @NonNull Consumer onSuccess, + @NonNull Consumer onError, + @NonNull Action onComplete, + @NonNull DisposableContainer container) { + Objects.requireNonNull(onSuccess, "onSuccess is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(onComplete, "onComplete is null"); + Objects.requireNonNull(container, "container is null"); + + DisposableAutoReleaseMultiObserver observer = new DisposableAutoReleaseMultiObserver<>( + container, onSuccess, onError, onComplete); + container.add(observer); + subscribe(observer); + return observer; + } + @SchedulerSupport(SchedulerSupport.NONE) @Override public final void subscribe(@NonNull MaybeObserver observer) { @@ -5459,7 +5519,7 @@ public final Single switchIfEmpty(@NonNull SingleSource other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe takeUntil(@NonNull MaybeSource other) { + public final <@NonNull U> Maybe takeUntil(@NonNull MaybeSource other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new MaybeTakeUntilMaybe<>(this, other)); } @@ -5490,7 +5550,7 @@ public final Maybe takeUntil(@NonNull MaybeSource other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe takeUntil(@NonNull Publisher other) { + public final <@NonNull U> Maybe takeUntil(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new MaybeTakeUntilPublisher<>(this, other)); } @@ -5855,7 +5915,7 @@ public final Maybe timeout(long timeout, @NonNull TimeUnit unit, @NonNull Sch @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe timeout(@NonNull MaybeSource timeoutIndicator) { + public final <@NonNull U> Maybe timeout(@NonNull MaybeSource timeoutIndicator) { Objects.requireNonNull(timeoutIndicator, "timeoutIndicator is null"); return RxJavaPlugins.onAssembly(new MaybeTimeoutMaybe<>(this, timeoutIndicator, null)); } @@ -5880,7 +5940,7 @@ public final Maybe timeout(@NonNull MaybeSource timeoutIndicator) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe timeout(@NonNull MaybeSource timeoutIndicator, @NonNull MaybeSource fallback) { + public final <@NonNull U> Maybe timeout(@NonNull MaybeSource timeoutIndicator, @NonNull MaybeSource fallback) { Objects.requireNonNull(timeoutIndicator, "timeoutIndicator is null"); Objects.requireNonNull(fallback, "fallback is null"); return RxJavaPlugins.onAssembly(new MaybeTimeoutMaybe<>(this, timeoutIndicator, fallback)); @@ -5908,7 +5968,7 @@ public final Maybe timeout(@NonNull MaybeSource timeoutIndicator, @Non @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe timeout(@NonNull Publisher timeoutIndicator) { + public final <@NonNull U> Maybe timeout(@NonNull Publisher timeoutIndicator) { Objects.requireNonNull(timeoutIndicator, "timeoutIndicator is null"); return RxJavaPlugins.onAssembly(new MaybeTimeoutPublisher<>(this, timeoutIndicator, null)); } @@ -5937,7 +5997,7 @@ public final Maybe timeout(@NonNull Publisher timeoutIndicator) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe timeout(@NonNull Publisher timeoutIndicator, @NonNull MaybeSource fallback) { + public final <@NonNull U> Maybe timeout(@NonNull Publisher timeoutIndicator, @NonNull MaybeSource fallback) { Objects.requireNonNull(timeoutIndicator, "timeoutIndicator is null"); Objects.requireNonNull(fallback, "fallback is null"); return RxJavaPlugins.onAssembly(new MaybeTimeoutPublisher<>(this, timeoutIndicator, fallback)); @@ -5994,7 +6054,7 @@ public final Maybe unsubscribeOn(@NonNull Scheduler scheduler) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe zipWith(@NonNull MaybeSource other, @NonNull BiFunction zipper) { + public final <@NonNull U, @NonNull R> Maybe zipWith(@NonNull MaybeSource other, @NonNull BiFunction zipper) { Objects.requireNonNull(other, "other is null"); return zip(this, other, zipper); } @@ -6076,7 +6136,7 @@ public final TestObserver test(boolean dispose) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Maybe<@NonNull T> fromOptional(@NonNull Optional optional) { + public static <@NonNull T> Maybe<@NonNull T> fromOptional(@NonNull Optional optional) { Objects.requireNonNull(optional, "optional is null"); return optional.map(Maybe::just).orElseGet(Maybe::empty); } @@ -6087,7 +6147,7 @@ public final TestObserver test(boolean dispose) { * *

* Note that the operator takes an already instantiated, running or terminated {@code CompletionStage}. - * If the optional is to be created per consumer upon subscription, use {@link #defer(Supplier)} + * If the {@code CompletionStage} is to be created per consumer upon subscription, use {@link #defer(Supplier)} * around {@code fromCompletionStage}: *


      * Maybe.defer(() -> Maybe.fromCompletionStage(createCompletionStage()));
@@ -6110,7 +6170,7 @@ public final TestObserver test(boolean dispose) {
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Maybe<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
+    public static <@NonNull T> Maybe<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
         Objects.requireNonNull(stage, "stage is null");
         return RxJavaPlugins.onAssembly(new MaybeFromCompletionStage<>(stage));
     }
@@ -6246,7 +6306,7 @@ public final CompletionStage toCompletionStage(@Nullable T defaultItem) {
     @SchedulerSupport(SchedulerSupport.NONE)
     @BackpressureSupport(BackpressureKind.FULL)
     @NonNull
-    public final  Flowable flattenStreamAsFlowable(@NonNull Function> mapper) {
+    public final <@NonNull R> Flowable flattenStreamAsFlowable(@NonNull Function> mapper) {
         Objects.requireNonNull(mapper, "mapper is null");
         return RxJavaPlugins.onAssembly(new MaybeFlattenStreamAsFlowable<>(this, mapper));
     }
@@ -6286,7 +6346,7 @@ public final  Flowable flattenStreamAsFlowable(@NonNull Function Observable flattenStreamAsObservable(@NonNull Function> mapper) {
+    public final <@NonNull R> Observable flattenStreamAsObservable(@NonNull Function> mapper) {
         Objects.requireNonNull(mapper, "mapper is null");
         return RxJavaPlugins.onAssembly(new MaybeFlattenStreamAsObservable<>(this, mapper));
     }
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeConverter.java b/src/main/java/io/reactivex/rxjava3/core/MaybeConverter.java
index 221e8a671a9..6ef529de7ef 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeConverter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeConverter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeEmitter.java b/src/main/java/io/reactivex/rxjava3/core/MaybeEmitter.java
index eb7f1f72417..57d7f5a2191 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeEmitter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeEmitter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeObserver.java b/src/main/java/io/reactivex/rxjava3/core/MaybeObserver.java
index b0974fa97ce..f6567dc94e9 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeObserver.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeObserver.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/core/MaybeOnSubscribe.java
index f02756199e4..67994d3d407 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeOnSubscribe.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeOnSubscribe.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,13 +10,14 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
 
 /**
  * A functional interface that has a {@code subscribe()} method that receives
- * an instance of a {@link MaybeEmitter} instance that allows pushing
+ * a {@link MaybeEmitter} instance that allows pushing
  * an event in a cancellation-safe manner.
  *
  * @param  the value type pushed
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeOperator.java b/src/main/java/io/reactivex/rxjava3/core/MaybeOperator.java
index 4ddb18d1f7a..7cea758dd92 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeOperator.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeOperator.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeSource.java b/src/main/java/io/reactivex/rxjava3/core/MaybeSource.java
index da9dbf06585..a15ea2c89d6 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeSource.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeSource.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
diff --git a/src/main/java/io/reactivex/rxjava3/core/MaybeTransformer.java b/src/main/java/io/reactivex/rxjava3/core/MaybeTransformer.java
index 620076d7222..770497fe3c9 100644
--- a/src/main/java/io/reactivex/rxjava3/core/MaybeTransformer.java
+++ b/src/main/java/io/reactivex/rxjava3/core/MaybeTransformer.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/Notification.java b/src/main/java/io/reactivex/rxjava3/core/Notification.java
index 086ffafc8e1..7f5896209f8 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Notification.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Notification.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -26,7 +26,9 @@ public final class Notification {
 
     final Object value;
 
-    /** Not meant to be implemented externally. */
+    /** Not meant to be implemented externally.
+     * @param value the value to carry around in the notification, not {@code null}
+     */
     private Notification(@Nullable Object value) {
         this.value = value;
     }
diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java
index 033d12bdffa..fcf809cdf6b 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Observable.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
 import org.reactivestreams.Publisher;
 
 import io.reactivex.rxjava3.annotations.*;
-import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.disposables.*;
 import io.reactivex.rxjava3.exceptions.*;
 import io.reactivex.rxjava3.functions.*;
 import io.reactivex.rxjava3.internal.functions.*;
-import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier;
 import io.reactivex.rxjava3.internal.jdk8.*;
 import io.reactivex.rxjava3.internal.observers.*;
 import io.reactivex.rxjava3.internal.operators.flowable.*;
@@ -35,6 +34,7 @@
 import io.reactivex.rxjava3.internal.util.*;
 import io.reactivex.rxjava3.observables.*;
 import io.reactivex.rxjava3.observers.*;
+import io.reactivex.rxjava3.operators.ScalarSupplier;
 import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import io.reactivex.rxjava3.schedulers.*;
 
@@ -52,7 +52,7 @@
  * 

* The documentation for this class makes use of marble diagrams. The following legend explains these diagrams: *

- * + * *

* The design of this class was derived from the * Reactive-Streams design and specification @@ -105,10 +105,18 @@ public abstract class Observable<@NonNull T> implements ObservableSource { * Mirrors the one {@link ObservableSource} in an {@link Iterable} of several {@code ObservableSource}s that first either emits an item or sends * a termination notification. *

- * + * + *

+ * When one of the {@code ObservableSource}s signal an item or terminates first, all subscriptions to the other + * {@code ObservableSource}s are disposed. *

*
Scheduler:
*
{@code amb} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If any of the losing {@code ObservableSource}s signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param the common element type @@ -122,7 +130,7 @@ public abstract class Observable<@NonNull T> implements ObservableSource { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable amb(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable amb(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new ObservableAmb<>(null, sources)); } @@ -131,10 +139,18 @@ public static Observable amb(@NonNull Iterable<@NonNull ? extends Observa * Mirrors the one {@link ObservableSource} in an array of several {@code ObservableSource}s that first either emits an item or sends * a termination notification. *

- * + * + *

+ * When one of the {@code ObservableSource}s signal an item or terminates first, all subscriptions to the other + * {@code ObservableSource}s are disposed. *

*
Scheduler:
*
{@code ambArray} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If any of the losing {@code ObservableSource}s signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param the common element type @@ -150,7 +166,7 @@ public static Observable amb(@NonNull Iterable<@NonNull ? extends Observa @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Observable ambArray(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable ambArray(@NonNull ObservableSource... sources) { Objects.requireNonNull(sources, "sources is null"); int len = sources.length; if (len == 0) { @@ -191,7 +207,7 @@ public static int bufferSize() { * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -212,7 +228,7 @@ public static int bufferSize() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable combineLatest( + public static <@NonNull T, @NonNull R> Observable combineLatest( @NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function combiner) { return combineLatest(sources, combiner, bufferSize()); @@ -235,7 +251,7 @@ public static Observable combineLatest( * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -259,7 +275,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T, @NonNull R> Observable combineLatest( @NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); @@ -288,7 +304,7 @@ public static Observable combineLatest( * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatestArray} does not operate by default on a particular {@link Scheduler}.
@@ -309,7 +325,7 @@ public static Observable combineLatest( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable combineLatestArray( + public static <@NonNull T, @NonNull R> Observable combineLatestArray( @NonNull ObservableSource[] sources, @NonNull Function combiner) { return combineLatestArray(sources, combiner, bufferSize()); @@ -332,7 +348,7 @@ public static Observable combineLatestArray( * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatestArray} does not operate by default on a particular {@link Scheduler}.
@@ -356,7 +372,7 @@ public static Observable combineLatestArray( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatestArray( + public static <@NonNull T, @NonNull R> Observable combineLatestArray( @NonNull ObservableSource[] sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); @@ -380,7 +396,7 @@ public static Observable combineLatestArray( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -403,7 +419,7 @@ public static Observable combineLatestArray( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiFunction combiner) { Objects.requireNonNull(source1, "source1 is null"); @@ -421,7 +437,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -447,7 +463,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull Function3 combiner) { @@ -467,7 +483,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -497,7 +513,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull Function4 combiner) { @@ -518,7 +534,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -551,7 +567,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @@ -574,7 +590,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -610,7 +626,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @@ -634,7 +650,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -674,7 +690,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @@ -700,7 +716,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -743,7 +759,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @@ -770,7 +786,7 @@ public static Observable combineLatest( * resulting sequence terminates immediately (normally or with all the errors accumulated till that point). * If that input source is also synchronous, other sources after it will not be subscribed to. *

- * + * *

*
Scheduler:
*
{@code combineLatest} does not operate by default on a particular {@link Scheduler}.
@@ -816,7 +832,7 @@ public static Observable combineLatest( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatest( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Observable combineLatest( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @@ -841,7 +857,7 @@ public static Observable combineLates * the {@code ObservableSource}s each time an item is received from any of the {@code ObservableSource}s, where this * aggregation is defined by a specified function. *

- * + * *

* Note on method signature: since Java doesn't allow creating a generic array with {@code new T[]}, the * implementation of this operator has to create an {@code Object[]} instead. Unfortunately, a @@ -874,7 +890,7 @@ public static Observable combineLates @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable combineLatestArrayDelayError( + public static <@NonNull T, @NonNull R> Observable combineLatestArrayDelayError( @NonNull ObservableSource[] sources, @NonNull Function combiner) { return combineLatestArrayDelayError(sources, combiner, bufferSize()); @@ -898,7 +914,7 @@ public static Observable combineLatestArrayDelayError( * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatestArrayDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -922,7 +938,7 @@ public static Observable combineLatestArrayDelayError( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatestArrayDelayError(@NonNull ObservableSource[] sources, + public static <@NonNull T, @NonNull R> Observable combineLatestArrayDelayError(@NonNull ObservableSource[] sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -953,7 +969,7 @@ public static Observable combineLatestArrayDelayError(@NonNull Observa * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatestDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -974,7 +990,7 @@ public static Observable combineLatestArrayDelayError(@NonNull Observa @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, + public static <@NonNull T, @NonNull R> Observable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function combiner) { return combineLatestDelayError(sources, combiner, bufferSize()); } @@ -997,7 +1013,7 @@ public static Observable combineLatestDelayError(@NonNull Iterable<@No * any items and without any calls to the combiner function. * *

- * + * *

*
Scheduler:
*
{@code combineLatestDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1021,7 +1037,7 @@ public static Observable combineLatestDelayError(@NonNull Iterable<@No @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, + public static <@NonNull T, @NonNull R> Observable combineLatestDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function combiner, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -1036,7 +1052,7 @@ public static Observable combineLatestDelayError(@NonNull Iterable<@No * Concatenates elements of each {@link ObservableSource} provided via an {@link Iterable} sequence into a single sequence * of elements without interleaving them. *

- * + * *

*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1050,7 +1066,7 @@ public static Observable combineLatestDelayError(@NonNull Iterable<@No @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable concat(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable concat(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return fromIterable(sources).concatMapDelayError((Function)Functions.identity(), false, bufferSize()); } @@ -1059,7 +1075,7 @@ public static Observable concat(@NonNull Iterable<@NonNull ? extends Obse * Returns an {@code Observable} that emits the items emitted by each of the {@link ObservableSource}s emitted by the * {@code ObservableSource}, one after the other, without interleaving them. *

- * + * *

*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1075,7 +1091,7 @@ public static Observable concat(@NonNull Iterable<@NonNull ? extends Obse @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concat(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable concat(@NonNull ObservableSource> sources) { return concat(sources, bufferSize()); } @@ -1083,7 +1099,7 @@ public static Observable concat(@NonNull ObservableSource - * + * *
*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1103,7 +1119,7 @@ public static Observable concat(@NonNull ObservableSource Observable concat(@NonNull ObservableSource> sources, int bufferSize) { + public static <@NonNull T> Observable concat(@NonNull ObservableSource> sources, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableConcatMap(sources, Functions.identity(), bufferSize, ErrorMode.IMMEDIATE)); @@ -1113,7 +1129,7 @@ public static Observable concat(@NonNull ObservableSource - * + * *
*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1131,7 +1147,7 @@ public static Observable concat(@NonNull ObservableSource Observable concat(@NonNull ObservableSource source1, ObservableSource source2) { + public static <@NonNull T> Observable concat(@NonNull ObservableSource source1, ObservableSource source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return concatArray(source1, source2); @@ -1141,7 +1157,7 @@ public static Observable concat(@NonNull ObservableSource so * Returns an {@code Observable} that emits the items emitted by three {@link ObservableSource}s, one after the other, without * interleaving them. *

- * + * *

*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1161,7 +1177,7 @@ public static Observable concat(@NonNull ObservableSource so @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable concat( + public static <@NonNull T> Observable concat( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3) { Objects.requireNonNull(source1, "source1 is null"); @@ -1174,7 +1190,7 @@ public static Observable concat( * Returns an {@code Observable} that emits the items emitted by four {@link ObservableSource}s, one after the other, without * interleaving them. *

- * + * *

*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -1196,7 +1212,7 @@ public static Observable concat( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable concat( + public static <@NonNull T> Observable concat( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4) { Objects.requireNonNull(source1, "source1 is null"); @@ -1211,7 +1227,7 @@ public static Observable concat( *

* Note: named this way because of overload conflict with {@code concat(ObservableSource)} *

- * + * *

*
Scheduler:
*
{@code concatArray} does not operate by default on a particular {@link Scheduler}.
@@ -1226,7 +1242,7 @@ public static Observable concat( @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable concatArray(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArray(@NonNull ObservableSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -1241,7 +1257,7 @@ public static Observable concatArray(@NonNull ObservableSource - * + * *
*
Scheduler:
*
{@code concatArrayDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1255,7 +1271,7 @@ public static Observable concatArray(@NonNull ObservableSource Observable concatArrayDelayError(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArrayDelayError(@NonNull ObservableSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return empty(); @@ -1290,7 +1306,7 @@ public static Observable concatArrayDelayError(@NonNull ObservableSource< @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Observable concatArrayEager(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArrayEager(@NonNull ObservableSource... sources) { return concatArrayEager(bufferSize(), bufferSize(), sources); } @@ -1321,7 +1337,7 @@ public static Observable concatArrayEager(@NonNull ObservableSource Observable concatArrayEager(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArrayEager(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), false, maxConcurrency, bufferSize); } @@ -1348,7 +1364,7 @@ public static Observable concatArrayEager(int maxConcurrency, int bufferS @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Observable concatArrayEagerDelayError(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArrayEagerDelayError(@NonNull ObservableSource... sources) { return concatArrayEagerDelayError(bufferSize(), bufferSize(), sources); } @@ -1380,7 +1396,7 @@ public static Observable concatArrayEagerDelayError(@NonNull ObservableSo @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable concatArrayEagerDelayError(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { + public static <@NonNull T> Observable concatArrayEagerDelayError(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -1389,7 +1405,7 @@ public static Observable concatArrayEagerDelayError(int maxConcurrency, i * by subscribing to each {@code ObservableSource}, one after the other, one at a time and delays any errors till * the all inner {@code ObservableSource}s terminate. *

- * + * *

*
Scheduler:
*
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1403,7 +1419,7 @@ public static Observable concatArrayEagerDelayError(int maxConcurrency, i @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable concatDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable concatDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return concatDelayError(fromIterable(sources)); } @@ -1413,7 +1429,7 @@ public static Observable concatDelayError(@NonNull Iterable<@NonNull ? ex * by subscribing to each inner {@code ObservableSource}, one after the other, one at a time and delays any errors till the * all inner and the outer {@code ObservableSource}s terminate. *

- * + * *

*
Scheduler:
*
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1427,7 +1443,7 @@ public static Observable concatDelayError(@NonNull Iterable<@NonNull ? ex @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatDelayError(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable concatDelayError(@NonNull ObservableSource> sources) { return concatDelayError(sources, bufferSize(), true); } @@ -1435,7 +1451,7 @@ public static Observable concatDelayError(@NonNull ObservableSource - * + * *
*
Scheduler:
*
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1454,7 +1470,7 @@ public static Observable concatDelayError(@NonNull ObservableSource Observable concatDelayError(@NonNull ObservableSource> sources, int bufferSize, boolean tillTheEnd) { + public static <@NonNull T> Observable concatDelayError(@NonNull ObservableSource> sources, int bufferSize, boolean tillTheEnd) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize is null"); return RxJavaPlugins.onAssembly(new ObservableConcatMap(sources, Functions.identity(), bufferSize, tillTheEnd ? ErrorMode.END : ErrorMode.BOUNDARY)); @@ -1481,7 +1497,7 @@ public static Observable concatDelayError(@NonNull ObservableSource Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { return concatEager(sources, bufferSize(), bufferSize()); } @@ -1512,7 +1528,7 @@ public static Observable concatEager(@NonNull Iterable<@NonNull ? extends @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).concatMapEagerDelayError((Function)Functions.identity(), false, maxConcurrency, bufferSize); } @@ -1537,7 +1553,7 @@ public static Observable concatEager(@NonNull Iterable<@NonNull ? extends @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEager(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable concatEager(@NonNull ObservableSource> sources) { return concatEager(sources, bufferSize(), bufferSize()); } @@ -1569,7 +1585,7 @@ public static Observable concatEager(@NonNull ObservableSource Observable concatEager(@NonNull ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable concatEager(@NonNull ObservableSource> sources, int maxConcurrency, int bufferSize) { return wrap(sources).concatMapEager((Function)Functions.identity(), maxConcurrency, bufferSize); } @@ -1595,7 +1611,7 @@ public static Observable concatEager(@NonNull ObservableSource Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { return concatEagerDelayError(sources, bufferSize(), bufferSize()); } @@ -1627,7 +1643,7 @@ public static Observable concatEagerDelayError(@NonNull Iterable<@NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -1653,7 +1669,7 @@ public static Observable concatEagerDelayError(@NonNull Iterable<@NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEagerDelayError(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable concatEagerDelayError(@NonNull ObservableSource> sources) { return concatEagerDelayError(sources, bufferSize(), bufferSize()); } @@ -1684,7 +1700,7 @@ public static Observable concatEagerDelayError(@NonNull ObservableSource< @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEagerDelayError(@NonNull ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable concatEagerDelayError(@NonNull ObservableSource> sources, int maxConcurrency, int bufferSize) { return wrap(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -1722,7 +1738,7 @@ public static Observable concatEagerDelayError(@NonNull ObservableSource< * disposes the flow (making {@link ObservableEmitter#isDisposed} return {@code true}), * other observers subscribed to the same returned {@code Observable} are not affected. *

- * + * *

* You should call the {@code ObservableEmitter}'s {@code onNext}, {@code onError} and {@code onComplete} methods in a serialized fashion. The * rest of its methods are thread-safe. @@ -1742,7 +1758,7 @@ public static Observable concatEagerDelayError(@NonNull ObservableSource< @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable create(@NonNull ObservableOnSubscribe source) { + public static <@NonNull T> Observable create(@NonNull ObservableOnSubscribe source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new ObservableCreate<>(source)); } @@ -1752,7 +1768,7 @@ public static Observable create(@NonNull ObservableOnSubscribe source) * that subscribes. That is, for each subscriber, the actual {@code ObservableSource} that subscriber observes is * determined by the factory function. *

- * + * *

* The {@code defer} operator allows you to defer or delay emitting items from an {@code ObservableSource} until such time as an * {@code Observer} subscribes to the {@code ObservableSource}. This allows an {@code Observer} to easily obtain updates or a @@ -1774,7 +1790,7 @@ public static Observable create(@NonNull ObservableOnSubscribe source) @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable defer(@NonNull Supplier> supplier) { + public static <@NonNull T> Observable defer(@NonNull Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new ObservableDefer<>(supplier)); } @@ -1783,7 +1799,7 @@ public static Observable defer(@NonNull Supplier - * + * *

*
Scheduler:
*
{@code empty} does not operate by default on a particular {@link Scheduler}.
@@ -1798,7 +1814,7 @@ public static Observable defer(@NonNull Supplier Observable empty() { + public static <@NonNull T> Observable empty() { return RxJavaPlugins.onAssembly((Observable) ObservableEmpty.INSTANCE); } @@ -1823,7 +1839,7 @@ public static Observable empty() { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable error(@NonNull Supplier supplier) { + public static <@NonNull T> Observable error(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new ObservableError<>(supplier)); } @@ -1849,16 +1865,16 @@ public static Observable error(@NonNull Supplier sup @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable error(@NonNull Throwable throwable) { + public static <@NonNull T> Observable error(@NonNull Throwable throwable) { Objects.requireNonNull(throwable, "throwable is null"); return error(Functions.justSupplier(throwable)); } /** - * Returns an {@code Observable} instance that runs the given {@link Action} for each subscriber and + * Returns an {@code Observable} instance that runs the given {@link Action} for each {@link Observer} and * emits either its exception or simply completes. *

- * + * *

*
Scheduler:
*
{@code fromAction} does not operate by default on a particular {@link Scheduler}.
@@ -1871,7 +1887,7 @@ public static Observable error(@NonNull Throwable throwable) { *
*
* @param the target type - * @param action the {@code Action} to run for each subscriber + * @param action the {@code Action} to run for each {@code Observer} * @return the new {@code Observable} instance * @throws NullPointerException if {@code action} is {@code null} * @since 3.0.0 @@ -1879,7 +1895,7 @@ public static Observable error(@NonNull Throwable throwable) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromAction(@NonNull Action action) { + public static <@NonNull T> Observable fromAction(@NonNull Action action) { Objects.requireNonNull(action, "action is null"); return RxJavaPlugins.onAssembly(new ObservableFromAction<>(action)); } @@ -1887,7 +1903,7 @@ public static Observable fromAction(@NonNull Action action) { /** * Converts an array into an {@link ObservableSource} that emits the items in the array. *

- * + * *

*
Scheduler:
*
{@code fromArray} does not operate by default on a particular {@link Scheduler}.
@@ -1905,7 +1921,7 @@ public static Observable fromAction(@NonNull Action action) { @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable fromArray(@NonNull T... items) { + public static <@NonNull T> Observable fromArray(@NonNull T... items) { Objects.requireNonNull(items, "items is null"); if (items.length == 0) { return empty(); @@ -1920,7 +1936,7 @@ public static Observable fromArray(@NonNull T... items) { * Returns an {@code Observable} that, when an observer subscribes to it, invokes a function you specify and then * emits the value returned from that function. *

- * + * *

* This allows you to defer the execution of the function you specify until an observer subscribes to the * {@code Observable}. That is to say, it makes the function "lazy." @@ -1949,7 +1965,7 @@ public static Observable fromArray(@NonNull T... items) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromCallable(@NonNull Callable callable) { + public static <@NonNull T> Observable fromCallable(@NonNull Callable callable) { Objects.requireNonNull(callable, "callable is null"); return RxJavaPlugins.onAssembly(new ObservableFromCallable<>(callable)); } @@ -1970,7 +1986,7 @@ public static Observable fromCallable(@NonNull Callable call @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromCompletable(@NonNull CompletableSource completableSource) { + public static <@NonNull T> Observable fromCompletable(@NonNull CompletableSource completableSource) { Objects.requireNonNull(completableSource, "completableSource is null"); return RxJavaPlugins.onAssembly(new ObservableFromCompletable<>(completableSource)); } @@ -2004,11 +2020,12 @@ public static Observable fromCompletable(@NonNull CompletableSource compl * @return the new {@code Observable} instance * @throws NullPointerException if {@code future} is {@code null} * @see ReactiveX operators documentation: From + * @see #fromCompletionStage(CompletionStage) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromFuture(@NonNull Future future) { + public static <@NonNull T> Observable fromFuture(@NonNull Future future) { Objects.requireNonNull(future, "future is null"); return RxJavaPlugins.onAssembly(new ObservableFromFuture<>(future, 0L, null)); } @@ -2046,11 +2063,12 @@ public static Observable fromFuture(@NonNull Future future) * @return the new {@code Observable} instance * @throws NullPointerException if {@code future} or {@code unit} is {@code null} * @see ReactiveX operators documentation: From + * @see #fromCompletionStage(CompletionStage) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromFuture(@NonNull Future future, long timeout, @NonNull TimeUnit unit) { + public static <@NonNull T> Observable fromFuture(@NonNull Future future, long timeout, @NonNull TimeUnit unit) { Objects.requireNonNull(future, "future is null"); Objects.requireNonNull(unit, "unit is null"); return RxJavaPlugins.onAssembly(new ObservableFromFuture<>(future, timeout, unit)); @@ -2059,7 +2077,7 @@ public static Observable fromFuture(@NonNull Future future, /** * Converts an {@link Iterable} sequence into an {@code Observable} that emits the items in the sequence. *

- * + * *

*
Scheduler:
*
{@code fromIterable} does not operate by default on a particular {@link Scheduler}.
@@ -2078,7 +2096,7 @@ public static Observable fromFuture(@NonNull Future future, @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromIterable(@NonNull Iterable<@NonNull ? extends T> source) { + public static <@NonNull T> Observable fromIterable(@NonNull Iterable source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new ObservableFromIterable<>(source)); } @@ -2102,7 +2120,7 @@ public static Observable fromIterable(@NonNull Iterable<@NonNull ? extend @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromMaybe(@NonNull MaybeSource maybe) { + public static <@NonNull T> Observable fromMaybe(@NonNull MaybeSource maybe) { Objects.requireNonNull(maybe, "maybe is null"); return RxJavaPlugins.onAssembly(new MaybeToObservable<>(maybe)); } @@ -2139,21 +2157,26 @@ public static Observable fromMaybe(@NonNull MaybeSource maybe) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromPublisher(@NonNull Publisher<@NonNull ? extends T> publisher) { + public static <@NonNull T> Observable fromPublisher(@NonNull Publisher publisher) { Objects.requireNonNull(publisher, "publisher is null"); return RxJavaPlugins.onAssembly(new ObservableFromPublisher<>(publisher)); } /** - * Returns an {@code Observable} instance that runs the given {@link Runnable} for each observer and - * emits either its exception or simply completes. + * Returns an {@code Observable} instance that runs the given {@link Runnable} for each {@link Observer} and + * emits either its unchecked exception or simply completes. *

* + *

+ * If the code to be wrapped needs to throw a checked or more broader {@link Throwable} exception, that + * exception has to be converted to an unchecked exception by the wrapped code itself. Alternatively, + * use the {@link #fromAction(Action)} method which allows the wrapped code to throw any {@code Throwable} + * exception and will signal it to observers as-is. *

*
Scheduler:
*
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
*
Error handling:
- *
If the {@code Runnable} throws an exception, the respective {@link Throwable} is + *
If the {@code Runnable} throws an exception, the respective {@code Throwable} is * delivered to the downstream via {@link Observer#onError(Throwable)}, * except when the downstream has canceled the resulting {@code Observable} source. * In this latter case, the {@code Throwable} is delivered to the global error handler via @@ -2161,15 +2184,16 @@ public static Observable fromPublisher(@NonNull Publisher<@NonNull ? exte *
*
* @param the target type - * @param run the {@code Runnable} to run for each observer + * @param run the {@code Runnable} to run for each {@code Observer} * @return the new {@code Observable} instance * @throws NullPointerException if {@code run} is {@code null} * @since 3.0.0 + * @see #fromAction(Action) */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromRunnable(@NonNull Runnable run) { + public static <@NonNull T> Observable fromRunnable(@NonNull Runnable run) { Objects.requireNonNull(run, "run is null"); return RxJavaPlugins.onAssembly(new ObservableFromRunnable<>(run)); } @@ -2192,7 +2216,7 @@ public static Observable fromRunnable(@NonNull Runnable run) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromSingle(@NonNull SingleSource source) { + public static <@NonNull T> Observable fromSingle(@NonNull SingleSource source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new SingleToObservable<>(source)); } @@ -2201,7 +2225,7 @@ public static Observable fromSingle(@NonNull SingleSource source) { * Returns an {@code Observable} that, when an observer subscribes to it, invokes a supplier function you specify and then * emits the value returned from that function. *

- * + * *

* This allows you to defer the execution of the function you specify until an observer subscribes to the * {@code Observable}. That is to say, it makes the function "lazy." @@ -2230,7 +2254,7 @@ public static Observable fromSingle(@NonNull SingleSource source) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable fromSupplier(@NonNull Supplier supplier) { + public static <@NonNull T> Observable fromSupplier(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new ObservableFromSupplier<>(supplier)); } @@ -2238,7 +2262,7 @@ public static Observable fromSupplier(@NonNull Supplier supp /** * Returns a cold, synchronous and stateless generator of values. *

- * + * *

* Note that the {@link Emitter#onNext}, {@link Emitter#onError} and * {@link Emitter#onComplete} methods provided to the function via the {@link Emitter} instance should be called synchronously, @@ -2260,7 +2284,7 @@ public static Observable fromSupplier(@NonNull Supplier supp @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable generate(@NonNull Consumer> generator) { + public static <@NonNull T> Observable generate(@NonNull Consumer> generator) { Objects.requireNonNull(generator, "generator is null"); return generate(Functions.nullSupplier(), ObservableInternalHelper.simpleGenerator(generator), Functions.emptyConsumer()); @@ -2269,7 +2293,7 @@ public static Observable generate(@NonNull Consumer> generator /** * Returns a cold, synchronous and stateful generator of values. *

- * + * *

* Note that the {@link Emitter#onNext}, {@link Emitter#onError} and * {@link Emitter#onComplete} methods provided to the function via the {@link Emitter} instance should be called synchronously, @@ -2293,7 +2317,7 @@ public static Observable generate(@NonNull Consumer> generator @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator) { + public static <@NonNull T, @NonNull S> Observable generate(@NonNull Supplier initialState, @NonNull BiConsumer> generator) { Objects.requireNonNull(generator, "generator is null"); return generate(initialState, ObservableInternalHelper.simpleBiGenerator(generator), Functions.emptyConsumer()); } @@ -2301,7 +2325,7 @@ public static Observable generate(@NonNull Supplier initialState, @ /** * Returns a cold, synchronous and stateful generator of values. *

- * + * *

* Note that the {@link Emitter#onNext}, {@link Emitter#onError} and * {@link Emitter#onComplete} methods provided to the function via the {@link Emitter} instance should be called synchronously, @@ -2327,7 +2351,7 @@ public static Observable generate(@NonNull Supplier initialState, @ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable generate( + public static <@NonNull T, @NonNull S> Observable generate( @NonNull Supplier initialState, @NonNull BiConsumer> generator, @NonNull Consumer disposeState) { @@ -2338,7 +2362,7 @@ public static Observable generate( /** * Returns a cold, synchronous and stateful generator of values. *

- * + * *

* Note that the {@link Emitter#onNext}, {@link Emitter#onError} and * {@link Emitter#onComplete} methods provided to the function via the {@link Emitter} instance should be called synchronously, @@ -2363,14 +2387,14 @@ public static Observable generate( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator) { + public static <@NonNull T, @NonNull S> Observable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator) { return generate(initialState, generator, Functions.emptyConsumer()); } /** * Returns a cold, synchronous and stateful generator of values. *

- * + * *

* Note that the {@link Emitter#onNext}, {@link Emitter#onError} and * {@link Emitter#onComplete} methods provided to the function via the {@link Emitter} instance should be called synchronously, @@ -2397,7 +2421,7 @@ public static Observable generate(@NonNull Supplier initialState, @ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator, + public static <@NonNull T, @NonNull S> Observable generate(@NonNull Supplier initialState, @NonNull BiFunction, S> generator, @NonNull Consumer disposeState) { Objects.requireNonNull(initialState, "initialState is null"); Objects.requireNonNull(generator, "generator is null"); @@ -2409,7 +2433,7 @@ public static Observable generate(@NonNull Supplier initialState, @ * Returns an {@code Observable} that emits a {@code 0L} after the {@code initialDelay} and ever increasing numbers * after each {@code period} of time thereafter. *

- * + * *

*
Scheduler:
*
{@code interval} operates by default on the {@code computation} {@link Scheduler}.
@@ -2437,7 +2461,7 @@ public static Observable interval(long initialDelay, long period, @NonNull * Returns an {@code Observable} that emits a {@code 0L} after the {@code initialDelay} and ever increasing numbers * after each {@code period} of time thereafter, on a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -2469,7 +2493,7 @@ public static Observable interval(long initialDelay, long period, @NonNull /** * Returns an {@code Observable} that emits a sequential number every specified interval of time. *

- * + * *

*
Scheduler:
*
{@code interval} operates by default on the {@code computation} {@link Scheduler}.
@@ -2494,7 +2518,7 @@ public static Observable interval(long period, @NonNull TimeUnit unit) { * Returns an {@code Observable} that emits a sequential number every specified interval of time, on a * specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -2522,7 +2546,7 @@ public static Observable interval(long period, @NonNull TimeUnit unit, @No *

* The sequence completes immediately after the last value (start + count - 1) has been reached. *

- * + * *

*
Scheduler:
*
{@code intervalRange} by default operates on the {@link Schedulers#computation() computation} {@link Scheduler}.
@@ -2537,10 +2561,11 @@ public static Observable interval(long period, @NonNull TimeUnit unit, @No * @throws IllegalArgumentException * if {@code count} is negative, or if {@code start} + {@code count} − 1 exceeds * {@link Long#MAX_VALUE} + * @see #range(int, int) */ @CheckReturnValue - @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) public static Observable intervalRange(long start, long count, long initialDelay, long period, @NonNull TimeUnit unit) { return intervalRange(start, count, initialDelay, period, unit, Schedulers.computation()); } @@ -2550,7 +2575,7 @@ public static Observable intervalRange(long start, long count, long initia *

* The sequence completes immediately after the last value (start + count - 1) has been reached. *

- * *

+ * *
*
Scheduler:
*
you provide the {@link Scheduler}.
*
@@ -2620,7 +2645,7 @@ public static Observable intervalRange(long start, long count, long initia @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item) { + public static <@NonNull T> Observable just(@NonNull T item) { Objects.requireNonNull(item, "item is null"); return RxJavaPlugins.onAssembly(new ObservableJust<>(item)); } @@ -2628,7 +2653,7 @@ public static Observable just(@NonNull T item) { /** * Converts two items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2647,7 +2672,7 @@ public static Observable just(@NonNull T item) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); @@ -2657,7 +2682,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2) { /** * Converts three items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2678,7 +2703,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2689,7 +2714,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts four items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2712,7 +2737,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2724,7 +2749,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts five items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2750,7 +2775,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2763,7 +2788,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts six items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2791,7 +2816,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2805,7 +2830,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts seven items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2836,7 +2861,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2851,7 +2876,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts eight items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2884,7 +2909,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2900,7 +2925,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts nine items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2935,7 +2960,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8, @NonNull T item9) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8, @NonNull T item9) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -2952,7 +2977,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul /** * Converts ten items into an {@code Observable} that emits those items. *

- * + * *

*
Scheduler:
*
{@code just} does not operate by default on a particular {@link Scheduler}.
@@ -2990,7 +3015,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8, @NonNull T item9, @NonNull T item10) { + public static <@NonNull T> Observable just(@NonNull T item1, @NonNull T item2, @NonNull T item3, @NonNull T item4, @NonNull T item5, @NonNull T item6, @NonNull T item7, @NonNull T item8, @NonNull T item9, @NonNull T item10) { Objects.requireNonNull(item1, "item1 is null"); Objects.requireNonNull(item2, "item2 is null"); Objects.requireNonNull(item3, "item3 is null"); @@ -3009,7 +3034,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul * Flattens an {@link Iterable} of {@link ObservableSource}s into one {@code Observable}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code ObservableSource}s. *

- * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3049,7 +3074,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).flatMap((Function)Functions.identity(), false, maxConcurrency, bufferSize); } @@ -3057,7 +3082,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser * Flattens an array of {@link ObservableSource}s into one {@code Observable}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code ObservableSource}s. *

- * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3098,14 +3123,14 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable mergeArray(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { + public static <@NonNull T> Observable mergeArray(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), false, maxConcurrency, bufferSize); } /** * Flattens an {@link Iterable} of {@link ObservableSource}s into one {@code Observable}, without any transformation. *

- * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3139,7 +3164,7 @@ public static Observable mergeArray(int maxConcurrency, int bufferSize, @ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { return fromIterable(sources).flatMap((Function)Functions.identity()); } @@ -3147,7 +3172,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser * Flattens an {@link Iterable} of {@link ObservableSource}s into one {@code Observable}, without any transformation, while limiting the * number of concurrent subscriptions to these {@code ObservableSource}s. *

- * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3185,7 +3210,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency) { + public static <@NonNull T> Observable merge(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency) { return fromIterable(sources).flatMap((Function)Functions.identity(), maxConcurrency); } @@ -3193,7 +3218,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser * Flattens an {@link ObservableSource} that emits {@code ObservableSource}s into a single {@code Observable} that emits the items emitted by * those {@code ObservableSource}s, without any transformation. *

- * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3227,7 +3252,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "unchecked", "rawtypes" }) @NonNull - public static Observable merge(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable merge(@NonNull ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap(sources, Functions.identity(), false, Integer.MAX_VALUE, bufferSize())); } @@ -3237,7 +3262,7 @@ public static Observable merge(@NonNull ObservableSource - * + * *

* You can combine the items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3276,7 +3301,7 @@ public static Observable merge(@NonNull ObservableSource Observable merge(@NonNull ObservableSource> sources, int maxConcurrency) { + public static <@NonNull T> Observable merge(@NonNull ObservableSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new ObservableFlatMap(sources, Functions.identity(), false, maxConcurrency, bufferSize())); @@ -3285,7 +3310,7 @@ public static Observable merge(@NonNull ObservableSource - * + * *

* You can combine items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3321,7 +3346,7 @@ public static Observable merge(@NonNull ObservableSource Observable merge(@NonNull ObservableSource source1, @NonNull ObservableSource source2) { + public static <@NonNull T> Observable merge(@NonNull ObservableSource source1, @NonNull ObservableSource source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return fromArray(source1, source2).flatMap((Function)Functions.identity(), false, 2); @@ -3330,7 +3355,7 @@ public static Observable merge(@NonNull ObservableSource sou /** * Flattens three {@link ObservableSource}s into a single {@code Observable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3368,7 +3393,7 @@ public static Observable merge(@NonNull ObservableSource sou @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable merge( + public static <@NonNull T> Observable merge( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3) { Objects.requireNonNull(source1, "source1 is null"); @@ -3380,7 +3405,7 @@ public static Observable merge( /** * Flattens four {@link ObservableSource}s into a single {@code Observable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3420,7 +3445,7 @@ public static Observable merge( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable merge( + public static <@NonNull T> Observable merge( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4) { Objects.requireNonNull(source1, "source1 is null"); @@ -3433,7 +3458,7 @@ public static Observable merge( /** * Flattens an array of {@link ObservableSource}s into one {@code Observable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code merge} method. @@ -3468,7 +3493,7 @@ public static Observable merge( @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable mergeArray(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable mergeArray(@NonNull ObservableSource... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), sources.length); } @@ -3481,7 +3506,7 @@ public static Observable mergeArray(@NonNull ObservableSource - * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3501,7 +3526,7 @@ public static Observable mergeArray(@NonNull ObservableSource Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + public static <@NonNull T> Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { return fromIterable(sources).flatMap((Function)Functions.identity(), true); } @@ -3514,7 +3539,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext * error via {@link Observer#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code ObservableSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3539,7 +3564,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + public static <@NonNull T> Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { return fromIterable(sources).flatMap((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -3552,7 +3577,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext * error via {@link Observer#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code ObservableSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3578,7 +3603,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable mergeArrayDelayError(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { + public static <@NonNull T> Observable mergeArrayDelayError(int maxConcurrency, int bufferSize, @NonNull ObservableSource... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), true, maxConcurrency, bufferSize); } @@ -3591,7 +3616,7 @@ public static Observable mergeArrayDelayError(int maxConcurrency, int buf * error via {@link Observer#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code ObservableSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3614,7 +3639,7 @@ public static Observable mergeArrayDelayError(int maxConcurrency, int buf @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency) { + public static <@NonNull T> Observable mergeDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency) { return fromIterable(sources).flatMap((Function)Functions.identity(), true, maxConcurrency); } @@ -3627,7 +3652,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext * error via {@link Observer#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code ObservableSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3647,7 +3672,7 @@ public static Observable mergeDelayError(@NonNull Iterable<@NonNull ? ext @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "unchecked", "rawtypes" }) @NonNull - public static Observable mergeDelayError(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable mergeDelayError(@NonNull ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap(sources, Functions.identity(), true, Integer.MAX_VALUE, bufferSize())); } @@ -3662,7 +3687,7 @@ public static Observable mergeDelayError(@NonNull ObservableSource - * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3686,7 +3711,7 @@ public static Observable mergeDelayError(@NonNull ObservableSource Observable mergeDelayError(@NonNull ObservableSource> sources, int maxConcurrency) { + public static <@NonNull T> Observable mergeDelayError(@NonNull ObservableSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); return RxJavaPlugins.onAssembly(new ObservableFlatMap(sources, Functions.identity(), true, maxConcurrency, bufferSize())); @@ -3701,7 +3726,7 @@ public static Observable mergeDelayError(@NonNull ObservableSource - * + * *

* Even if both merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3723,7 +3748,7 @@ public static Observable mergeDelayError(@NonNull ObservableSource Observable mergeDelayError( + public static <@NonNull T> Observable mergeDelayError( @NonNull ObservableSource source1, @NonNull ObservableSource source2) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); @@ -3740,7 +3765,7 @@ public static Observable mergeDelayError( * from propagating that error notification until all of the merged {@code ObservableSource}s have finished emitting * items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3764,7 +3789,7 @@ public static Observable mergeDelayError( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable mergeDelayError( + public static <@NonNull T> Observable mergeDelayError( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3) { Objects.requireNonNull(source1, "source1 is null"); @@ -3783,7 +3808,7 @@ public static Observable mergeDelayError( * will refrain from propagating that error notification until all of the merged {@code ObservableSource}s have finished * emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3809,7 +3834,7 @@ public static Observable mergeDelayError( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable mergeDelayError( + public static <@NonNull T> Observable mergeDelayError( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4) { Objects.requireNonNull(source1, "source1 is null"); @@ -3828,7 +3853,7 @@ public static Observable mergeDelayError( * error via {@link Observer#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code ObservableSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code ObservableSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its {@code Observer}s once. @@ -3849,14 +3874,14 @@ public static Observable mergeDelayError( @SchedulerSupport(SchedulerSupport.NONE) @NonNull @SafeVarargs - public static Observable mergeArrayDelayError(@NonNull ObservableSource... sources) { + public static <@NonNull T> Observable mergeArrayDelayError(@NonNull ObservableSource... sources) { return fromArray(sources).flatMap((Function)Functions.identity(), true, sources.length); } /** * Returns an {@code Observable} that never sends any items or notifications to an {@link Observer}. *

- * + * *

* The returned {@code Observable} is useful primarily for testing purposes. *

@@ -3873,14 +3898,14 @@ public static Observable mergeArrayDelayError(@NonNull ObservableSource Observable never() { + public static <@NonNull T> Observable never() { return RxJavaPlugins.onAssembly((Observable) ObservableNever.INSTANCE); } /** * Returns an {@code Observable} that emits a sequence of {@link Integer}s within a specified range. *

- * + * *

*
Scheduler:
*
{@code range} does not operate by default on a particular {@link Scheduler}.
@@ -3895,6 +3920,8 @@ public static Observable never() { * if {@code count} is negative, or if {@code start} + {@code count} − 1 exceeds * {@link Integer#MAX_VALUE} * @see ReactiveX operators documentation: Range + * @see #rangeLong(long, long) + * @see #intervalRange(long, long, long, long, TimeUnit) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -3933,6 +3960,7 @@ public static Observable range(int start, int count) { * if {@code count} is negative, or if {@code start} + {@code count} − 1 exceeds * {@link Long#MAX_VALUE} * @see ReactiveX operators documentation: Range + * @see #intervalRange(long, long, long, long, TimeUnit) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -3962,7 +3990,7 @@ public static Observable rangeLong(long start, long count) { * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link ObservableSource} sequences are the * same by comparing the items emitted by each {@code ObservableSource} pairwise. *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -3981,7 +4009,7 @@ public static Observable rangeLong(long start, long count) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull ObservableSource source1, @NonNull ObservableSource source2) { + public static <@NonNull T> Single sequenceEqual(@NonNull ObservableSource source1, @NonNull ObservableSource source2) { return sequenceEqual(source1, source2, ObjectHelper.equalsPredicate(), bufferSize()); } @@ -3990,7 +4018,7 @@ public static Single sequenceEqual(@NonNull ObservableSource - * + * *
*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -4011,7 +4039,7 @@ public static Single sequenceEqual(@NonNull ObservableSource Single sequenceEqual( + public static <@NonNull T> Single sequenceEqual( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiPredicate isEqual) { return sequenceEqual(source1, source2, isEqual, bufferSize()); @@ -4022,7 +4050,7 @@ public static Single sequenceEqual( * same by comparing the items emitted by each {@code ObservableSource} pairwise based on the results of a specified * equality function. *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -4046,7 +4074,7 @@ public static Single sequenceEqual( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual( + public static <@NonNull T> Single sequenceEqual( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiPredicate isEqual, int bufferSize) { Objects.requireNonNull(source1, "source1 is null"); @@ -4060,7 +4088,7 @@ public static Single sequenceEqual( * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link ObservableSource} sequences are the * same by comparing the items emitted by each {@code ObservableSource} pairwise. *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -4082,7 +4110,7 @@ public static Single sequenceEqual( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single sequenceEqual(@NonNull ObservableSource source1, @NonNull ObservableSource source2, + public static <@NonNull T> Single sequenceEqual(@NonNull ObservableSource source1, @NonNull ObservableSource source2, int bufferSize) { return sequenceEqual(source1, source2, ObjectHelper.equalsPredicate(), bufferSize); } @@ -4091,7 +4119,7 @@ public static Single sequenceEqual(@NonNull ObservableSource - * + * *

* {@code switchOnNext} subscribes to an {@code ObservableSource} that emits {@code ObservableSource}s. Each time it observes one of * these emitted {@code ObservableSource}s, the {@code ObservableSource} returned by {@code switchOnNext} begins emitting the items @@ -4119,7 +4147,7 @@ public static Single sequenceEqual(@NonNull ObservableSource Observable switchOnNext(@NonNull ObservableSource> sources, int bufferSize) { + public static <@NonNull T> Observable switchOnNext(@NonNull ObservableSource> sources, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableSwitchMap(sources, Functions.identity(), bufferSize, false)); @@ -4129,7 +4157,7 @@ public static Observable switchOnNext(@NonNull ObservableSource - * + * *

* {@code switchOnNext} subscribes to an {@code ObservableSource} that emits {@code ObservableSource}s. Each time it observes one of * these emitted {@code ObservableSource}s, the {@code ObservableSource} returned by {@code switchOnNext} begins emitting the items @@ -4153,7 +4181,7 @@ public static Observable switchOnNext(@NonNull ObservableSource Observable switchOnNext(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable switchOnNext(@NonNull ObservableSource> sources) { return switchOnNext(sources, bufferSize()); } @@ -4161,7 +4189,7 @@ public static Observable switchOnNext(@NonNull ObservableSource - * + * *

* {@code switchOnNext} subscribes to an {@code ObservableSource} that emits {@code ObservableSource}s. Each time it observes one of * these emitted {@code ObservableSource}s, the {@code ObservableSource} returned by {@code switchOnNext} begins emitting the items @@ -4187,7 +4215,7 @@ public static Observable switchOnNext(@NonNull ObservableSource Observable switchOnNextDelayError(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable switchOnNextDelayError(@NonNull ObservableSource> sources) { return switchOnNextDelayError(sources, bufferSize()); } @@ -4195,7 +4223,7 @@ public static Observable switchOnNextDelayError(@NonNull ObservableSource * Converts an {@link ObservableSource} that emits {@code ObservableSource}s into an {@code Observable} that emits the items emitted by the * most recently emitted of those {@code ObservableSource}s and delays any exception until all {@code ObservableSource}s terminate. *

- * + * *

* {@code switchOnNext} subscribes to an {@code ObservableSource} that emits {@code ObservableSource}s. Each time it observes one of * these emitted {@code ObservableSource}s, the {@code ObservableSource} returned by {@code switchOnNext} begins emitting the items @@ -4225,7 +4253,7 @@ public static Observable switchOnNextDelayError(@NonNull ObservableSource @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable switchOnNextDelayError(@NonNull ObservableSource> sources, int bufferSize) { + public static <@NonNull T> Observable switchOnNextDelayError(@NonNull ObservableSource> sources, int bufferSize) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableSwitchMap(sources, Functions.identity(), bufferSize, true)); @@ -4234,7 +4262,7 @@ public static Observable switchOnNextDelayError(@NonNull ObservableSource /** * Returns an {@code Observable} that emits {@code 0L} after a specified delay, and then completes. *

- * + * *

*
Scheduler:
*
{@code timer} operates by default on the {@code computation} {@link Scheduler}.
@@ -4259,7 +4287,7 @@ public static Observable timer(long delay, @NonNull TimeUnit unit) { * Returns an {@code Observable} that emits {@code 0L} after a specified delay, on a specified {@link Scheduler}, and then * completes. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -4305,7 +4333,7 @@ public static Observable timer(long delay, @NonNull TimeUnit unit, @NonNul @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable unsafeCreate(@NonNull ObservableSource onSubscribe) { + public static <@NonNull T> Observable unsafeCreate(@NonNull ObservableSource onSubscribe) { Objects.requireNonNull(onSubscribe, "onSubscribe is null"); if (onSubscribe instanceof Observable) { throw new IllegalArgumentException("unsafeCreate(Observable) should be upgraded"); @@ -4318,7 +4346,7 @@ public static Observable unsafeCreate(@NonNull ObservableSource onSubs * that resource and calls the provided {@code resourceDisposer} function if this inner source terminates or the * downstream disposes the flow. *

- * + * *

*
Scheduler:
*
{@code using} does not operate by default on a particular {@link Scheduler}.
@@ -4339,7 +4367,7 @@ public static Observable unsafeCreate(@NonNull ObservableSource onSubs @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable using( + public static <@NonNull T, @NonNull D> Observable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup) { @@ -4351,7 +4379,7 @@ public static Observable using( * that resource and calls the provided {@code disposer} function if this inner source terminates or the * downstream disposes the flow; doing it before these end-states have been reached if {@code eager == true}, after otherwise. *

- * + * *

*
Scheduler:
*
{@code using} does not operate by default on a particular {@link Scheduler}.
@@ -4378,7 +4406,7 @@ public static Observable using( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable using( + public static <@NonNull T, @NonNull D> Observable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup, boolean eager) { @@ -4404,7 +4432,7 @@ public static Observable using( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable wrap(@NonNull ObservableSource source) { + public static <@NonNull T> Observable wrap(@NonNull ObservableSource source) { Objects.requireNonNull(source, "source is null"); if (source instanceof Observable) { return RxJavaPlugins.onAssembly((Observable)source); @@ -4441,7 +4469,7 @@ public static Observable wrap(@NonNull ObservableSource source) { * {@code Function} passed to the method would trigger a {@link ClassCastException}. * *

- * + * *

*
Scheduler:
*
{@code zip} does not operate by default on a particular {@link Scheduler}.
@@ -4461,7 +4489,7 @@ public static Observable wrap(@NonNull ObservableSource source) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function zipper) { + public static <@NonNull T, @NonNull R> Observable zip(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function zipper) { Objects.requireNonNull(zipper, "zipper is null"); Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new ObservableZip<>(null, sources, zipper, bufferSize(), false)); @@ -4496,7 +4524,7 @@ public static Observable zip(@NonNull Iterable<@NonNull ? extends Obse * {@code Function} passed to the method would trigger a {@link ClassCastException}. * *

- * + * *

*
Scheduler:
*
{@code zip} does not operate by default on a particular {@link Scheduler}.
@@ -4522,7 +4550,7 @@ public static Observable zip(@NonNull Iterable<@NonNull ? extends Obse @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, + public static <@NonNull T, @NonNull R> Observable zip(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, @NonNull Function zipper, boolean delayError, int bufferSize) { Objects.requireNonNull(zipper, "zipper is null"); @@ -4535,7 +4563,7 @@ public static Observable zip(@NonNull Iterable<@NonNull ? extends Obse * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -4579,7 +4607,7 @@ public static Observable zip(@NonNull Iterable<@NonNull ? extends Obse @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiFunction zipper) { Objects.requireNonNull(source1, "source1 is null"); @@ -4592,7 +4620,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -4637,7 +4665,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiFunction zipper, boolean delayError) { Objects.requireNonNull(source1, "source1 is null"); @@ -4650,7 +4678,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * two items emitted, in sequence, by two other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1} and the first item @@ -4697,7 +4725,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull BiFunction zipper, boolean delayError, int bufferSize) { Objects.requireNonNull(source1, "source1 is null"); @@ -4710,7 +4738,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * three items emitted, in sequence, by three other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -4758,7 +4786,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull Function3 zipper) { @@ -4773,7 +4801,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * four items emitted, in sequence, by four other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -4825,7 +4853,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull Function4 zipper) { @@ -4841,7 +4869,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * five items emitted, in sequence, by five other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by {@code o1}, the first item @@ -4896,7 +4924,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull Function5 zipper) { @@ -4913,7 +4941,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * six items emitted, in sequence, by six other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by each source {@code ObservableSource}, the @@ -4970,7 +4998,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @NonNull Function6 zipper) { @@ -4988,7 +5016,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * seven items emitted, in sequence, by seven other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by each source {@code ObservableSource}, the @@ -5049,7 +5077,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @NonNull ObservableSource source7, @@ -5069,7 +5097,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * eight items emitted, in sequence, by eight other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by each source {@code ObservableSource}, the @@ -5133,7 +5161,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @NonNull ObservableSource source7, @NonNull ObservableSource source8, @@ -5154,7 +5182,7 @@ public static Observable zip( * Returns an {@code Observable} that emits the results of a specified combiner function applied to combinations of * nine items emitted, in sequence, by nine other {@link ObservableSource}s. *

- * + * *

* {@code zip} applies this function in strict sequence, so the first item emitted by the resulting {@code Observable} * will be the result of the function applied to the first item emitted by each source {@code ObservableSource}, the @@ -5221,7 +5249,7 @@ public static Observable zip( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Observable zip( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull ObservableSource source5, @NonNull ObservableSource source6, @NonNull ObservableSource source7, @NonNull ObservableSource source8, @NonNull ObservableSource source9, @@ -5269,7 +5297,7 @@ public static Observable zip( * {@code Function} passed to the method would trigger a {@link ClassCastException}. * *

- * + * *

*
Scheduler:
*
{@code zipArray} does not operate by default on a particular {@link Scheduler}.
@@ -5295,7 +5323,7 @@ public static Observable zip( @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Observable zipArray( + public static <@NonNull T, @NonNull R> Observable zipArray( @NonNull Function zipper, boolean delayError, int bufferSize, @NonNull ObservableSource... sources) { @@ -5340,10 +5368,19 @@ public final Single all(@NonNull Predicate predicate) { * Mirrors the current {@code Observable} or the other {@link ObservableSource} provided of which the first either emits an item or sends a termination * notification. *

- * + * + *

+ * When the current {@code Observable} signals an item or terminates first, the subscription to the other + * {@code ObservableSource} is disposed. If the other {@code ObservableSource} signals an item or terminates first, + * the subscription to the current {@code Observable} is disposed. *

*
Scheduler:
*
{@code ambWith} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
+ * If the losing {@code ObservableSource} signals an error, the error is routed to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
*
* * @param other @@ -5366,7 +5403,7 @@ public final Observable ambWith(@NonNull ObservableSource other) * specified condition, otherwise {@code false}. Note: this always emits {@code false} if the * current {@code Observable} is empty. *

- * + * *

* In Rx.Net this is the {@code any} {@link Observer} but we renamed it in RxJava to better match Java naming * idioms. @@ -5397,6 +5434,10 @@ public final Single any(@NonNull Predicate predicate) { *

*
Scheduler:
*
{@code blockingFirst} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the source signals an error, the operator wraps a checked {@link Exception} + * into {@link RuntimeException} and throws that. Otherwise, {@code RuntimeException}s and + * {@link Error}s are rethrown as they are.
*
* * @return the first item emitted by the current {@code Observable} @@ -5425,6 +5466,10 @@ public final T blockingFirst() { *
*
Scheduler:
*
{@code blockingFirst} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the source signals an error, the operator wraps a checked {@link Exception} + * into {@link RuntimeException} and throws that. Otherwise, {@code RuntimeException}s and + * {@link Error}s are rethrown as they are.
*
* * @param defaultItem @@ -5450,7 +5495,7 @@ public final T blockingFirst(@NonNull T defaultItem) { * {@link Consumer} with each upstream item on the current thread until the * upstream terminates. *

- * + * *

* Note: the method will only return if the upstream terminates or the current * thread is interrupted. @@ -5477,7 +5522,6 @@ public final T blockingFirst(@NonNull T defaultItem) { * @see #blockingForEach(Consumer, int) */ @SchedulerSupport(SchedulerSupport.NONE) - @NonNull public final void blockingForEach(@NonNull Consumer onNext) { blockingForEach(onNext, bufferSize()); } @@ -5487,7 +5531,7 @@ public final void blockingForEach(@NonNull Consumer onNext) { * {@link Consumer} with each upstream item on the current thread until the * upstream terminates. *

- * + * *

* Note: the method will only return if the upstream terminates or the current * thread is interrupted. @@ -5517,7 +5561,6 @@ public final void blockingForEach(@NonNull Consumer onNext) { * @see #subscribe(Consumer) */ @SchedulerSupport(SchedulerSupport.NONE) - @NonNull public final void blockingForEach(@NonNull Consumer onNext, int capacityHint) { Objects.requireNonNull(onNext, "onNext is null"); Iterator it = blockingIterable(capacityHint).iterator(); @@ -5537,7 +5580,7 @@ public final void blockingForEach(@NonNull Consumer onNext, int capac * subscribes to the current {@code Observable} and blocks * until the current {@code Observable} emits items or terminates. *

- * + * *

*
Scheduler:
*
{@code blockingIterable} does not operate by default on a particular {@link Scheduler}.
@@ -5558,7 +5601,7 @@ public final Iterable blockingIterable() { * subscribes to the current {@code Observable} and blocks * until the current {@code Observable} emits items or terminates. *

- * + * *

*
Scheduler:
*
{@code blockingIterable} does not operate by default on a particular {@link Scheduler}.
@@ -5581,7 +5624,7 @@ public final Iterable blockingIterable(int capacityHint) { * Returns the last item emitted by the current {@code Observable}, or throws * {@link NoSuchElementException} if the current {@code Observable} emits no items. *

- * + * *

*
Scheduler:
*
{@code blockingLast} does not operate by default on a particular {@link Scheduler}.
@@ -5613,7 +5656,7 @@ public final T blockingLast() { * Returns the last item emitted by the current {@code Observable}, or a default value if it emits no * items. *

- * + * *

*
Scheduler:
*
{@code blockingLast} does not operate by default on a particular {@link Scheduler}.
@@ -5671,7 +5714,7 @@ public final Iterable blockingLatest() { * Returns an {@link Iterable} that always returns the item most recently emitted by the current * {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code blockingMostRecent} does not operate by default on a particular {@link Scheduler}.
@@ -5696,7 +5739,7 @@ public final Iterable blockingMostRecent(@NonNull T initialItem) { * Returns an {@link Iterable} that blocks until the current {@code Observable} emits another item, then * returns that item. *

- * + * *

*
Scheduler:
*
{@code blockingNext} does not operate by default on a particular {@link Scheduler}.
@@ -5716,7 +5759,7 @@ public final Iterable blockingNext() { * If the current {@code Observable} completes after emitting a single item, return that item, otherwise * throw a {@link NoSuchElementException}. *

- * + * *

*
Scheduler:
*
{@code blockingSingle} does not operate by default on a particular {@link Scheduler}.
@@ -5745,7 +5788,7 @@ public final T blockingSingle() { * more than one item, throw an {@link IllegalArgumentException}; if it emits no items, return a default * value. *

- * + * *

*
Scheduler:
*
{@code blockingSingle} does not operate by default on a particular {@link Scheduler}.
@@ -5923,7 +5966,7 @@ public final void blockingSubscribe(@NonNull Observer observer) { * from the current {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification * the event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -5949,7 +5992,7 @@ public final void blockingSubscribe(@NonNull Observer observer) { * from the current {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification * the event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -5979,7 +6022,7 @@ public final void blockingSubscribe(@NonNull Observer observer) { * from the current {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification * the event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -6003,7 +6046,7 @@ public final void blockingSubscribe(@NonNull Observer observer) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Observable buffer(int count, int skip, @NonNull Supplier bufferSupplier) { + public final <@NonNull U extends Collection> Observable buffer(int count, int skip, @NonNull Supplier bufferSupplier) { ObjectHelper.verifyPositive(count, "count"); ObjectHelper.verifyPositive(skip, "skip"); Objects.requireNonNull(bufferSupplier, "bufferSupplier is null"); @@ -6017,7 +6060,7 @@ public final > Observable buffer(int count, i * from the current {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification * the event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -6049,7 +6092,7 @@ public final > Observable buffer(int count, i * from the current {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification * the event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} operates by default on the {@code computation} {@link Scheduler}.
@@ -6081,7 +6124,7 @@ public final > Observable buffer(int count, i * {@code Observable} issues an {@code onError} notification the event is passed on immediately without first emitting the * buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -6115,7 +6158,7 @@ public final > Observable buffer(int count, i * {@code Observable} issues an {@code onError} notification the event is passed on immediately without first emitting the * buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -6155,7 +6198,7 @@ public final > Observable buffer(int count, i * {@code Observable} issues an {@code onError} notification the event is passed on immediately without first emitting the * buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} operates by default on the {@code computation} {@link Scheduler}.
@@ -6186,7 +6229,7 @@ public final > Observable buffer(int count, i * {@code onError} notification the event is passed on immediately without first emitting the buffer it is in the process of * assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} operates by default on the {@code computation} {@link Scheduler}.
@@ -6220,7 +6263,7 @@ public final > Observable buffer(int count, i * that if the current {@code Observable} issues an {@code onError} notification the event is passed on immediately without * first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -6256,7 +6299,7 @@ public final > Observable buffer(int count, i * that if the current {@code Observable} issues an {@code onError} notification the event is passed on immediately without * first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -6305,7 +6348,7 @@ public final > Observable buffer(int count, i * {@code Observable}. Note that if the current {@code Observable} issues an {@code onError} notification the event is passed on * immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -6336,7 +6379,7 @@ public final > Observable buffer(int count, i * current {@code Observable}, {@code openingIndicator} or {@code closingIndicator} issues an {@code onError} notification the * event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -6356,7 +6399,7 @@ public final > Observable buffer(int count, i @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable<@NonNull List> buffer( + public final <@NonNull TOpening, @NonNull TClosing> Observable<@NonNull List> buffer( @NonNull ObservableSource openingIndicator, @NonNull Function> closingIndicator) { return buffer(openingIndicator, closingIndicator, ArrayListSupplier.asSupplier()); @@ -6369,7 +6412,7 @@ public final > Observable buffer(int count, i * current {@code Observable}, {@code openingIndicator} or {@code closingIndicator} issues an {@code onError} notification the * event is passed on immediately without first emitting the buffer it is in the process of assembling. *

- * + * *

*
Scheduler:
*
This version of {@code buffer} does not operate by default on a particular {@link Scheduler}.
@@ -6393,7 +6436,7 @@ public final > Observable buffer(int count, i @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Observable buffer( + public final <@NonNull TOpening, @NonNull TClosing, @NonNull U extends Collection> Observable buffer( @NonNull ObservableSource openingIndicator, @NonNull Function> closingIndicator, @NonNull Supplier bufferSupplier) { @@ -6407,7 +6450,7 @@ public final > Observable buffer(int count, i * Returns an {@code Observable} that emits non-overlapping buffered items from the current {@code Observable} each time the * specified boundary {@link ObservableSource} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code ObservableSource} causes the returned {@code ObservableSource} to emit the * latest buffer and complete. If either the current {@code Observable} or the boundary {@code ObservableSource} issues an @@ -6430,7 +6473,7 @@ public final > Observable buffer(int count, i @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable<@NonNull List> buffer(@NonNull ObservableSource boundaryIndicator) { + public final <@NonNull B> Observable<@NonNull List> buffer(@NonNull ObservableSource boundaryIndicator) { return buffer(boundaryIndicator, ArrayListSupplier.asSupplier()); } @@ -6438,7 +6481,7 @@ public final > Observable buffer(int count, i * Returns an {@code Observable} that emits non-overlapping buffered items from the current {@code Observable} each time the * specified boundary {@link ObservableSource} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code ObservableSource} causes the returned {@code ObservableSource} to emit the * latest buffer and complete. If either the current {@code Observable} or the boundary {@code ObservableSource} issues an @@ -6464,7 +6507,7 @@ public final > Observable buffer(int count, i @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable<@NonNull List> buffer(@NonNull ObservableSource boundaryIndicator, int initialCapacity) { + public final <@NonNull B> Observable<@NonNull List> buffer(@NonNull ObservableSource boundaryIndicator, int initialCapacity) { ObjectHelper.verifyPositive(initialCapacity, "initialCapacity"); return buffer(boundaryIndicator, Functions.createArrayList(initialCapacity)); } @@ -6473,7 +6516,7 @@ public final > Observable buffer(int count, i * Returns an {@code Observable} that emits non-overlapping buffered items from the current {@code Observable} each time the * specified boundary {@link ObservableSource} emits an item. *

- * + * *

* Completion of either the source or the boundary {@code ObservableSource} causes the returned {@code ObservableSource} to emit the * latest buffer and complete. If either the current {@code Observable} or the boundary {@code ObservableSource} issues an @@ -6500,7 +6543,7 @@ public final > Observable buffer(int count, i @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Observable buffer(@NonNull ObservableSource boundaryIndicator, @NonNull Supplier bufferSupplier) { + public final <@NonNull B, @NonNull U extends Collection> Observable buffer(@NonNull ObservableSource boundaryIndicator, @NonNull Supplier bufferSupplier) { Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); Objects.requireNonNull(bufferSupplier, "bufferSupplier is null"); return RxJavaPlugins.onAssembly(new ObservableBufferExactBoundary<>(this, boundaryIndicator, bufferSupplier)); @@ -6510,7 +6553,7 @@ public final > Observable buffer(int count, i * Returns an {@code Observable} that subscribes to the current {@code Observable} lazily, caches all of its events * and replays them, in the same order as received, to all the downstream observers. *

- * + * *

* This is useful when you want an {@code Observable} to cache responses and you can't control the * subscribe/dispose behavior of all the {@link Observer}s. @@ -6566,7 +6609,7 @@ public final Observable cache() { * Returns an {@code Observable} that subscribes to the current {@code Observable} lazily, caches all of its events * and replays them, in the same order as received, to all the downstream observers. *

- * + * *

* This is useful when you want an {@code Observable} to cache responses and you can't control the * subscribe/dispose behavior of all the {@link Observer}s. @@ -6625,10 +6668,12 @@ public final Observable cacheWithInitialCapacity(int initialCapacity) { } /** - * Returns an {@code Observable} that emits the items emitted by the current {@code Observable}, converted to the specified - * type. + * Returns an {@code Observable} that emits the upstream items while + * they can be cast via {@link Class#cast(Object)} until the upstream terminates, + * or until the upstream signals an item which can't be cast, + * resulting in a {@link ClassCastException} to be signaled to the downstream. *

- * + * *

*
Scheduler:
*
{@code cast} does not operate by default on a particular {@link Scheduler}.
@@ -6636,8 +6681,7 @@ public final Observable cacheWithInitialCapacity(int initialCapacity) { * * @param the output value type cast to * @param clazz - * the target class type that {@code cast} will cast the items emitted by the current {@code Observable} - * into before emitting them from the resulting {@code Observable} + * the target class to use to try and cast the upstream items into * @return the new {@code Observable} instance * @throws NullPointerException if {@code clazz} is {@code null} * @see ReactiveX operators documentation: Map @@ -6645,7 +6689,7 @@ public final Observable cacheWithInitialCapacity(int initialCapacity) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable cast(@NonNull Class clazz) { + public final <@NonNull U> Observable cast(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return map(Functions.castFunction(clazz)); } @@ -6654,7 +6698,7 @@ public final Observable cast(@NonNull Class clazz) { * Collects items emitted by the finite source {@code Observable} into a single mutable data structure and returns * a {@link Single} that emits this structure. *

- * + * *

* This is a simplified version of {@code reduce} that does not need to return the state on each pass. *

@@ -6679,7 +6723,7 @@ public final Observable cast(@NonNull Class clazz) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single collect(@NonNull Supplier initialItemSupplier, @NonNull BiConsumer collector) { + public final <@NonNull U> Single collect(@NonNull Supplier initialItemSupplier, @NonNull BiConsumer collector) { Objects.requireNonNull(initialItemSupplier, "initialItemSupplier is null"); Objects.requireNonNull(collector, "collector is null"); return RxJavaPlugins.onAssembly(new ObservableCollectSingle<>(this, initialItemSupplier, collector)); @@ -6689,7 +6733,7 @@ public final Single collect(@NonNull Supplier initialItemSup * Collects items emitted by the finite source {@code Observable} into a single mutable data structure and returns * a {@link Single} that emits this structure. *

- * + * *

* This is a simplified version of {@code reduce} that does not need to return the state on each pass. *

@@ -6714,7 +6758,7 @@ public final Single collect(@NonNull Supplier initialItemSup @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single collectInto(@NonNull U initialItem, @NonNull BiConsumer collector) { + public final <@NonNull U> Single collectInto(@NonNull U initialItem, @NonNull BiConsumer collector) { Objects.requireNonNull(initialItem, "initialItem is null"); return collect(Functions.justSupplier(initialItem), collector); } @@ -6743,7 +6787,7 @@ public final Single collectInto(@NonNull U initialItem, @NonNull BiConsum @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable compose(@NonNull ObservableTransformer composer) { + public final <@NonNull R> Observable compose(@NonNull ObservableTransformer composer) { return wrap(((ObservableTransformer) Objects.requireNonNull(composer, "composer is null")).apply(this)); } @@ -6752,7 +6796,7 @@ public final Observable compose(@NonNull ObservableTransformer - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -6774,7 +6818,7 @@ public final Observable compose(@NonNull ObservableTransformer Observable concatMap(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMap(@NonNull Function> mapper) { return concatMap(mapper, 2); } @@ -6783,7 +6827,7 @@ public final Observable concatMap(@NonNull Function - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -6808,7 +6852,7 @@ public final Observable concatMap(@NonNull Function Observable concatMap(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Observable concatMap(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); if (this instanceof ScalarSupplier) { @@ -6827,7 +6871,7 @@ public final Observable concatMap(@NonNull Function - * + * *

* The difference between {@link #concatMap(Function, int)} and this operator is that this operator guarantees the {@code mapper} * function is executed on the specified scheduler. @@ -6853,7 +6897,7 @@ public final Observable concatMap(@NonNull Function Observable concatMap(@NonNull Function> mapper, int bufferSize, @NonNull Scheduler scheduler) { + public final <@NonNull R> Observable concatMap(@NonNull Function> mapper, int bufferSize, @NonNull Scheduler scheduler) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -6885,7 +6929,7 @@ public final Observable concatMap(@NonNull Function Observable concatMapDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapDelayError(@NonNull Function> mapper) { return concatMapDelayError(mapper, true, bufferSize()); } @@ -6920,7 +6964,7 @@ public final Observable concatMapDelayError(@NonNull Function Observable concatMapDelayError(@NonNull Function> mapper, + public final <@NonNull R> Observable concatMapDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); @@ -6965,7 +7009,7 @@ public final Observable concatMapDelayError(@NonNull Function Observable concatMapDelayError(@NonNull Function> mapper, + public final <@NonNull R> Observable concatMapDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize, @NonNull Scheduler scheduler) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); @@ -6996,7 +7040,7 @@ public final Observable concatMapDelayError(@NonNull Function Observable concatMapEager(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapEager(@NonNull Function> mapper) { return concatMapEager(mapper, Integer.MAX_VALUE, bufferSize()); } @@ -7026,7 +7070,7 @@ public final Observable concatMapEager(@NonNull Function Observable concatMapEager(@NonNull Function> mapper, + public final <@NonNull R> Observable concatMapEager(@NonNull Function> mapper, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -7060,7 +7104,7 @@ public final Observable concatMapEager(@NonNull Function Observable concatMapEagerDelayError(@NonNull Function> mapper, + public final <@NonNull R> Observable concatMapEagerDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapEagerDelayError(mapper, tillTheEnd, Integer.MAX_VALUE, bufferSize()); } @@ -7096,7 +7140,7 @@ public final Observable concatMapEagerDelayError(@NonNull Function Observable concatMapEagerDelayError(@NonNull Function> mapper, + public final <@NonNull R> Observable concatMapEagerDelayError(@NonNull Function> mapper, boolean tillTheEnd, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -7162,7 +7206,7 @@ public final Completable concatMapCompletable(@NonNull Function - * + * *

*
Scheduler:
*
{@code concatMapCompletableDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7188,7 +7232,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapCompletableDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7220,7 +7264,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapCompletableDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7275,7 +7319,7 @@ public final Completable concatMapCompletableDelayError(@NonNull Function Observable concatMapIterable(@NonNull Function> mapper) { + public final <@NonNull U> Observable concatMapIterable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlattenIterable<>(this, mapper)); } @@ -7285,7 +7329,7 @@ public final Observable concatMapIterable(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -7304,7 +7348,7 @@ public final Observable concatMapIterable(@NonNull Function Observable concatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapMaybe(@NonNull Function> mapper) { return concatMapMaybe(mapper, 2); } @@ -7313,7 +7357,7 @@ public final Observable concatMapMaybe(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -7335,7 +7379,7 @@ public final Observable concatMapMaybe(@NonNull Function Observable concatMapMaybe(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Observable concatMapMaybe(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableConcatMapMaybe<>(this, mapper, ErrorMode.IMMEDIATE, bufferSize)); @@ -7346,7 +7390,7 @@ public final Observable concatMapMaybe(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapMaybeDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7365,7 +7409,7 @@ public final Observable concatMapMaybe(@NonNull Function Observable concatMapMaybeDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapMaybeDelayError(@NonNull Function> mapper) { return concatMapMaybeDelayError(mapper, true, 2); } @@ -7374,7 +7418,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapMaybeDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7399,7 +7443,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function Observable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd) { + public final <@NonNull R> Observable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapMaybeDelayError(mapper, tillTheEnd, 2); } @@ -7408,7 +7452,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapMaybeDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7435,7 +7479,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function Observable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize) { + public final <@NonNull R> Observable concatMapMaybeDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableConcatMapMaybe<>(this, mapper, tillTheEnd ? ErrorMode.END : ErrorMode.BOUNDARY, bufferSize)); @@ -7446,7 +7490,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -7465,7 +7509,7 @@ public final Observable concatMapMaybeDelayError(@NonNull Function Observable concatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapSingle(@NonNull Function> mapper) { return concatMapSingle(mapper, 2); } @@ -7474,7 +7518,7 @@ public final Observable concatMapSingle(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -7496,7 +7540,7 @@ public final Observable concatMapSingle(@NonNull Function Observable concatMapSingle(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Observable concatMapSingle(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableConcatMapSingle<>(this, mapper, ErrorMode.IMMEDIATE, bufferSize)); @@ -7507,7 +7551,7 @@ public final Observable concatMapSingle(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapSingleDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7526,7 +7570,7 @@ public final Observable concatMapSingle(@NonNull Function Observable concatMapSingleDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable concatMapSingleDelayError(@NonNull Function> mapper) { return concatMapSingleDelayError(mapper, true, 2); } @@ -7535,7 +7579,7 @@ public final Observable concatMapSingleDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapSingleDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7560,7 +7604,7 @@ public final Observable concatMapSingleDelayError(@NonNull Function Observable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd) { + public final <@NonNull R> Observable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd) { return concatMapSingleDelayError(mapper, tillTheEnd, 2); } @@ -7569,7 +7613,7 @@ public final Observable concatMapSingleDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapSingleDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -7596,7 +7640,7 @@ public final Observable concatMapSingleDelayError(@NonNull Function Observable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize) { + public final <@NonNull R> Observable concatMapSingleDelayError(@NonNull Function> mapper, boolean tillTheEnd, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableConcatMapSingle<>(this, mapper, tillTheEnd ? ErrorMode.END : ErrorMode.BOUNDARY, bufferSize)); @@ -7606,7 +7650,7 @@ public final Observable concatMapSingleDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatWith} does not operate by default on a particular {@link Scheduler}.
@@ -7630,7 +7674,7 @@ public final Observable concatWith(@NonNull ObservableSource oth * Returns an {@code Observable} that emits the items from the current {@code Observable} followed by the success item or error event * of the {@code other} {@link SingleSource}. *

- * + * *

*
Scheduler:
*
{@code concatWith} does not operate by default on a particular {@link Scheduler}.
@@ -7653,7 +7697,7 @@ public final Observable concatWith(@NonNull SingleSource other) * Returns an {@code Observable} that emits the items from the current {@code Observable} followed by the success item or terminal events * of the other {@link MaybeSource}. *

- * + * *

*
Scheduler:
*
{@code concatWith} does not operate by default on a particular {@link Scheduler}.
@@ -7676,7 +7720,7 @@ public final Observable concatWith(@NonNull MaybeSource other) { * Returns an {@code Observable} that emits items from the current {@code Observable} and when it completes normally, the * other {@link CompletableSource} is subscribed to and the returned {@code Observable} emits its terminal events. *

- * + * *

*
Scheduler:
*
{@code concatWith} does not operate by default on a particular {@link Scheduler}.
@@ -7699,7 +7743,7 @@ public final Observable concatWith(@NonNull CompletableSource other) { * Returns a {@link Single} that emits a {@link Boolean} that indicates whether the current {@code Observable} emitted a * specified item. *

- * + * *

*
Scheduler:
*
{@code contains} does not operate by default on a particular {@link Scheduler}.
@@ -7723,7 +7767,7 @@ public final Single contains(@NonNull Object item) { * Returns a {@link Single} that counts the total number of items emitted by the current {@code Observable} and emits * this count as a 64-bit {@link Long}. *

- * + * *

*
Scheduler:
*
{@code count} does not operate by default on a particular {@link Scheduler}.
@@ -7744,7 +7788,7 @@ public final Single count() { * current {@code Observable} that are followed by another item within a computed debounce duration * denoted by an item emission or completion from a generated inner {@link ObservableSource} for that original item. *

- * + * *

* The delivery of the item happens on the thread of the first {@code onNext} or {@code onComplete} * signal of the generated {@code ObservableSource} sequence, @@ -7769,7 +7813,7 @@ public final Single count() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable debounce(@NonNull Function> debounceIndicator) { + public final <@NonNull U> Observable debounce(@NonNull Function> debounceIndicator) { Objects.requireNonNull(debounceIndicator, "debounceIndicator is null"); return RxJavaPlugins.onAssembly(new ObservableDebounce<>(this, debounceIndicator)); } @@ -7782,7 +7826,7 @@ public final Observable debounce(@NonNull FunctionNote: If items keep being emitted by the current {@code Observable} faster than the timeout then no items * will be emitted by the resulting {@code Observable}. *

- * + * *

* Delivery of the item after the grace period happens on the {@code computation} {@link Scheduler}'s * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the @@ -7821,7 +7865,7 @@ public final Observable debounce(long timeout, @NonNull TimeUnit unit) { * Note: If items keep being emitted by the current {@code Observable} faster than the timeout then no items * will be emitted by the resulting {@code Observable}. *

- * + * *

* Delivery of the item after the grace period happens on the given {@code Scheduler}'s * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the @@ -7853,14 +7897,62 @@ public final Observable debounce(long timeout, @NonNull TimeUnit unit) { public final Observable debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<>(this, timeout, unit, scheduler)); + return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<>(this, timeout, unit, scheduler, null)); + } + + /** + * Returns an {@code Observable} that mirrors the current {@code Observable}, except that it drops items emitted by the + * current {@code Observable} that are followed by newer items before a timeout value expires on a specified + * {@link Scheduler}. The timer resets on each emission. + *

+ * Note: If items keep being emitted by the current {@code Observable} faster than the timeout then no items + * will be emitted by the resulting {@code Observable}. + *

+ * + *

+ * Delivery of the item after the grace period happens on the given {@code Scheduler}'s + * {@code Worker} which if takes too long, a newer item may arrive from the upstream, causing the + * {@code Worker}'s task to get disposed, which may also interrupt any downstream blocking operation + * (yielding an {@code InterruptedException}). It is recommended processing items + * that may take long time to be moved to another thread via {@link #observeOn} applied after + * {@code debounce} itself. + *

+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param timeout + * the time each item has to be "the most recent" of those emitted by the current {@code Observable} to + * ensure that it's not dropped + * @param unit + * the unit of time for the specified {@code timeout} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle the timeout for each + * item + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} } or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Debounce + * @see #throttleWithTimeout(long, TimeUnit, Scheduler, Consumer) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<>(this, timeout, unit, scheduler, onDropped)); } /** * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} or a specified default item * if the current {@code Observable} is empty. *

- * + * *

*
Scheduler:
*
{@code defaultIfEmpty} does not operate by default on a particular {@link Scheduler}.
@@ -7884,7 +7976,7 @@ public final Observable defaultIfEmpty(@NonNull T defaultItem) { * Returns an {@code Observable} that delays the emissions of the current {@code Observable} via * a per-item derived {@link ObservableSource}'s item emission or termination, on a per source item basis. *

- * + * *

* Note: the resulting {@code Observable} will immediately propagate any {@code onError} notification * from the current {@code Observable}. @@ -7906,7 +7998,7 @@ public final Observable defaultIfEmpty(@NonNull T defaultItem) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delay(@NonNull Function> itemDelayIndicator) { + public final <@NonNull U> Observable delay(@NonNull Function> itemDelayIndicator) { Objects.requireNonNull(itemDelayIndicator, "itemDelayIndicator is null"); return flatMap(ObservableInternalHelper.itemDelay(itemDelayIndicator)); } @@ -7915,7 +8007,7 @@ public final Observable delay(@NonNull Function - * + * *

*
Scheduler:
*
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
@@ -7942,7 +8034,7 @@ public final Observable delay(long time, @NonNull TimeUnit unit) { * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} shifted forward in time by a * specified delay. If {@code delayError} is {@code true}, error notifications will also be delayed. *

- * + * *

*
Scheduler:
*
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
@@ -7971,7 +8063,7 @@ public final Observable delay(long time, @NonNull TimeUnit unit, boolean dela * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} shifted forward in time by a * specified delay. An error notification from the current {@code Observable} is not delayed. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -7998,7 +8090,7 @@ public final Observable delay(long time, @NonNull TimeUnit unit, @NonNull Sch * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} shifted forward in time by a * specified delay. If {@code delayError} is {@code true}, error notifications will also be delayed. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -8031,7 +8123,7 @@ public final Observable delay(long time, @NonNull TimeUnit unit, @NonNull Sch * Returns an {@code Observable} that delays the subscription to and emissions from the current {@code Observable} via * {@link ObservableSource}s for the subscription itself and on a per-item basis. *

- * + * *

* Note: the resulting {@code Observable} will immediately propagate any {@code onError} notification * from the current {@code Observable}. @@ -8058,7 +8150,7 @@ public final Observable delay(long time, @NonNull TimeUnit unit, @NonNull Sch @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delay(@NonNull ObservableSource subscriptionIndicator, + public final <@NonNull U, @NonNull V> Observable delay(@NonNull ObservableSource subscriptionIndicator, @NonNull Function> itemDelayIndicator) { return delaySubscription(subscriptionIndicator).delay(itemDelayIndicator); } @@ -8067,7 +8159,7 @@ public final Observable delay(@NonNull ObservableSource subscriptio * Returns an {@code Observable} that delays the subscription to the current {@code Observable} * until the other {@link ObservableSource} emits an element or completes normally. *

- * + * *

*
Scheduler:
*
This method does not operate by default on a particular {@link Scheduler}.
@@ -8083,7 +8175,7 @@ public final Observable delay(@NonNull ObservableSource subscriptio @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delaySubscription(@NonNull ObservableSource subscriptionIndicator) { + public final <@NonNull U> Observable delaySubscription(@NonNull ObservableSource subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new ObservableDelaySubscriptionOther<>(this, subscriptionIndicator)); } @@ -8091,7 +8183,7 @@ public final Observable delaySubscription(@NonNull ObservableSource su /** * Returns an {@code Observable} that delays the subscription to the current {@code Observable} by a given amount of time. *

- * + * *

*
Scheduler:
*
This version of {@code delaySubscription} operates by default on the {@code computation} {@link Scheduler}.
@@ -8116,7 +8208,7 @@ public final Observable delaySubscription(long time, @NonNull TimeUnit unit) * Returns an {@code Observable} that delays the subscription to the current {@code Observable} by a given amount of time, * both waiting and subscribing on a given {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -8144,7 +8236,7 @@ public final Observable delaySubscription(long time, @NonNull TimeUnit unit, * {@link Notification} objects extracted from the source items via a selector function * into their respective {@link Observer} signal types. *

- * + * *

* The intended use of the {@code selector} function is to perform a * type-safe identity mapping (see example) on a source that is already of type @@ -8189,7 +8281,7 @@ public final Observable delaySubscription(long time, @NonNull TimeUnit unit, @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable dematerialize(@NonNull Function> selector) { + public final <@NonNull R> Observable dematerialize(@NonNull Function> selector) { Objects.requireNonNull(selector, "selector is null"); return RxJavaPlugins.onAssembly(new ObservableDematerialize<>(this, selector)); } @@ -8198,7 +8290,7 @@ public final Observable dematerialize(@NonNull Function - * + * *

* It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} * and {@link Object#hashCode()} to provide meaningful comparison between items as the default Java @@ -8236,7 +8328,7 @@ public final Observable distinct() { * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects * returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} * and {@link Object#hashCode()} to provide meaningful comparison between the key objects as the default @@ -8269,7 +8361,7 @@ public final Observable distinct() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable distinct(@NonNull Function keySelector) { + public final <@NonNull K> Observable distinct(@NonNull Function keySelector) { return distinct(keySelector, Functions.createHashSet()); } @@ -8278,7 +8370,7 @@ public final Observable distinct(@NonNull Function keySelec * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects * returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} * and {@link Object#hashCode()} to provide meaningful comparison between the key objects as @@ -8302,7 +8394,7 @@ public final Observable distinct(@NonNull Function keySelec @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable distinct(@NonNull Function keySelector, @NonNull Supplier> collectionSupplier) { + public final <@NonNull K> Observable distinct(@NonNull Function keySelector, @NonNull Supplier> collectionSupplier) { Objects.requireNonNull(keySelector, "keySelector is null"); Objects.requireNonNull(collectionSupplier, "collectionSupplier is null"); return RxJavaPlugins.onAssembly(new ObservableDistinct<>(this, keySelector, collectionSupplier)); @@ -8312,7 +8404,7 @@ public final Observable distinct(@NonNull Function keySelec * Returns an {@code Observable} that emits all items emitted by the current {@code Observable} that are distinct from their * immediate predecessors based on {@link Object#equals(Object)} comparison. *

- * + * *

* It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} to provide * meaningful comparison between items as the default Java implementation only considers reference equivalence. @@ -8350,7 +8442,7 @@ public final Observable distinctUntilChanged() { * immediate predecessors, according to a key selector function and based on {@link Object#equals(Object)} comparison * of those objects returned by the key selector function. *

- * + * *

* It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} to provide * meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. @@ -8384,7 +8476,7 @@ public final Observable distinctUntilChanged() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable distinctUntilChanged(@NonNull Function keySelector) { + public final <@NonNull K> Observable distinctUntilChanged(@NonNull Function keySelector) { Objects.requireNonNull(keySelector, "keySelector is null"); return RxJavaPlugins.onAssembly(new ObservableDistinctUntilChanged<>(this, keySelector, ObjectHelper.equalsPredicate())); } @@ -8393,7 +8485,7 @@ public final Observable distinctUntilChanged(@NonNull Function - * + * *

* Note that the operator always retains the latest item from upstream regardless of the comparison result * and uses it in the next comparison with the next upstream item. @@ -8430,7 +8522,7 @@ public final Observable distinctUntilChanged(@NonNull BiPredicate - * + * *

*
Scheduler:
*
{@code doAfterNext} does not operate by default on a particular {@link Scheduler}.
@@ -8455,7 +8547,7 @@ public final Observable doAfterNext(@NonNull Consumer onAfterNext) * Registers an {@link Action} to be called when the current {@code Observable} invokes either * {@link Observer#onComplete onComplete} or {@link Observer#onError onError}. *

- * + * *

*
Scheduler:
*
{@code doAfterTerminate} does not operate by default on a particular {@link Scheduler}.
@@ -8514,7 +8606,7 @@ public final Observable doFinally(@NonNull Action onFinally) { * If the action throws a runtime exception, that exception is rethrown by the {@code dispose()} call, * sometimes as a {@link CompositeException} if there were multiple exceptions along the way. *

- * + * *

*
Scheduler:
*
{@code doOnDispose} does not operate by default on a particular {@link Scheduler}.
@@ -8536,7 +8628,7 @@ public final Observable doOnDispose(@NonNull Action onDispose) { /** * Returns an {@code Observable} that invokes an {@link Action} when the current {@code Observable} calls {@code onComplete}. *

- * + * *

*
Scheduler:
*
{@code doOnComplete} does not operate by default on a particular {@link Scheduler}.
@@ -8559,12 +8651,16 @@ public final Observable doOnComplete(@NonNull Action onComplete) { * Calls the appropriate {@code onXXX} consumer (shared between all {@link Observer}s) whenever a signal with the same type * passes through, before forwarding them to the downstream. *

- * + * *

*
Scheduler:
*
{@code doOnEach} does not operate by default on a particular {@link Scheduler}.
*
* + * @param onNext the {@link Consumer} to invoke when the current {@code Observable} calls {@code onNext} + * @param onError the {@code Consumer} to invoke when the current {@code Observable} calls {@code onError} + * @param onComplete the {@link Action} to invoke when the current {@code Observable} calls {@code onComplete} + * @param onAfterTerminate the {@code Action} to invoke when the current {@code Observable} calls {@code onAfterTerminate} * @return the new {@code Observable} instance * @throws NullPointerException if {@code onNext}, {@code onError}, {@code onComplete} or {@code onAfterTerminate} is {@code null} * @see ReactiveX operators documentation: Do @@ -8584,7 +8680,7 @@ private Observable doOnEach(@NonNull Consumer onNext, @NonNull Con * Returns an {@code Observable} that invokes a {@link Consumer} with the appropriate {@link Notification} * object when the current {@code Observable} signals an item or terminates. *

- * + * *

*
Scheduler:
*
{@code doOnEach} does not operate by default on a particular {@link Scheduler}.
@@ -8618,7 +8714,7 @@ public final Observable doOnEach(@NonNull Consumer> o * {@code onNext} or the {@code onComplete} method of the supplied observer throws, the downstream will be * terminated and will receive this thrown exception. *

- * + * *

*
Scheduler:
*
{@code doOnEach} does not operate by default on a particular {@link Scheduler}.
@@ -8650,7 +8746,7 @@ public final Observable doOnEach(@NonNull Observer observer) { * In case the {@code onError} action throws, the downstream will receive a composite exception containing * the original exception and the exception thrown by {@code onError}. *

- * + * *

*
Scheduler:
*
{@code doOnError} does not operate by default on a particular {@link Scheduler}.
@@ -8673,7 +8769,7 @@ public final Observable doOnError(@NonNull Consumer onErro * Calls the appropriate {@code onXXX} method (shared between all {@link Observer}s) for the lifecycle events of * the sequence (subscription, disposal). *

- * + * *

*
Scheduler:
*
{@code doOnLifecycle} does not operate by default on a particular {@link Scheduler}.
@@ -8699,7 +8795,7 @@ public final Observable doOnLifecycle(@NonNull Consumer o /** * Calls the given {@link Consumer} with the value emitted by the current {@code Observable} before forwarding it to the downstream. *

- * + * *

*
Scheduler:
*
{@code doOnNext} does not operate by default on a particular {@link Scheduler}.
@@ -8724,7 +8820,7 @@ public final Observable doOnNext(@NonNull Consumer onNext) { * current {@code Observable} is reference counted, in which case the current {@code Observable} will invoke * the given action for the first subscription. *

- * + * *

*
Scheduler:
*
{@code doOnSubscribe} does not operate by default on a particular {@link Scheduler}.
@@ -8861,7 +8957,7 @@ public final Single elementAtOrError(long index) { /** * Filters items emitted by the current {@code Observable} by only emitting those that satisfy a specified {@link Predicate}. *

- * + * *

*
Scheduler:
*
{@code filter} does not operate by default on a particular {@link Scheduler}.
@@ -8906,7 +9002,7 @@ public final Maybe firstElement() { * Returns a {@link Single} that emits only the very first item emitted by the current {@code Observable}, or a default item * if the current {@code Observable} completes without emitting any items. *

- * + * *

*
Scheduler:
*
{@code first} does not operate by default on a particular {@link Scheduler}.
@@ -8950,7 +9046,7 @@ public final Single firstOrError() { * by the current {@code Observable}, where that function returns an {@link ObservableSource}, and then merging those returned * {@code ObservableSource}s and emitting the results of this merger. *

- * + * *

*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -8967,7 +9063,7 @@ public final Single firstOrError() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable flatMap(@NonNull Function> mapper) { + public final <@NonNull R> Observable flatMap(@NonNull Function> mapper) { return flatMap(mapper, false); } @@ -8996,7 +9092,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, boolean delayErrors) { + public final <@NonNull R> Observable flatMap(@NonNull Function> mapper, boolean delayErrors) { return flatMap(mapper, delayErrors, Integer.MAX_VALUE); } @@ -9030,7 +9126,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { + public final <@NonNull R> Observable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency) { return flatMap(mapper, delayErrors, maxConcurrency, bufferSize()); } @@ -9066,7 +9162,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull R> Observable flatMap(@NonNull Function> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -9086,7 +9182,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9109,7 +9205,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap( + public final <@NonNull R> Observable flatMap( @NonNull Function> onNextMapper, @NonNull Function> onErrorMapper, @NonNull Supplier> onCompleteSupplier) { @@ -9124,7 +9220,7 @@ public final Observable flatMap( * {@code Observable} and then flattens the {@link ObservableSource}s returned from these functions and emits the resulting items, * while limiting the maximum number of concurrent subscriptions to these {@code ObservableSource}s. *

- * + * *

*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9151,7 +9247,7 @@ public final Observable flatMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable flatMap( + public final <@NonNull R> Observable flatMap( @NonNull Function> onNextMapper, @NonNull Function> onErrorMapper, @NonNull Supplier> onCompleteSupplier, @@ -9189,7 +9285,7 @@ public final Observable flatMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable flatMap(@NonNull Function> mapper, int maxConcurrency) { + public final <@NonNull R> Observable flatMap(@NonNull Function> mapper, int maxConcurrency) { return flatMap(mapper, false, maxConcurrency, bufferSize()); } @@ -9197,7 +9293,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9219,7 +9315,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Observable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner) { return flatMap(mapper, combiner, false, bufferSize(), bufferSize()); } @@ -9228,7 +9324,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9253,7 +9349,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Observable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors) { return flatMap(mapper, combiner, delayErrors, bufferSize(), bufferSize()); } @@ -9263,7 +9359,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9292,7 +9388,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Observable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors, int maxConcurrency) { return flatMap(mapper, combiner, delayErrors, maxConcurrency, bufferSize()); } @@ -9302,7 +9398,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9333,7 +9429,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Observable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, boolean delayErrors, int maxConcurrency, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -9345,7 +9441,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9371,7 +9467,7 @@ public final Observable flatMap(@NonNull Function Observable flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Observable flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner, int maxConcurrency) { return flatMap(mapper, combiner, false, maxConcurrency, bufferSize()); } @@ -9441,7 +9537,7 @@ public final Completable flatMapCompletable(@NonNull Function Observable flatMapIterable(@NonNull Function> mapper) { + public final <@NonNull U> Observable flatMapIterable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlattenIterable<>(this, mapper)); } @@ -9475,7 +9571,7 @@ public final Observable flatMapIterable(@NonNull Function Observable flatMapIterable(@NonNull Function> mapper, + public final <@NonNull U, @NonNull V> Observable flatMapIterable(@NonNull Function> mapper, @NonNull BiFunction combiner) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -9486,7 +9582,7 @@ public final Observable flatMapIterable(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -9499,7 +9595,7 @@ public final Observable flatMapIterable(@NonNull Function Observable flatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Observable flatMapMaybe(@NonNull Function> mapper) { return flatMapMaybe(mapper, false); } @@ -9508,7 +9604,7 @@ public final Observable flatMapMaybe(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -9523,7 +9619,7 @@ public final Observable flatMapMaybe(@NonNull Function Observable flatMapMaybe(@NonNull Function> mapper, boolean delayErrors) { + public final <@NonNull R> Observable flatMapMaybe(@NonNull Function> mapper, boolean delayErrors) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMapMaybe<>(this, mapper, delayErrors)); } @@ -9532,7 +9628,7 @@ public final Observable flatMapMaybe(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -9545,7 +9641,7 @@ public final Observable flatMapMaybe(@NonNull Function Observable flatMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Observable flatMapSingle(@NonNull Function> mapper) { return flatMapSingle(mapper, false); } @@ -9554,7 +9650,7 @@ public final Observable flatMapSingle(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -9569,7 +9665,7 @@ public final Observable flatMapSingle(@NonNull Function Observable flatMapSingle(@NonNull Function> mapper, boolean delayErrors) { + public final <@NonNull R> Observable flatMapSingle(@NonNull Function> mapper, boolean delayErrors) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMapSingle<>(this, mapper, delayErrors)); } @@ -9694,7 +9790,7 @@ public final Disposable forEachWhile(@NonNull Predicate onNext, @NonN * Groups the items emitted by the current {@code Observable} according to a specified criterion, and emits these * grouped items as {@link GroupedObservable}s. *

- * + * *

* Each emitted {@code GroupedObservable} allows only a single {@link Observer} to subscribe to it during its * lifetime and if this {@code Observer} calls {@code dispose()} before the @@ -9728,7 +9824,7 @@ public final Disposable forEachWhile(@NonNull Predicate onNext, @NonN @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> groupBy(@NonNull Function keySelector) { + public final <@NonNull K> Observable> groupBy(@NonNull Function keySelector) { return groupBy(keySelector, (Function)Functions.identity(), false, bufferSize()); } @@ -9736,7 +9832,7 @@ public final Observable> groupBy(@NonNull Function - * + * *

* Each emitted {@code GroupedObservable} allows only a single {@link Observer} to subscribe to it during its * lifetime and if this {@code Observer} calls {@code dispose()} before the @@ -9773,7 +9869,7 @@ public final Observable> groupBy(@NonNull Function Observable> groupBy(@NonNull Function keySelector, boolean delayError) { + public final <@NonNull K> Observable> groupBy(@NonNull Function keySelector, boolean delayError) { return groupBy(keySelector, (Function)Functions.identity(), delayError, bufferSize()); } @@ -9781,7 +9877,7 @@ public final Observable> groupBy(@NonNull Function - * + * *

* Each emitted {@code GroupedObservable} allows only a single {@link Observer} to subscribe to it during its * lifetime and if this {@code Observer} calls {@code dispose()} before the @@ -9818,7 +9914,7 @@ public final Observable> groupBy(@NonNull Function Observable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Observable> groupBy(@NonNull Function keySelector, Function valueSelector) { return groupBy(keySelector, valueSelector, false, bufferSize()); } @@ -9827,7 +9923,7 @@ public final Observable> groupBy(@NonNull Functio * Groups the items emitted by the current {@code Observable} according to a specified criterion, and emits these * grouped items as {@link GroupedObservable}s. *

- * + * *

* Each emitted {@code GroupedObservable} allows only a single {@link Observer} to subscribe to it during its * lifetime and if this {@code Observer} calls {@code dispose()} before the @@ -9867,7 +9963,7 @@ public final Observable> groupBy(@NonNull Functio @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Observable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector, boolean delayError) { return groupBy(keySelector, valueSelector, delayError, bufferSize()); } @@ -9876,7 +9972,7 @@ public final Observable> groupBy(@NonNull Functio * Groups the items emitted by the current {@code Observable} according to a specified criterion, and emits these * grouped items as {@link GroupedObservable}s. *

- * + * *

* Each emitted {@code GroupedObservable} allows only a single {@link Observer} to subscribe to it during its * lifetime and if this {@code Observer} calls {@code dispose()} before the @@ -9919,7 +10015,7 @@ public final Observable> groupBy(@NonNull Functio @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> groupBy(@NonNull Function keySelector, + public final <@NonNull K, @NonNull V> Observable> groupBy(@NonNull Function keySelector, @NonNull Function valueSelector, boolean delayError, int bufferSize) { Objects.requireNonNull(keySelector, "keySelector is null"); @@ -9935,7 +10031,7 @@ public final Observable> groupBy(@NonNull Functio * There are no guarantees in what order the items get combined when multiple * items from one or both source {@code ObservableSource}s overlap. *

- * + * *

*
Scheduler:
*
{@code groupJoin} does not operate by default on a particular {@link Scheduler}.
@@ -9963,7 +10059,7 @@ public final Observable> groupBy(@NonNull Functio @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable groupJoin( + public final <@NonNull TRight, @NonNull TLeftEnd, @NonNull TRightEnd, @NonNull R> Observable groupJoin( @NonNull ObservableSource other, @NonNull Function> leftEnd, @NonNull Function> rightEnd, @@ -10003,7 +10099,7 @@ public final Observable hide() { /** * Ignores all items emitted by the current {@code Observable} and only calls {@code onComplete} or {@code onError}. *

- * + * *

*
Scheduler:
*
{@code ignoreElements} does not operate by default on a particular {@link Scheduler}.
@@ -10025,7 +10121,7 @@ public final Completable ignoreElements() { * In Rx.Net this is negated as the {@code any} {@link Observer} but we renamed this in RxJava to better match Java * naming idioms. *

- * + * *

*
Scheduler:
*
{@code isEmpty} does not operate by default on a particular {@link Scheduler}.
@@ -10047,7 +10143,7 @@ public final Single isEmpty() { * There are no guarantees in what order the items get combined when multiple * items from one or both source {@code ObservableSource}s overlap. *

- * + * *

*
Scheduler:
*
{@code join} does not operate by default on a particular {@link Scheduler}.
@@ -10075,7 +10171,7 @@ public final Single isEmpty() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable join( + public final <@NonNull TRight, @NonNull TLeftEnd, @NonNull TRightEnd, @NonNull R> Observable join( @NonNull ObservableSource other, @NonNull Function> leftEnd, @NonNull Function> rightEnd, @@ -10093,7 +10189,7 @@ public final Observable join( * Returns a {@link Maybe} that emits the last item emitted by the current {@code Observable} or * completes if the current {@code Observable} is empty. *

- * + * *

*
Scheduler:
*
{@code lastElement} does not operate by default on a particular {@link Scheduler}.
@@ -10113,7 +10209,7 @@ public final Maybe lastElement() { * Returns a {@link Single} that emits only the last item emitted by the current {@code Observable}, or a default item * if the current {@code Observable} completes without emitting any items. *

- * + * *

*
Scheduler:
*
{@code last} does not operate by default on a particular {@link Scheduler}.
@@ -10299,7 +10395,7 @@ public final Single lastOrError() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable lift(@NonNull ObservableOperator lifter) { + public final <@NonNull R> Observable lift(@NonNull ObservableOperator lifter) { Objects.requireNonNull(lifter, "lifter is null"); return RxJavaPlugins.onAssembly(new ObservableLift<>(this, lifter)); } @@ -10308,7 +10404,7 @@ public final Observable lift(@NonNull ObservableOperator - * + * *
*
Scheduler:
*
{@code map} does not operate by default on a particular {@link Scheduler}.
@@ -10324,7 +10420,7 @@ public final Observable lift(@NonNull ObservableOperator Observable map(@NonNull Function mapper) { + public final <@NonNull R> Observable map(@NonNull Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableMap<>(this, mapper)); } @@ -10333,7 +10429,7 @@ public final Observable map(@NonNull Function map * Returns an {@code Observable} that represents all of the emissions and notifications from the current * {@code Observable} into emissions marked with their original types within {@link Notification} objects. *

- * + * *

*
Scheduler:
*
{@code materialize} does not operate by default on a particular {@link Scheduler}.
@@ -10353,7 +10449,7 @@ public final Observable> materialize() { /** * Flattens the current {@code Observable} and another {@link ObservableSource} into a single {@code Observable} sequence, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code ObservableSource}s so that they appear as a single {@code ObservableSource}, by * using the {@code mergeWith} method. @@ -10379,7 +10475,7 @@ public final Observable mergeWith(@NonNull ObservableSource othe /** * Merges the sequence of items of the current {@code Observable} with the success value of the other {@link SingleSource}. *

- * + * *

* The success value of the other {@code SingleSource} can get interleaved at any point of the current * {@code Observable} sequence. @@ -10405,7 +10501,7 @@ public final Observable mergeWith(@NonNull SingleSource other) { * Merges the sequence of items of the current {@code Observable} with the success value of the other {@link MaybeSource} * or waits both to complete normally if the {@code MaybeSource} is empty. *

- * + * *

* The success value of the other {@code MaybeSource} can get interleaved at any point of the current * {@code Observable} sequence. @@ -10431,7 +10527,7 @@ public final Observable mergeWith(@NonNull MaybeSource other) { * Relays the items of the current {@code Observable} and completes only when the other {@link CompletableSource} completes * as well. *

- * + * *

*
Scheduler:
*
{@code mergeWith} does not operate by default on a particular {@link Scheduler}.
@@ -10457,7 +10553,7 @@ public final Observable mergeWith(@NonNull CompletableSource other) { *

Note that {@code onError} notifications will cut ahead of {@code onNext} notifications on the emission thread if {@code Scheduler} is truly * asynchronous. If strict event ordering is required, consider using the {@link #observeOn(Scheduler, boolean)} overload. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -10492,7 +10588,7 @@ public final Observable observeOn(@NonNull Scheduler scheduler) { * Returns an {@code Observable} to perform the current {@code Observable}'s emissions and notifications on a specified {@link Scheduler}, * asynchronously with an unbounded buffer with {@link Flowable#bufferSize()} "island size" and optionally delays {@code onError} notifications. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -10531,7 +10627,7 @@ public final Observable observeOn(@NonNull Scheduler scheduler, boolean delay * Returns an {@code Observable} to perform the current {@code Observable}'s emissions and notifications on a specified {@link Scheduler}, * asynchronously with an unbounded buffer of configurable "island size" and optionally delays {@code onError} notifications. *

- * + * *

* This operator keeps emitting as many signals as it can on the given {@code Scheduler}'s worker thread, * which may result in a longer than expected occupation of this thread. In other terms, @@ -10573,7 +10669,7 @@ public final Observable observeOn(@NonNull Scheduler scheduler, boolean delay /** * Filters the items emitted by the current {@code Observable}, only emitting those of the specified type. *

- * + * *

*
Scheduler:
*
{@code ofType} does not operate by default on a particular {@link Scheduler}.
@@ -10589,7 +10685,7 @@ public final Observable observeOn(@NonNull Scheduler scheduler, boolean delay @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable ofType(@NonNull Class clazz) { + public final <@NonNull U> Observable ofType(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return filter(Functions.isInstanceOf(clazz)).cast(clazz); } @@ -10641,7 +10737,7 @@ public final Observable onErrorComplete(@NonNull Predicate * Resumes the flow with an {@link ObservableSource} returned for the failure {@link Throwable} of the current {@code Observable} by a * function instead of signaling the error via {@code onError}. *

- * + * *

* By default, when an {@code ObservableSource} encounters an error that prevents it from emitting the expected item to * its {@link Observer}, the {@code ObservableSource} invokes its {@code Observer}'s {@code onError} method, and then quits @@ -10679,7 +10775,7 @@ public final Observable onErrorResumeNext(@NonNull Function - * + * *

* By default, when an {@code ObservableSource} encounters an error that prevents it from emitting the expected item to * its {@link Observer}, the {@code ObservableSource} invokes its {@code Observer}'s {@code onError} method, and then quits @@ -10717,7 +10813,7 @@ public final Observable onErrorResumeWith(@NonNull ObservableSource - * + * *

* By default, when an {@link ObservableSource} encounters an error that prevents it from emitting the expected item to * its {@link Observer}, the {@code ObservableSource} invokes its {@code Observer}'s {@code onError} method, and then quits @@ -10751,7 +10847,7 @@ public final Observable onErrorReturn(@NonNull Function - * + * *

* By default, when an {@link ObservableSource} encounters an error that prevents it from emitting the expected item to * its {@link Observer}, the {@code ObservableSource} invokes its {@code Observer}'s {@code onError} method, and then quits @@ -10807,7 +10903,7 @@ public final Observable onTerminateDetach() { * {@link ConnectableObservable#connect connect} method is called before it begins emitting items to those * {@link Observer}s that have subscribed to it. *

- * + * *

*
Scheduler:
*
{@code publish} does not operate by default on a particular {@link Scheduler}.
@@ -10846,7 +10942,7 @@ public final ConnectableObservable publish() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable publish(@NonNull Function, ? extends ObservableSource> selector) { + public final <@NonNull R> Observable publish(@NonNull Function, ? extends ObservableSource> selector) { Objects.requireNonNull(selector, "selector is null"); return RxJavaPlugins.onAssembly(new ObservablePublishSelector<>(this, selector)); } @@ -10857,7 +10953,7 @@ public final Observable publish(@NonNull Function, * {@code Observable} into the same function, and so on until all items have been emitted by the current and finite {@code Observable}, * and emits the final result from the final call to your function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate," "fold," "accumulate," * "compress," or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -10893,7 +10989,7 @@ public final Maybe reduce(@NonNull BiFunction reducer) { * emitted by the current {@code Observable} into the same function, and so on until all items have been emitted by the * current and finite {@code Observable}, emitting the final result from the final call to your function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate," "fold," "accumulate," * "compress," or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -10953,7 +11049,7 @@ public final Maybe reduce(@NonNull BiFunction reducer) { * and so on until all items have been emitted by the current and finite {@code Observable}, emitting the final result * from the final call to your function as its sole item. *

- * + * *

* This technique, which is called "reduce" here, is sometimes called "aggregate," "fold," "accumulate," * "compress," or "inject" in other programming contexts. Groovy, for instance, has an {@code inject} method @@ -11072,7 +11168,7 @@ public final Observable repeatUntil(@NonNull BooleanSupplier stop) { * call {@code onComplete} or {@code onError} on the child subscription. Otherwise, the current {@code Observable} * will be resubscribed. *

- * + * *

*
Scheduler:
*
{@code repeatWhen} does not operate by default on a particular {@link Scheduler}.
@@ -11098,7 +11194,7 @@ public final Observable repeatWhen(@NonNull Function - * + * *
*
Scheduler:
*
This version of {@code replay} does not operate by default on a particular {@link Scheduler}.
@@ -11136,7 +11232,7 @@ public final ConnectableObservable replay() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector) { Objects.requireNonNull(selector, "selector is null"); return ObservableReplay.multicastSelector(ObservableInternalHelper.replaySupplier(this), selector); } @@ -11171,7 +11267,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return ObservableReplay.multicastSelector(ObservableInternalHelper.replaySupplier(this, bufferSize, false), selector); @@ -11209,7 +11305,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, boolean eagerTruncate) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return ObservableReplay.multicastSelector(ObservableInternalHelper.replaySupplier(this, bufferSize, eagerTruncate), selector); @@ -11248,7 +11344,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit) { return replay(selector, bufferSize, time, unit, Schedulers.computation()); } @@ -11290,7 +11386,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); Objects.requireNonNull(unit, "unit is null"); @@ -11338,7 +11434,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, int bufferSize, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); Objects.requireNonNull(unit, "unit is null"); @@ -11374,7 +11470,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit) { return replay(selector, time, unit, Schedulers.computation()); } @@ -11408,7 +11504,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -11447,7 +11543,7 @@ public final Observable replay(@NonNull Function, ? @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { + public final <@NonNull R> Observable replay(@NonNull Function, ? extends ObservableSource> selector, long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean eagerTruncate) { Objects.requireNonNull(selector, "selector is null"); Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); @@ -11460,7 +11556,7 @@ public final Observable replay(@NonNull Function, ? * an ordinary {@code Observable}, except that it does not begin emitting items when it is subscribed to, but only * when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -11492,7 +11588,7 @@ public final ConnectableObservable replay(int bufferSize) { * an ordinary {@code Observable}, except that it does not begin emitting items when it is subscribed to, but only * when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -11525,7 +11621,7 @@ public final ConnectableObservable replay(int bufferSize, boolean eagerTrunca * {@code Observable} resembles an ordinary {@code Observable}, except that it does not begin emitting items when it is * subscribed to, but only when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -11566,7 +11662,7 @@ public final ConnectableObservable replay(int bufferSize, long time, @NonNull * To ensure no out-of-date or beyond-bufferSize items are referenced, * use the {@link #replay(int, long, TimeUnit, Scheduler, boolean)} overload with {@code eagerTruncate = true}. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -11603,7 +11699,7 @@ public final ConnectableObservable replay(int bufferSize, long time, @NonNull * connectable {@code Observable} resembles an ordinary {@code Observable}, except that it does not begin emitting items * when it is subscribed to, but only when its {@code connect} method is called. *

- * + * *

* Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. @@ -11647,7 +11743,7 @@ public final ConnectableObservable replay(int bufferSize, long time, @NonNull * resembles an ordinary {@code Observable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

*
Scheduler:
*
This version of {@code replay} operates by default on the {@code computation} {@link Scheduler}.
@@ -11674,7 +11770,7 @@ public final ConnectableObservable replay(long time, @NonNull TimeUnit unit) * resembles an ordinary {@code Observable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

* Note that the internal buffer may retain strong references to the oldest item. To ensure no out-of-date items * are referenced, use the {@link #replay(long, TimeUnit, Scheduler, boolean)} overload with {@code eagerTruncate = true}. @@ -11709,7 +11805,7 @@ public final ConnectableObservable replay(long time, @NonNull TimeUnit unit, * resembles an ordinary {@code Observable}, except that it does not begin emitting items when it is subscribed to, * but only when its {@code connect} method is called. *

- * + * *

* Note that the internal buffer may retain strong references to the oldest item. To ensure no out-of-date items * are referenced, set {@code eagerTruncate = true}. @@ -11744,7 +11840,7 @@ public final ConnectableObservable replay(long time, @NonNull TimeUnit unit, * Returns an {@code Observable} that mirrors the current {@code Observable}, resubscribing to it if it calls {@code onError} * (infinite retry count). *

- * + * *

* If the current {@code Observable} calls {@link Observer#onError}, this method will resubscribe to the current * {@code Observable} rather than propagating the {@code onError} call. @@ -11799,7 +11895,7 @@ public final Observable retry(@NonNull BiPredicate - * + * *

* If the current {@code Observable} calls {@link Observer#onError}, this method will resubscribe to the current * {@code Observable} for a maximum of {@code count} resubscriptions rather than propagating the @@ -11901,7 +11997,7 @@ public final Observable retryUntil(@NonNull BooleanSupplier stop) { * {@code onComplete} or {@code onError} on the child subscription. Otherwise, the current {@code Observable} * will be resubscribed. *

- * + * *

* Example: * @@ -11989,7 +12085,6 @@ public final Observable retryWhen( * @throws NullPointerException if {@code observer} is {@code null} */ @SchedulerSupport(SchedulerSupport.NONE) - @NonNull public final void safeSubscribe(@NonNull Observer observer) { Objects.requireNonNull(observer, "observer is null"); if (observer instanceof SafeObserver) { @@ -12003,7 +12098,7 @@ public final void safeSubscribe(@NonNull Observer observer) { * Returns an {@code Observable} that emits the most recently emitted item (if any) emitted by the current {@code Observable} * within periodic time intervals. *

- * + * *

*
Scheduler:
*
{@code sample} operates by default on the {@code computation} {@link Scheduler}.
@@ -12061,7 +12156,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit, boolean e * Returns an {@code Observable} that emits the most recently emitted item (if any) emitted by the current {@code Observable} * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -12084,7 +12179,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit, boolean e public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableSampleTimed<>(this, period, unit, scheduler, false)); + return RxJavaPlugins.onAssembly(new ObservableSampleTimed<>(this, period, unit, scheduler, false, null)); } /** @@ -12121,7 +12216,46 @@ public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableSampleTimed<>(this, period, unit, scheduler, emitLast)); + return RxJavaPlugins.onAssembly(new ObservableSampleTimed<>(this, period, unit, scheduler, emitLast, null)); + } + + /** + * Returns an {@code Observable} that emits the most recently emitted item (if any) emitted by the current {@code Observable} + * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler}. + *

+ * + *

+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param period + * the sampling rate + * @param unit + * the {@link TimeUnit} in which {@code period} is defined + * @param scheduler + * the {@code Scheduler} to use when sampling + * @param emitLast + * if {@code true} and the upstream completes while there is still an unsampled item available, + * that item is emitted to downstream before completion + * if {@code false}, an unsampled last item is ignored. + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @see #throttleLast(long, TimeUnit, Scheduler) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new ObservableSampleTimed<>(this, period, unit, scheduler, emitLast, onDropped)); } /** @@ -12145,7 +12279,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable sample(@NonNull ObservableSource sampler) { + public final <@NonNull U> Observable sample(@NonNull ObservableSource sampler) { Objects.requireNonNull(sampler, "sampler is null"); return RxJavaPlugins.onAssembly(new ObservableSampleWithObservable<>(this, sampler, false)); } @@ -12178,18 +12312,17 @@ public final Observable sample(@NonNull ObservableSource sampler) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable sample(@NonNull ObservableSource sampler, boolean emitLast) { + public final <@NonNull U> Observable sample(@NonNull ObservableSource sampler, boolean emitLast) { Objects.requireNonNull(sampler, "sampler is null"); return RxJavaPlugins.onAssembly(new ObservableSampleWithObservable<>(this, sampler, emitLast)); } /** - * Returns an {@code Observable} that applies a specified accumulator function to the first item emitted by the current - * {@code Observable}, then feeds the result of that function along with the second item emitted by the current - * {@code Observable} into the same function, and so on until all items have been emitted by the current {@code Observable}, - * emitting the result of each of these iterations. + * Returns an {@code Observable} that emits the first value emitted by the current {@code Observable}, then emits one value + * for each subsequent value emitted by the current {@code Observable}. Each emission after the first is the result of + * applying the specified accumulator function to the previous emission and the corresponding value from the current {@code Observable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -12214,12 +12347,11 @@ public final Observable scan(@NonNull BiFunction accumulator) { } /** - * Returns an {@code Observable} that applies a specified accumulator function to the first item emitted by the current - * {@code Observable} and a seed value, then feeds the result of that function along with the second item emitted by - * the current {@code Observable} into the same function, and so on until all items have been emitted by the current - * {@code Observable}, emitting the result of each of these iterations. + * Returns an {@code Observable} that emits the provided initial (seed) value, then emits one value for each value emitted + * by the current {@code Observable}. Each emission after the first is the result of applying the specified accumulator + * function to the previous emission and the corresponding value from the current {@code Observable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -12258,18 +12390,17 @@ public final Observable scan(@NonNull BiFunction accumulator) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable scan(@NonNull R initialValue, @NonNull BiFunction accumulator) { + public final <@NonNull R> Observable scan(@NonNull R initialValue, @NonNull BiFunction accumulator) { Objects.requireNonNull(initialValue, "initialValue is null"); return scanWith(Functions.justSupplier(initialValue), accumulator); } /** - * Returns an {@code Observable} that applies a specified accumulator function to the first item emitted by the current - * {@code Observable} and a seed value, then feeds the result of that function along with the second item emitted by - * the current {@code Observable} into the same function, and so on until all items have been emitted by the current - * {@code Observable}, emitting the result of each of these iterations. + * Returns an {@code Observable} that emits the provided initial (seed) value, then emits one value for each value emitted + * by the current {@code Observable}. Each emission after the first is the result of applying the specified accumulator + * function to the previous emission and the corresponding value from the current {@code Observable}. *

- * + * *

* This sort of function is sometimes called an accumulator. *

@@ -12294,7 +12425,7 @@ public final Observable scan(@NonNull R initialValue, @NonNull BiFunction @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable scanWith(@NonNull Supplier seedSupplier, @NonNull BiFunction accumulator) { + public final <@NonNull R> Observable scanWith(@NonNull Supplier seedSupplier, @NonNull BiFunction accumulator) { Objects.requireNonNull(seedSupplier, "seedSupplier is null"); Objects.requireNonNull(accumulator, "accumulator is null"); return RxJavaPlugins.onAssembly(new ObservableScanSeed<>(this, seedSupplier, accumulator)); @@ -12310,7 +12441,7 @@ public final Observable scanWith(@NonNull Supplier seedSupplier, @NonN * {@code onNext} from two different threads concurrently. You can force such an {@code Observable} to be * well-behaved and sequential by applying the {@code serialize} method to it. *

- * + * *

*
Scheduler:
*
{@code serialize} does not operate by default on a particular {@link Scheduler}.
@@ -12333,7 +12464,7 @@ public final Observable serialize() { *

* This is an alias for {@link #publish()}.{@link ConnectableObservable#refCount() refCount()}. *

- * + * *

*
Scheduler:
*
{@code share} does not operate by default on a particular {@link Scheduler}.
@@ -12354,7 +12485,7 @@ public final Observable share() { * emitted by the current {@code Observable}, or signals an {@link IllegalArgumentException} if the current * {@code Observable} emits more than one item. *

- * + * *

*
Scheduler:
*
{@code singleElement} does not operate by default on a particular {@link Scheduler}.
@@ -12375,7 +12506,7 @@ public final Maybe singleElement() { * emits only a single item, or a default item if the current {@code Observable} emits no items. If the current * {@code Observable} emits more than one item, an {@link IllegalArgumentException} is signaled instead. *

- * + * *

*
Scheduler:
*
{@code single} does not operate by default on a particular {@link Scheduler}.
@@ -12421,7 +12552,7 @@ public final Single singleOrError() { * Returns an {@code Observable} that skips the first {@code count} items emitted by the current {@code Observable} and emits * the remainder. *

- * + * *

*
Scheduler:
*
This version of {@code skip} does not operate by default on a particular {@link Scheduler}.
@@ -12450,7 +12581,7 @@ public final Observable skip(long count) { * Returns an {@code Observable} that skips values emitted by the current {@code Observable} before a specified time window * elapses. *

- * + * *

*
Scheduler:
*
{@code skip} does not operate on any particular scheduler but uses the current time @@ -12476,7 +12607,7 @@ public final Observable skip(long time, @NonNull TimeUnit unit) { * Returns an {@code Observable} that skips values emitted by the current {@code Observable} before a specified time window * on a specified {@link Scheduler} elapses. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use for the timed skipping
@@ -12503,7 +12634,7 @@ public final Observable skip(long time, @NonNull TimeUnit unit, @NonNull Sche * Returns an {@code Observable} that drops a specified number of items from the end of the sequence emitted by the * current {@code Observable}. *

- * + * *

* This {@link Observer} accumulates a queue long enough to store the first {@code count} items. As more items are * received, items are taken from the front of the queue and emitted by the returned {@code Observable}. This causes @@ -12537,7 +12668,7 @@ public final Observable skipLast(int count) { * Returns an {@code Observable} that drops items emitted by the current {@code Observable} during a specified time window * before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -12565,7 +12696,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit) { * Returns an {@code Observable} that drops items emitted by the current {@code Observable} during a specified time window * before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -12596,7 +12727,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit, boolean d * Returns an {@code Observable} that drops items emitted by the current {@code Observable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -12625,7 +12756,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit, @NonNull * Returns an {@code Observable} that drops items emitted by the current {@code Observable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -12657,7 +12788,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit, @NonNull * Returns an {@code Observable} that drops items emitted by the current {@code Observable} during a specified time window * (defined on a specified scheduler) before the source completes. *

- * + * *

* Note: this action will cache the latest items arriving in the specified time window. *

@@ -12697,7 +12828,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit, @NonNull * Returns an {@code Observable} that skips items emitted by the current {@code Observable} until a second {@link ObservableSource} emits * an item. *

- * + * *

*
Scheduler:
*
{@code skipUntil} does not operate by default on a particular {@link Scheduler}.
@@ -12714,7 +12845,7 @@ public final Observable skipLast(long time, @NonNull TimeUnit unit, @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable skipUntil(@NonNull ObservableSource other) { + public final <@NonNull U> Observable skipUntil(@NonNull ObservableSource other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new ObservableSkipUntil<>(this, other)); } @@ -12723,7 +12854,7 @@ public final Observable skipUntil(@NonNull ObservableSource other) { * Returns an {@code Observable} that skips all items emitted by the current {@code Observable} as long as a specified * condition holds {@code true}, but emits all further source items as soon as the condition becomes {@code false}. *

- * + * *

*
Scheduler:
*
{@code skipWhile} does not operate by default on a particular {@link Scheduler}.
@@ -12800,7 +12931,7 @@ public final Observable sorted(@NonNull Comparator comparator) { * Returns an {@code Observable} that emits the items in a specified {@link Iterable} before it begins to emit items * emitted by the current {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code startWithIterable} does not operate by default on a particular {@link Scheduler}.
@@ -12818,7 +12949,7 @@ public final Observable sorted(@NonNull Comparator comparator) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable startWithIterable(@NonNull Iterable<@NonNull ? extends T> items) { + public final Observable startWithIterable(@NonNull Iterable items) { return concatArray(fromIterable(items), this); } @@ -12892,7 +13023,7 @@ public final Observable startWith(@NonNull MaybeSource other) { * Returns an {@code Observable} that emits the items in a specified {@link ObservableSource} before it begins to emit * items emitted by the current {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code startWith} does not operate by default on a particular {@link Scheduler}.
@@ -12942,7 +13073,7 @@ public final Observable startWithItem(@NonNull T item) { * Returns an {@code Observable} that emits the specified items before it begins to emit items emitted by the current * {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code startWithArray} does not operate by default on a particular {@link Scheduler}.
@@ -12981,6 +13112,7 @@ public final Observable startWithArray(@NonNull T... items) { * * @return the new {@link Disposable} instance that can be used to dispose the subscription at any time * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @SchedulerSupport(SchedulerSupport.NONE) @NonNull @@ -13005,6 +13137,7 @@ public final Disposable subscribe() { * @throws NullPointerException * if {@code onNext} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -13027,9 +13160,10 @@ public final Disposable subscribe(@NonNull Consumer onNext) { * the {@code Consumer} you have designed to accept any error notification from the current * {@code Observable} * @return the new {@link Disposable} instance that can be used to dispose the subscription at any time - * @see ReactiveX operators documentation: Subscribe * @throws NullPointerException * if {@code onNext} or {@code onError} is {@code null} + * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -13058,6 +13192,7 @@ public final Disposable subscribe(@NonNull Consumer onNext, @NonNull * @throws NullPointerException * if {@code onNext}, {@code onError} or {@code onComplete} is {@code null} * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, Action, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -13075,6 +13210,47 @@ public final Disposable subscribe(@NonNull Consumer onNext, @NonNull return ls; } + /** + * Wraps the given onXXX callbacks into a {@link Disposable} {@link Observer}, + * adds it to the given {@code DisposableContainer} and ensures, that if the upstream + * terminates or this particular {@code Disposable} is disposed, the {@code Observer} is removed + * from the given container. + *

+ * The {@code Observer} will be removed after the callback for the terminal event has been invoked. + *

+ *
Scheduler:
+ *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param onNext the callback for upstream items + * @param onError the callback for an upstream error if any + * @param onComplete the callback for the upstream completion if any + * @param container the {@code DisposableContainer} (such as {@link CompositeDisposable}) to add and remove the + * created {@code Disposable} {@code Observer} + * @return the {@code Disposable} that allows disposing the particular subscription. + * @throws NullPointerException + * if {@code onNext}, {@code onError}, + * {@code onComplete} or {@code container} is {@code null} + * @since 3.1.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Disposable subscribe( + @NonNull Consumer onNext, + @NonNull Consumer onError, + @NonNull Action onComplete, + @NonNull DisposableContainer container) { + Objects.requireNonNull(onNext, "onNext is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(onComplete, "onComplete is null"); + Objects.requireNonNull(container, "container is null"); + + DisposableAutoReleaseObserver observer = new DisposableAutoReleaseObserver<>( + container, onNext, onError, onComplete); + container.add(observer); + subscribe(observer); + return observer; + } + @SchedulerSupport(SchedulerSupport.NONE) @Override public final void subscribe(@NonNull Observer observer) { @@ -13144,7 +13320,7 @@ public final void subscribe(@NonNull Observer observer) { /** * Asynchronously subscribes {@link Observer}s to the current {@code Observable} on the specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -13198,7 +13374,7 @@ public final Observable switchIfEmpty(@NonNull ObservableSource * The resulting {@code Observable} completes if both the current {@code Observable} and the last inner {@code ObservableSource}, if any, complete. * If the current {@code Observable} signals an {@code onError}, the inner {@code ObservableSource} is disposed and the error delivered in-sequence. *

- * + * *

*
Scheduler:
*
{@code switchMap} does not operate by default on a particular {@link Scheduler}.
@@ -13216,7 +13392,7 @@ public final Observable switchIfEmpty(@NonNull ObservableSource @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable switchMap(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMap(@NonNull Function> mapper) { return switchMap(mapper, bufferSize()); } @@ -13228,7 +13404,7 @@ public final Observable switchMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code switchMap} does not operate by default on a particular {@link Scheduler}.
@@ -13249,7 +13425,7 @@ public final Observable switchMap(@NonNull Function Observable switchMap(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Observable switchMap(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); if (this instanceof ScalarSupplier) { @@ -13383,7 +13559,7 @@ public final Completable switchMapCompletableDelayError(@NonNull Function Observable switchMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMapMaybe(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableSwitchMapMaybe<>(this, mapper, false)); } @@ -13411,7 +13587,7 @@ public final Observable switchMapMaybe(@NonNull Function Observable switchMapMaybeDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMapMaybeDelayError(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableSwitchMapMaybe<>(this, mapper, true)); } @@ -13443,7 +13619,7 @@ public final Observable switchMapMaybeDelayError(@NonNull Function Observable switchMapSingle(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMapSingle(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableSwitchMapSingle<>(this, mapper, false)); } @@ -13476,7 +13652,7 @@ public final Observable switchMapSingle(@NonNull Function Observable switchMapSingleDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMapSingleDelayError(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableSwitchMapSingle<>(this, mapper, true)); } @@ -13490,7 +13666,7 @@ public final Observable switchMapSingleDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code switchMapDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -13509,7 +13685,7 @@ public final Observable switchMapSingleDelayError(@NonNull Function Observable switchMapDelayError(@NonNull Function> mapper) { + public final <@NonNull R> Observable switchMapDelayError(@NonNull Function> mapper) { return switchMapDelayError(mapper, bufferSize()); } @@ -13522,7 +13698,7 @@ public final Observable switchMapDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code switchMapDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -13544,7 +13720,7 @@ public final Observable switchMapDelayError(@NonNull Function Observable switchMapDelayError(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull R> Observable switchMapDelayError(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); if (this instanceof ScalarSupplier) { @@ -13562,7 +13738,7 @@ public final Observable switchMapDelayError(@NonNull Function - * + * *

* This method returns an {@code Observable} that will invoke a subscribing {@link Observer}'s * {@link Observer#onNext onNext} function a maximum of {@code count} times before invoking @@ -13599,7 +13775,7 @@ public final Observable take(long count) { * If time runs out before the {@code Observable} completes normally, the {@code onComplete} event will be * signaled on the default {@code computation} {@link Scheduler}. *

- * + * *

*
Scheduler:
*
This version of {@code take} operates by default on the {@code computation} {@code Scheduler}.
@@ -13627,7 +13803,7 @@ public final Observable take(long time, @NonNull TimeUnit unit) { * If time runs out before the {@code Observable} completes normally, the {@code onComplete} event will be * signaled on the provided {@code Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -13654,7 +13830,7 @@ public final Observable take(long time, @NonNull TimeUnit unit, @NonNull Sche * Returns an {@code Observable} that emits at most the last {@code count} items emitted by the current {@code Observable}. * If the source emits fewer than {@code count} items then all of its items are emitted. *

- * + * *

*
Scheduler:
*
This version of {@code takeLast} does not operate by default on a particular {@link Scheduler}.
@@ -13688,7 +13864,7 @@ public final Observable takeLast(int count) { * Returns an {@code Observable} that emits at most a specified number of items from the current {@code Observable} that were * emitted in a specified window of time before the current {@code Observable} completed. *

- * + * *

*
Scheduler:
*
{@code takeLast} does not operate on any particular scheduler but uses the current time @@ -13718,7 +13894,7 @@ public final Observable takeLast(long count, long time, @NonNull TimeUnit uni * emitted in a specified window of time before the current {@code Observable} completed, where the timing information is * provided by a given {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use for tracking the current time
@@ -13750,7 +13926,7 @@ public final Observable takeLast(long count, long time, @NonNull TimeUnit uni * emitted in a specified window of time before the current {@code Observable} completed, where the timing information is * provided by a given {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use for tracking the current time
@@ -13792,7 +13968,7 @@ public final Observable takeLast(long count, long time, @NonNull TimeUnit uni * Returns an {@code Observable} that emits the items from the current {@code Observable} that were emitted in a specified * window of time before the current {@code Observable} completed. *

- * + * *

*
Scheduler:
*
{@code takeLast} does not operate on any particular scheduler but uses the current time @@ -13818,7 +13994,7 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit) { * Returns an {@code Observable} that emits the items from the current {@code Observable} that were emitted in a specified * window of time before the current {@code Observable} completed. *

- * + * *

*
Scheduler:
*
{@code takeLast} does not operate on any particular scheduler but uses the current time @@ -13849,7 +14025,7 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit, boolean d * window of time before the current {@code Observable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -13877,7 +14053,7 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit, @NonNull * window of time before the current {@code Observable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -13908,7 +14084,7 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit, @NonNull * window of time before the current {@code Observable} completed, where the timing information is provided by a specified * {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -13939,16 +14115,16 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit, @NonNull /** * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} until a second {@link ObservableSource} - * emits an item. + * emits an item or completes. *

- * + * *

*
Scheduler:
*
{@code takeUntil} does not operate by default on a particular {@link Scheduler}.
*
* * @param other - * the {@code ObservableSource} whose first emitted item will cause {@code takeUntil} to stop emitting items + * the {@code ObservableSource} whose first emitted item or completion will cause {@code takeUntil} to stop emitting items * from the current {@code Observable} * @param * the type of items emitted by {@code other} @@ -13959,7 +14135,7 @@ public final Observable takeLast(long time, @NonNull TimeUnit unit, @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable takeUntil(@NonNull ObservableSource other) { + public final <@NonNull U> Observable takeUntil(@NonNull ObservableSource other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new ObservableTakeUntil<>(this, other)); } @@ -13968,7 +14144,7 @@ public final Observable takeUntil(@NonNull ObservableSource other) { * Returns an {@code Observable} that emits items emitted by the current {@code Observable}, checks the specified predicate * for each item, and then completes when the condition is satisfied. *

- * + * *

* The difference between this operator and {@link #takeWhile(Predicate)} is that here, the condition is * evaluated after the item is emitted. @@ -13998,7 +14174,7 @@ public final Observable takeUntil(@NonNull Predicate stopPredicate * Returns an {@code Observable} that emits items emitted by the current {@code Observable} so long as each item satisfied a * specified condition, and then completes as soon as this condition is not satisfied. *

- * + * *

*
Scheduler:
*
{@code takeWhile} does not operate by default on a particular {@link Scheduler}.
@@ -14026,7 +14202,7 @@ public final Observable takeWhile(@NonNull Predicate predicate) { * This differs from {@link #throttleLast} in that this only tracks passage of time whereas * {@code throttleLast} ticks at scheduled intervals. *

- * + * *

*
Scheduler:
*
{@code throttleFirst} operates by default on the {@code computation} {@link Scheduler}.
@@ -14054,7 +14230,7 @@ public final Observable throttleFirst(long windowDuration, @NonNull TimeUnit * This differs from {@link #throttleLast} in that this only tracks passage of time whereas * {@code throttleLast} ticks at scheduled intervals. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -14077,7 +14253,46 @@ public final Observable throttleFirst(long windowDuration, @NonNull TimeUnit public final Observable throttleFirst(long skipDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableThrottleFirstTimed<>(this, skipDuration, unit, scheduler)); + return RxJavaPlugins.onAssembly(new ObservableThrottleFirstTimed<>(this, skipDuration, unit, scheduler, null)); + } + + /** + * Returns an {@code Observable} that emits only the first item emitted by the current {@code Observable} during sequential + * time windows of a specified duration, where the windows are managed by a specified {@link Scheduler}. + *

+ * This differs from {@link #throttleLast} in that this only tracks passage of time whereas + * {@code throttleLast} ticks at scheduled intervals. + *

+ * + *

+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param skipDuration + * time to wait before emitting another item after emitting the last item + * @param unit + * the unit of time of {@code skipDuration} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle timeout for each + * event + * @param onDropped + * called when an item doesn't get delivered to the downstream + * + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable throttleFirst(long skipDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new ObservableThrottleFirstTimed<>(this, skipDuration, unit, scheduler, onDropped)); } /** @@ -14087,7 +14302,7 @@ public final Observable throttleFirst(long skipDuration, @NonNull TimeUnit un * This differs from {@link #throttleFirst} in that this ticks along at a scheduled interval whereas * {@code throttleFirst} does not tick, it just tracks passage of time. *

- * + * *

*
Scheduler:
*
{@code throttleLast} operates by default on the {@code computation} {@link Scheduler}.
@@ -14117,7 +14332,44 @@ public final Observable throttleLast(long intervalDuration, @NonNull TimeUnit * This differs from {@link #throttleFirst} in that this ticks along at a scheduled interval whereas * {@code throttleFirst} does not tick, it just tracks passage of time. *

- * + * + *

+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param intervalDuration + * duration of windows within which the last item emitted by the current {@code Observable} will be + * emitted + * @param unit + * the unit of time of {@code intervalDuration} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle timeout for each + * event + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Sample + * @see #sample(long, TimeUnit, Scheduler) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable throttleLast(long intervalDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + return sample(intervalDuration, unit, scheduler, false, onDropped); + } + + /** + * Returns an {@code Observable} that emits only the last item emitted by the current {@code Observable} during sequential + * time windows of a specified duration, where the duration is governed by a specified {@link Scheduler}. + *

+ * This differs from {@link #throttleFirst} in that this ticks along at a scheduled interval whereas + * {@code throttleFirst} does not tick, it just tracks passage of time. + *

+ * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -14276,7 +14528,55 @@ public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableThrottleLatest<>(this, timeout, unit, scheduler, emitLast)); + return RxJavaPlugins.onAssembly(new ObservableThrottleLatest<>(this, timeout, unit, scheduler, emitLast, null)); + } + + /** + * Throttles items from the current {@code Observable} by first emitting the next + * item from upstream, then periodically emitting the latest item (if any) when + * the specified timeout elapses between them, invoking the consumer for any dropped item. + *

+ * + *

+ * If no items were emitted from the upstream during this timeout phase, the next + * upstream item is emitted immediately and the timeout window starts from then. + *

+ *
Scheduler:
+ *
You specify which {@link Scheduler} this operator will use.
+ *
Error handling:
+ *
+ * If the upstream signals an {@code onError} or {@code onDropped} callback crashes, + * the error is delivered immediately to the downstream. If both happen, a {@link CompositeException} + * is created, containing both the upstream and the callback error. + * If the {@code onDropped} callback crashes when the sequence gets disposed, the exception is forwarded + * to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + *
+ *
+ * @param timeout the time to wait after an item emission towards the downstream + * before trying to emit the latest item from upstream again + * @param unit the time unit + * @param scheduler the {@code Scheduler} where the timed wait and latest item + * emission will be performed + * @param emitLast If {@code true}, the very last item from the upstream will be emitted + * immediately when the upstream completes, regardless if there is + * a timeout window active or not. If {@code false}, the very last + * upstream item is ignored and the flow terminates. + * @param onDropped called when an item is replaced by a newer item that doesn't get delivered + * to the downstream, including the very last item if {@code emitLast} is {@code false} + * and the current undelivered item when the sequence gets disposed. + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code onDropped} is {@code null} + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean emitLast, @NonNull Consumer onDropped) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + Objects.requireNonNull(onDropped, "onDropped is null"); + return RxJavaPlugins.onAssembly(new ObservableThrottleLatest<>(this, timeout, unit, scheduler, emitLast, onDropped)); } /** @@ -14287,7 +14587,7 @@ public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, * Note: If items keep being emitted by the current {@code Observable} faster than the timeout then no items * will be emitted by the resulting {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code throttleWithTimeout} operates by default on the {@code computation} {@link Scheduler}.
@@ -14319,7 +14619,7 @@ public final Observable throttleWithTimeout(long timeout, @NonNull TimeUnit u * Note: If items keep being emitted by the current {@code Observable} faster than the timeout then no items * will be emitted by the resulting {@code Observable}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -14346,11 +14646,50 @@ public final Observable throttleWithTimeout(long timeout, @NonNull TimeUnit u return debounce(timeout, unit, scheduler); } + /** + * Returns an {@code Observable} that mirrors the current {@code Observable}, except that it drops items emitted by the + * current {@code Observable} that are followed by newer items before a timeout value expires on a specified + * {@link Scheduler}. The timer resets on each emission (Alias to {@link #debounce(long, TimeUnit, Scheduler)}). + *

+ * Note: If items keep being emitted by the current {@code Observable} faster than the timeout then no items + * will be emitted by the resulting {@code Observable}. + *

+ * + *

+ *
Scheduler:
+ *
You specify which {@code Scheduler} this operator will use.
+ *
+ * + * @param timeout + * the length of the window of time that must pass after the emission of an item from the current + * {@code Observable}, in which the current {@code Observable} emits no items, in order for the item to be emitted by the + * resulting {@code Observable} + * @param unit + * the unit of time for the specified {@code timeout} + * @param scheduler + * the {@code Scheduler} to use internally to manage the timers that handle the timeout for each + * item + * @param onDropped + * called with the current entry when it has been replaced by a new one + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} or {@code onDropped} is {@code null} + * @see ReactiveX operators documentation: Debounce + * @see #debounce(long, TimeUnit, Scheduler, Consumer) + * @since 3.1.6 - Experimental + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + @Experimental + public final Observable throttleWithTimeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Consumer onDropped) { + return debounce(timeout, unit, scheduler, onDropped); + } + /** * Returns an {@code Observable} that emits records of the time interval between consecutive items emitted by the * current {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code timeInterval} does not operate on any particular scheduler but uses the current time @@ -14371,7 +14710,7 @@ public final Observable> timeInterval() { * Returns an {@code Observable} that emits records of the time interval between consecutive items emitted by the * current {@code Observable}, where this interval is computed on a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
The operator does not operate on any particular scheduler but uses the current time @@ -14395,7 +14734,7 @@ public final Observable> timeInterval(@NonNull Scheduler scheduler) { * Returns an {@code Observable} that emits records of the time interval between consecutive items emitted by the * current {@code Observable}. *

- * + * *

*
Scheduler:
*
{@code timeInterval} does not operate on any particular scheduler but uses the current time @@ -14418,7 +14757,7 @@ public final Observable> timeInterval(@NonNull TimeUnit unit) { * Returns an {@code Observable} that emits records of the time interval between consecutive items emitted by the * current {@code Observable}, where this interval is computed on a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
The operator does not operate on any particular scheduler but uses the current time @@ -14447,7 +14786,7 @@ public final Observable> timeInterval(@NonNull TimeUnit unit, @NonNull * time after the emission of the previous item, where that period of time is measured by an {@link ObservableSource} that * is a function of the previous item. *

- * + * *

* Note: The arrival of the first source item is never timed out. *

@@ -14467,7 +14806,7 @@ public final Observable> timeInterval(@NonNull TimeUnit unit, @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable timeout(@NonNull Function> itemTimeoutIndicator) { + public final <@NonNull V> Observable timeout(@NonNull Function> itemTimeoutIndicator) { return timeout0(null, itemTimeoutIndicator, null); } @@ -14477,7 +14816,7 @@ public final Observable timeout(@NonNull Function - * + * *

* Note: The arrival of the first source item is never timed out. *

@@ -14499,7 +14838,7 @@ public final Observable timeout(@NonNull Function Observable timeout(@NonNull Function> itemTimeoutIndicator, + public final <@NonNull V> Observable timeout(@NonNull Function> itemTimeoutIndicator, @NonNull ObservableSource fallback) { Objects.requireNonNull(fallback, "fallback is null"); return timeout0(null, itemTimeoutIndicator, fallback); @@ -14510,7 +14849,7 @@ public final Observable timeout(@NonNull Function - * + * *
*
Scheduler:
*
This version of {@code timeout} operates by default on the {@code computation} {@link Scheduler}.
@@ -14537,7 +14876,7 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit) { * the current {@code Observable} is disposed and the resulting {@code Observable} begins instead * to mirror a fallback {@link ObservableSource}. *

- * + * *

*
Scheduler:
*
This version of {@code timeout} operates by default on the {@code computation} {@link Scheduler}.
@@ -14567,7 +14906,7 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNul * starting from its predecessor, the current {@code Observable} is disposed and returned {@code Observable} * begins instead to mirror a fallback {@link ObservableSource}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -14599,7 +14938,7 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNul * specified timeout duration starting from its predecessor, the resulting {@code Observable} terminates and * notifies observers of a {@link TimeoutException}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -14627,7 +14966,7 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNul * {@link TimeoutException} if either the first item emitted by the current {@code Observable} or any subsequent item * doesn't arrive within time windows defined by indicator {@link ObservableSource}s. *

- * + * *

*
Scheduler:
*
This version of {@code timeout} operates by default on the {@code immediate} {@link Scheduler}.
@@ -14651,7 +14990,7 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNul @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable timeout(@NonNull ObservableSource firstTimeoutIndicator, + public final <@NonNull U, @NonNull V> Observable timeout(@NonNull ObservableSource firstTimeoutIndicator, @NonNull Function> itemTimeoutIndicator) { Objects.requireNonNull(firstTimeoutIndicator, "firstTimeoutIndicator is null"); return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, null); @@ -14662,7 +15001,7 @@ public final Observable timeout(@NonNull ObservableSource firstTime * the first item emitted by the current {@code Observable} or any subsequent item doesn't arrive within time windows * defined by indicator {@code ObservableSource}s. *

- * + * *

*
Scheduler:
*
This version of {@code timeout} operates by default on the {@code immediate} {@link Scheduler}.
@@ -14689,7 +15028,7 @@ public final Observable timeout(@NonNull ObservableSource firstTime @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable timeout( + public final <@NonNull U, @NonNull V> Observable timeout( @NonNull ObservableSource firstTimeoutIndicator, @NonNull Function> itemTimeoutIndicator, @NonNull ObservableSource fallback) { @@ -14720,7 +15059,7 @@ private Observable timeout0( * Returns an {@code Observable} that emits each item emitted by the current {@code Observable}, wrapped in a * {@link Timed} object. *

- * + * *

*
Scheduler:
*
{@code timestamp} does not operate on any particular scheduler but uses the current time @@ -14741,7 +15080,7 @@ public final Observable> timestamp() { * Returns an {@code Observable} that emits each item emitted by the current {@code Observable}, wrapped in a * {@link Timed} object whose timestamps are provided by a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
This operator does not operate on any particular scheduler but uses the current time @@ -14765,7 +15104,7 @@ public final Observable> timestamp(@NonNull Scheduler scheduler) { * Returns an {@code Observable} that emits each item emitted by the current {@code Observable}, wrapped in a * {@link Timed} object. *

- * + * *

*
Scheduler:
*
{@code timestamp} does not operate on any particular scheduler but uses the current time @@ -14788,7 +15127,7 @@ public final Observable> timestamp(@NonNull TimeUnit unit) { * Returns an {@code Observable} that emits each item emitted by the current {@code Observable}, wrapped in a * {@link Timed} object whose timestamps are provided by a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
This operator does not operate on any particular scheduler but uses the current time @@ -14829,7 +15168,7 @@ public final Observable> timestamp(@NonNull TimeUnit unit, @NonNull Sch @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final R to(@NonNull ObservableConverter converter) { + public final <@NonNull R> R to(@NonNull ObservableConverter converter) { return Objects.requireNonNull(converter, "converter is null").apply(this); } @@ -14837,7 +15176,7 @@ public final R to(@NonNull ObservableConverter converter) { * Returns a {@link Single} that emits a single item, a {@link List} composed of all the items emitted by the * current and finite {@code Observable}. *

- * + * *

* Normally, an {@link ObservableSource} that returns multiple items will do so by invoking its {@link Observer}'s * {@link Observer#onNext onNext} method for each such item. You can change this behavior by having the @@ -14867,7 +15206,7 @@ public final R to(@NonNull ObservableConverter converter) { * Returns a {@link Single} that emits a single item, a {@link List} composed of all the items emitted by the * current and finite {@code Observable}. *

- * + * *

* Normally, an {@link ObservableSource} that returns multiple items will do so by invoking its {@link Observer}'s * {@link Observer#onNext onNext} method for each such item. You can change this behavior by having the @@ -14937,7 +15276,7 @@ public final R to(@NonNull ObservableConverter converter) { * current and finite {@code Observable}, mapped by the keys returned by a specified * {@code keySelector} function. *

- * + * *

* If more than one source item maps to the same key, the {@code HashMap} will contain the latest of those items. *

@@ -14959,7 +15298,7 @@ public final R to(@NonNull ObservableConverter converter) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single<@NonNull Map> toMap(@NonNull Function keySelector) { + public final <@NonNull K> Single<@NonNull Map> toMap(@NonNull Function keySelector) { Objects.requireNonNull(keySelector, "keySelector is null"); return collect(HashMapSupplier.asSupplier(), Functions.toMapKeySelector(keySelector)); } @@ -14968,7 +15307,7 @@ public final R to(@NonNull ObservableConverter converter) { * Returns a {@link Single} that emits a single {@link HashMap} containing values corresponding to items emitted by the * current and finite {@code Observable}, mapped by the keys and values returned by the given selector functions. *

- * + * *

* If more than one source item maps to the same key, the {@code HashMap} will contain a single entry that * corresponds to the latest of those items. @@ -14994,7 +15333,7 @@ public final R to(@NonNull ObservableConverter converter) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single> toMap( + public final <@NonNull K, @NonNull V> Single> toMap( @NonNull Function keySelector, @NonNull Function valueSelector) { Objects.requireNonNull(keySelector, "keySelector is null"); @@ -15006,7 +15345,7 @@ public final Single> toMap( * Returns a {@link Single} that emits a single {@link Map} (subclass), returned by a specified {@code mapFactory} function, that * contains keys and values extracted from the items, via selector functions, emitted by the current and finite {@code Observable}. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code Map} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15031,7 +15370,7 @@ public final Single> toMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single> toMap( + public final <@NonNull K, @NonNull V> Single> toMap( @NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier> mapSupplier) { @@ -15045,7 +15384,7 @@ public final Single> toMap( * Returns a {@link Single} that emits a single {@link HashMap} that contains an {@link ArrayList} of items emitted by the * current and finite {@code Observable} keyed by a specified {@code keySelector} function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code HashMap} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15065,7 +15404,7 @@ public final Single> toMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single<@NonNull Map>> toMultimap(@NonNull Function keySelector) { + public final <@NonNull K> Single<@NonNull Map>> toMultimap(@NonNull Function keySelector) { Function valueSelector = Functions.identity(); Supplier>> mapSupplier = HashMapSupplier.asSupplier(); Function> collectionFactory = ArrayListSupplier.asFunction(); @@ -15077,7 +15416,7 @@ public final Single> toMap( * specified {@code valueSelector} function from items emitted by the current and finite {@code Observable}, * keyed by a specified {@code keySelector} function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code HashMap} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15100,7 +15439,7 @@ public final Single> toMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single<@NonNull Map>> toMultimap(@NonNull Function keySelector, Function valueSelector) { + public final <@NonNull K, @NonNull V> Single<@NonNull Map>> toMultimap(@NonNull Function keySelector, Function valueSelector) { Supplier>> mapSupplier = HashMapSupplier.asSupplier(); Function> collectionFactory = ArrayListSupplier.asFunction(); return toMultimap(keySelector, valueSelector, mapSupplier, collectionFactory); @@ -15111,7 +15450,7 @@ public final Single> toMap( * contains a custom {@link Collection} of values, extracted by a specified {@code valueSelector} function from * items emitted by the current and finite {@code Observable}, and keyed by the {@code keySelector} function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code Map} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15138,7 +15477,7 @@ public final Single> toMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single<@NonNull Map>> toMultimap( + public final <@NonNull K, @NonNull V> Single<@NonNull Map>> toMultimap( @NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier>> mapSupplier, @@ -15155,7 +15494,7 @@ public final Single> toMap( * contains an {@link ArrayList} of values, extracted by a specified {@code valueSelector} function from items * emitted by the current and finite {@code Observable} and keyed by the {@code keySelector} function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code Map} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15180,7 +15519,7 @@ public final Single> toMap( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single<@NonNull Map>> toMultimap( + public final <@NonNull K, @NonNull V> Single<@NonNull Map>> toMultimap( @NonNull Function keySelector, @NonNull Function valueSelector, @NonNull Supplier>> mapSupplier @@ -15256,7 +15595,7 @@ public final Flowable toFlowable(@NonNull BackpressureStrategy strategy) { * all other items emitted by the current {@code Observable}, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code List} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15281,7 +15620,7 @@ public final Flowable toFlowable(@NonNull BackpressureStrategy strategy) { * Returns a {@link Single} that emits a {@link List} that contains the items emitted by the current and finite {@code Observable}, in a * sorted order based on a specified comparison function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code List} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15310,7 +15649,7 @@ public final Flowable toFlowable(@NonNull BackpressureStrategy strategy) { * Returns a {@link Single} that emits a {@link List} that contains the items emitted by the current and finite {@code Observable}, in a * sorted order based on a specified comparison function. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code List} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15348,7 +15687,7 @@ public final Flowable toFlowable(@NonNull BackpressureStrategy strategy) { * all other items emitted by the current {@code Observable}, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

- * + * *

* Note that this operator requires the upstream to signal {@code onComplete} for the accumulated {@code List} to * be emitted. Sources that are infinite and never complete will never emit anything through this @@ -15403,7 +15742,7 @@ public final Observable unsubscribeOn(@NonNull Scheduler scheduler) { * {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the current window and * propagates the notification from the current {@code Observable}. *

- * + * *

*
Scheduler:
*
This version of {@code window} does not operate by default on a particular {@link Scheduler}.
@@ -15428,7 +15767,7 @@ public final Observable> window(long count) { * the current {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the current window * and propagates the notification from the current {@code Observable}. *

- * + * *

*
Scheduler:
*
This version of {@code window} does not operate by default on a particular {@link Scheduler}.
@@ -15456,7 +15795,7 @@ public final Observable> window(long count, long skip) { * the current {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the current window * and propagates the notification from the current {@code Observable}. *

- * + * *

*
Scheduler:
*
This version of {@code window} does not operate by default on a particular {@link Scheduler}.
@@ -15490,7 +15829,7 @@ public final Observable> window(long count, long skip, int bufferS * {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15526,7 +15865,7 @@ public final Observable> window(long timespan, long timeskip, @Non * {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15564,7 +15903,7 @@ public final Observable> window(long timespan, long timeskip, @Non * {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15608,7 +15947,7 @@ public final Observable> window(long timespan, long timeskip, @Non * {@code timespan} argument. When the current {@code Observable} completes or encounters an error, the resulting * {@code Observable} emits the current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15642,7 +15981,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * reached first). When the current {@code Observable} completes or encounters an error, the resulting {@code Observable} * emits the current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15680,7 +16019,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * reached first). When the current {@code Observable} completes or encounters an error, the resulting {@code Observable} * emits the current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15719,7 +16058,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * {@code timespan} argument. When the current {@code Observable} completes or encounters an error, the resulting * {@code Observable} emits the current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15756,7 +16095,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * first). When the current {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15796,7 +16135,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * first). When the current {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15838,7 +16177,7 @@ public final Observable> window(long timespan, @NonNull TimeUnit u * first). When the current {@code Observable} completes or encounters an error, the resulting {@code Observable} emits the * current window and propagates the notification from the current {@code Observable}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15885,7 +16224,7 @@ public final Observable> window( * where the boundary of each window is determined by the items emitted from a specified boundary-governing * {@link ObservableSource}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15907,7 +16246,7 @@ public final Observable> window( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window(@NonNull ObservableSource boundaryIndicator) { + public final <@NonNull B> Observable> window(@NonNull ObservableSource boundaryIndicator) { return window(boundaryIndicator, bufferSize()); } @@ -15916,7 +16255,7 @@ public final Observable> window(@NonNull ObservableSource b * where the boundary of each window is determined by the items emitted from a specified boundary-governing * {@link ObservableSource}. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15941,7 +16280,7 @@ public final Observable> window(@NonNull ObservableSource b @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window(@NonNull ObservableSource boundaryIndicator, int bufferSize) { + public final <@NonNull B> Observable> window(@NonNull ObservableSource boundaryIndicator, int bufferSize) { Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableWindowBoundary<>(this, boundaryIndicator, bufferSize)); @@ -15953,7 +16292,7 @@ public final Observable> window(@NonNull ObservableSource b * the {@code openingIndicator} {@link ObservableSource} emits an item and when the {@code ObservableSource} returned by * {@code closingIndicator} emits an item. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -15978,7 +16317,7 @@ public final Observable> window(@NonNull ObservableSource b @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window( + public final <@NonNull U, @NonNull V> Observable> window( @NonNull ObservableSource openingIndicator, @NonNull Function> closingIndicator) { return window(openingIndicator, closingIndicator, bufferSize()); @@ -15990,7 +16329,7 @@ public final Observable> window( * the {@code openingIndicator} {@link ObservableSource} emits an item and when the {@code ObservableSource} returned by * {@code closingIndicator} emits an item. *

- * + * *

* Note that ignoring windows or subscribing later (i.e., on another thread) will result in * so-called window abandonment where a window may not contain any elements. In this case, subsequent @@ -16018,7 +16357,7 @@ public final Observable> window( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window( + public final <@NonNull U, @NonNull V> Observable> window( @NonNull ObservableSource openingIndicator, @NonNull Function> closingIndicator, int bufferSize) { Objects.requireNonNull(openingIndicator, "openingIndicator is null"); @@ -16030,8 +16369,15 @@ public final Observable> window( /** * Merges the specified {@link ObservableSource} into the current {@code Observable} sequence by using the {@code resultSelector} * function only when the current {@code Observable} emits an item. + * + *

Note that this operator doesn't emit anything until the other source has produced at + * least one value. The resulting emission only happens when the current {@code Observable} emits (and + * not when the other source emits, unlike combineLatest). + * If the other source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before the other source has produced at least one value, the sequence completes + * without emission. *

- * + * * *

*
Scheduler:
@@ -16053,7 +16399,7 @@ public final Observable> window( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable withLatestFrom(@NonNull ObservableSource other, @NonNull BiFunction combiner) { + public final <@NonNull U, @NonNull R> Observable withLatestFrom(@NonNull ObservableSource other, @NonNull BiFunction combiner) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -16068,8 +16414,10 @@ public final Observable withLatestFrom(@NonNull ObservableSource - * + * *
*
Scheduler:
*
This operator does not operate by default on a particular {@link Scheduler}.
@@ -16088,7 +16436,7 @@ public final Observable withLatestFrom(@NonNull ObservableSource Observable withLatestFrom( + public final <@NonNull T1, @NonNull T2, @NonNull R> Observable withLatestFrom( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull Function3 combiner) { Objects.requireNonNull(source1, "source1 is null"); @@ -16106,8 +16454,10 @@ public final Observable withLatestFrom( * least one value. The resulting emission only happens when the current {@code Observable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. *

- * + * *

*
Scheduler:
*
This operator does not operate by default on a particular {@link Scheduler}.
@@ -16128,7 +16478,7 @@ public final Observable withLatestFrom( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable withLatestFrom( + public final <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Observable withLatestFrom( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull Function4 combiner) { @@ -16148,8 +16498,10 @@ public final Observable withLatestFrom( * least one value. The resulting emission only happens when the current {@code Observable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. *

- * + * *

*
Scheduler:
*
This operator does not operate by default on a particular {@link Scheduler}.
@@ -16173,7 +16525,7 @@ public final Observable withLatestFrom( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable withLatestFrom( + public final <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Observable withLatestFrom( @NonNull ObservableSource source1, @NonNull ObservableSource source2, @NonNull ObservableSource source3, @NonNull ObservableSource source4, @NonNull Function5 combiner) { @@ -16194,8 +16546,10 @@ public final Observable withLatestFrom( * least one value. The resulting emission only happens when the current {@code Observable} emits (and * not when any of the other sources emit, unlike combineLatest). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. *

- * + * *

*
Scheduler:
*
This operator does not operate by default on a particular {@link Scheduler}.
@@ -16211,7 +16565,7 @@ public final Observable withLatestFrom( @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable withLatestFrom(@NonNull ObservableSource[] others, @NonNull Function combiner) { + public final <@NonNull R> Observable withLatestFrom(@NonNull ObservableSource[] others, @NonNull Function combiner) { Objects.requireNonNull(others, "others is null"); Objects.requireNonNull(combiner, "combiner is null"); return RxJavaPlugins.onAssembly(new ObservableWithLatestFromMany<>(this, others, combiner)); @@ -16225,8 +16579,10 @@ public final Observable withLatestFrom(@NonNull ObservableSource[] oth * least one value. The resulting emission only happens when the current {@code Observable} emits (and * not when any of the other sources emit, unlike {@code combineLatest}). * If a source doesn't produce any value and just completes, the sequence is completed immediately. + * If the upstream completes before all other sources have produced at least one value, the sequence completes + * without emission. *

- * + * *

*
Scheduler:
*
This operator does not operate by default on a particular {@link Scheduler}.
@@ -16242,7 +16598,7 @@ public final Observable withLatestFrom(@NonNull ObservableSource[] oth @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable withLatestFrom(@NonNull Iterable<@NonNull ? extends ObservableSource> others, @NonNull Function combiner) { + public final <@NonNull R> Observable withLatestFrom(@NonNull Iterable<@NonNull ? extends ObservableSource> others, @NonNull Function combiner) { Objects.requireNonNull(others, "others is null"); Objects.requireNonNull(combiner, "combiner is null"); return RxJavaPlugins.onAssembly(new ObservableWithLatestFromMany<>(this, others, combiner)); @@ -16252,7 +16608,7 @@ public final Observable withLatestFrom(@NonNull Iterable<@NonNull ? exten * Returns an {@code Observable} that emits items that are the result of applying a specified function to pairs of * values, one each from the current {@code Observable} and a specified {@link Iterable} sequence. *

- * + * *

* Note that the {@code other} {@code Iterable} is evaluated as items are observed from the current {@code Observable}; it is * not pre-consumed. This allows you to zip infinite streams on either side. @@ -16277,7 +16633,7 @@ public final Observable withLatestFrom(@NonNull Iterable<@NonNull ? exten @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final <@NonNull U, R> Observable zipWith(@NonNull Iterable other, @NonNull BiFunction zipper) { + public final <@NonNull U, @NonNull R> Observable zipWith(@NonNull Iterable other, @NonNull BiFunction zipper) { Objects.requireNonNull(other, "other is null"); Objects.requireNonNull(zipper, "zipper is null"); return RxJavaPlugins.onAssembly(new ObservableZipIterable<>(this, other, zipper)); @@ -16287,7 +16643,7 @@ public final Observable withLatestFrom(@NonNull Iterable<@NonNull ? exten * Returns an {@code Observable} that emits items that are the result of applying a specified function to pairs of * values, one each from the current {@code Observable} and another specified {@link ObservableSource}. *

- * + * *

* The operator subscribes to its sources in order they are specified and completes eagerly if * one of the sources is shorter than the rest while disposing the other sources. Therefore, it @@ -16321,7 +16677,7 @@ public final Observable withLatestFrom(@NonNull Iterable<@NonNull ? exten @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable zipWith(@NonNull ObservableSource other, + public final <@NonNull U, @NonNull R> Observable zipWith(@NonNull ObservableSource other, @NonNull BiFunction zipper) { Objects.requireNonNull(other, "other is null"); return zip(this, other, zipper); @@ -16331,7 +16687,7 @@ public final Observable zipWith(@NonNull ObservableSource * Returns an {@code Observable} that emits items that are the result of applying a specified function to pairs of * values, one each from the current {@code Observable} and another specified {@link ObservableSource}. *

- * + * *

* The operator subscribes to its sources in order they are specified and completes eagerly if * one of the sources is shorter than the rest while disposing the other sources. Therefore, it @@ -16368,7 +16724,7 @@ public final Observable zipWith(@NonNull ObservableSource @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable zipWith(@NonNull ObservableSource other, + public final <@NonNull U, @NonNull R> Observable zipWith(@NonNull ObservableSource other, @NonNull BiFunction zipper, boolean delayError) { return zip(this, other, zipper, delayError); } @@ -16377,7 +16733,7 @@ public final Observable zipWith(@NonNull ObservableSource * Returns an {@code Observable} that emits items that are the result of applying a specified function to pairs of * values, one each from the current {@code Observable} and another specified {@link ObservableSource}. *

- * + * *

* The operator subscribes to its sources in order they are specified and completes eagerly if * one of the sources is shorter than the rest while disposing the other sources. Therefore, it @@ -16417,7 +16773,7 @@ public final Observable zipWith(@NonNull ObservableSource @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable zipWith(@NonNull ObservableSource other, + public final <@NonNull U, @NonNull R> Observable zipWith(@NonNull ObservableSource other, @NonNull BiFunction zipper, boolean delayError, int bufferSize) { return zip(this, other, zipper, delayError, bufferSize); } @@ -16499,7 +16855,7 @@ public final TestObserver test(boolean dispose) { // NoPMD @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable<@NonNull T> fromOptional(@NonNull Optional optional) { + public static <@NonNull T> Observable<@NonNull T> fromOptional(@NonNull Optional optional) { Objects.requireNonNull(optional, "optional is null"); return optional.map(Observable::just).orElseGet(Observable::empty); } @@ -16510,7 +16866,7 @@ public final TestObserver test(boolean dispose) { // NoPMD * *

* Note that the operator takes an already instantiated, running or terminated {@code CompletionStage}. - * If the optional is to be created per consumer upon subscription, use {@link #defer(Supplier)} + * If the {@code CompletionStage} is to be created per consumer upon subscription, use {@link #defer(Supplier)} * around {@code fromCompletionStage}: *


      * Observable.defer(() -> Observable.fromCompletionStage(createCompletionStage()));
@@ -16533,7 +16889,7 @@ public final TestObserver test(boolean dispose) { // NoPMD
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Observable<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
+    public static <@NonNull T> Observable<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
         Objects.requireNonNull(stage, "stage is null");
         return RxJavaPlugins.onAssembly(new ObservableFromCompletionStage<>(stage));
     }
@@ -16576,7 +16932,7 @@ public final TestObserver test(boolean dispose) { // NoPMD
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Observable<@NonNull T> fromStream(@NonNull Stream stream) {
+    public static <@NonNull T> Observable<@NonNull T> fromStream(@NonNull Stream stream) {
         Objects.requireNonNull(stream, "stream is null");
         return RxJavaPlugins.onAssembly(new ObservableFromStream<>(stream));
     }
@@ -16630,7 +16986,7 @@ public final TestObserver test(boolean dispose) { // NoPMD
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R, A> Single collect(@NonNull Collector collector) {
+    public final <@NonNull R, @Nullable A> Single collect(@NonNull Collector collector) {
         Objects.requireNonNull(collector, "collector is null");
         return RxJavaPlugins.onAssembly(new ObservableCollectWithCollectorSingle<>(this, collector));
     }
@@ -16928,7 +17284,7 @@ public final Stream blockingStream(int capacityHint) {
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Observable concatMapStream(@NonNull Function> mapper) {
+    public final <@NonNull R> Observable concatMapStream(@NonNull Function> mapper) {
         return flatMapStream(mapper);
     }
 
@@ -16975,7 +17331,7 @@ public final Stream blockingStream(int capacityHint) {
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public final <@NonNull R> Observable flatMapStream(@NonNull Function> mapper) {
+    public final <@NonNull R> Observable flatMapStream(@NonNull Function> mapper) {
         Objects.requireNonNull(mapper, "mapper is null");
         return RxJavaPlugins.onAssembly(new ObservableFlatMapStream<>(this, mapper));
     }
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableConverter.java b/src/main/java/io/reactivex/rxjava3/core/ObservableConverter.java
index 7ab3a30a740..24cb2c9fad1 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableConverter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableConverter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableEmitter.java b/src/main/java/io/reactivex/rxjava3/core/ObservableEmitter.java
index 1ce0b936872..0658c4ba818 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableEmitter.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableEmitter.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/core/ObservableOnSubscribe.java
index de98fe0817d..056441620ad 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableOnSubscribe.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableOnSubscribe.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,13 +10,14 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
 
 /**
  * A functional interface that has a {@code subscribe()} method that receives
- * an instance of an {@link ObservableEmitter} instance that allows pushing
+ * an {@link ObservableEmitter} instance that allows pushing
  * events in a cancellation-safe manner.
  *
  * @param  the value type pushed
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableOperator.java b/src/main/java/io/reactivex/rxjava3/core/ObservableOperator.java
index 749bfa1a701..fd697fa626e 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableOperator.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableOperator.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableSource.java b/src/main/java/io/reactivex/rxjava3/core/ObservableSource.java
index 89603f8e9cd..c00bfc2170a 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableSource.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableSource.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -10,6 +10,7 @@
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
  * the License for the specific language governing permissions and limitations under the License.
  */
+
 package io.reactivex.rxjava3.core;
 
 import io.reactivex.rxjava3.annotations.NonNull;
diff --git a/src/main/java/io/reactivex/rxjava3/core/ObservableTransformer.java b/src/main/java/io/reactivex/rxjava3/core/ObservableTransformer.java
index e6686e2e97c..57b32bdc71f 100644
--- a/src/main/java/io/reactivex/rxjava3/core/ObservableTransformer.java
+++ b/src/main/java/io/reactivex/rxjava3/core/ObservableTransformer.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/Observer.java b/src/main/java/io/reactivex/rxjava3/core/Observer.java
index dd4fb58711e..6b911f51e58 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Observer.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Observer.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
diff --git a/src/main/java/io/reactivex/rxjava3/core/Scheduler.java b/src/main/java/io/reactivex/rxjava3/core/Scheduler.java
index 7b96792bbef..3aa001127ad 100644
--- a/src/main/java/io/reactivex/rxjava3/core/Scheduler.java
+++ b/src/main/java/io/reactivex/rxjava3/core/Scheduler.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016-present, RxJava Contributors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
@@ -18,11 +18,9 @@
 
 import io.reactivex.rxjava3.annotations.*;
 import io.reactivex.rxjava3.disposables.Disposable;
-import io.reactivex.rxjava3.exceptions.Exceptions;
 import io.reactivex.rxjava3.functions.Function;
 import io.reactivex.rxjava3.internal.disposables.*;
 import io.reactivex.rxjava3.internal.schedulers.*;
-import io.reactivex.rxjava3.internal.util.ExceptionHelper;
 import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import io.reactivex.rxjava3.schedulers.SchedulerRunnableIntrospection;
 
@@ -62,8 +60,9 @@
  * interface which can grant access to the original or hooked {@code Runnable}, thus, a repeated {@code RxJavaPlugins.onSchedule}
  * can detect the earlier hook and not apply a new one over again.
  * 

- * The default implementation of {@link #now(TimeUnit)} and {@link Worker#now(TimeUnit)} methods to return current - * {@link System#currentTimeMillis()} value in the desired time unit. Custom {@code Scheduler} implementations can override this + * The default implementation of {@link #now(TimeUnit)} and {@link Worker#now(TimeUnit)} methods to return current {@link System#currentTimeMillis()} + * value in the desired time unit, unless {@code rx3.scheduler.use-nanotime} (boolean) is set. When the property is set to + * {@code true}, the method uses {@link System#nanoTime()} as its basis instead. Custom {@code Scheduler} implementations can override this * to provide specialized time accounting (such as virtual time to be advanced programmatically). * Note that operators requiring a {@code Scheduler} may rely on either of the {@code now()} calls provided by * {@code Scheduler} or {@code Worker} respectively, therefore, it is recommended they represent a logically @@ -75,8 +74,8 @@ * based on the relative time between it and {@link Worker#now(TimeUnit)}. However, drifts or changes in the * system clock could affect this calculation either by scheduling subsequent runs too frequently or too far apart. * Therefore, the default implementation uses the {@link #clockDriftTolerance()} value (set via - * {@code rx3.scheduler.drift-tolerance} in minutes) to detect a drift in {@link Worker#now(TimeUnit)} and - * re-adjust the absolute/relative time calculation accordingly. + * {@code rx3.scheduler.drift-tolerance} and {@code rx3.scheduler.drift-tolerance-unit}) to detect a + * drift in {@link Worker#now(TimeUnit)} and re-adjust the absolute/relative time calculation accordingly. *

* The default implementations of {@link #start()} and {@link #shutdown()} do nothing and should be overridden if the * underlying task-execution scheme supports stopping and restarting itself. @@ -90,20 +89,73 @@ * All methods on the {@code Scheduler} and {@code Worker} classes should be thread safe. */ public abstract class Scheduler { + /** + * Value representing whether to use {@link System#nanoTime()}, or default as clock for {@link #now(TimeUnit)} + * and {@link Scheduler.Worker#now(TimeUnit)}. + *

+ * Associated system parameter: + *

    + *
  • {@code rx3.scheduler.use-nanotime}, boolean, default {@code false} + *
+ */ + static boolean IS_DRIFT_USE_NANOTIME = Boolean.getBoolean("rx3.scheduler.use-nanotime"); + + /** + * Returns the current clock time depending on state of {@link Scheduler#IS_DRIFT_USE_NANOTIME} in given {@code unit} + *

+ * By default {@link System#currentTimeMillis()} will be used as the clock. When the property is set + * {@link System#nanoTime()} will be used. + *

+ * @param unit the time unit + * @return the 'current time' in given unit + * @throws NullPointerException if {@code unit} is {@code null} + */ + static long computeNow(TimeUnit unit) { + if (!IS_DRIFT_USE_NANOTIME) { + return unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + return unit.convert(System.nanoTime(), TimeUnit.NANOSECONDS); + } + /** * The tolerance for a clock drift in nanoseconds where the periodic scheduler will rebase. *

- * The associated system parameter, {@code rx3.scheduler.drift-tolerance}, expects its value in minutes. + * Associated system parameters: + *

    + *
  • {@code rx3.scheduler.drift-tolerance}, long, default {@code 15}
  • + *
  • {@code rx3.scheduler.drift-tolerance-unit}, string, default {@code minutes}, + * supports {@code seconds} and {@code milliseconds}. + *
+ */ + static final long CLOCK_DRIFT_TOLERANCE_NANOSECONDS = + computeClockDrift( + Long.getLong("rx3.scheduler.drift-tolerance", 15), + System.getProperty("rx3.scheduler.drift-tolerance-unit", "minutes") + ); + + /** + * Returns the clock drift tolerance in nanoseconds based on the input selection. + * @param time the time value + * @param timeUnit the time unit string + * @return the time amount in nanoseconds */ - static final long CLOCK_DRIFT_TOLERANCE_NANOSECONDS; - static { - CLOCK_DRIFT_TOLERANCE_NANOSECONDS = TimeUnit.MINUTES.toNanos( - Long.getLong("rx3.scheduler.drift-tolerance", 15)); + static long computeClockDrift(long time, String timeUnit) { + if ("seconds".equalsIgnoreCase(timeUnit)) { + return TimeUnit.SECONDS.toNanos(time); + } else if ("milliseconds".equalsIgnoreCase(timeUnit)) { + return TimeUnit.MILLISECONDS.toNanos(time); + } + return TimeUnit.MINUTES.toNanos(time); } /** * Returns the clock drift tolerance in nanoseconds. - *

Related system property: {@code rx3.scheduler.drift-tolerance} in minutes. + *

Related system properties: + *

    + *
  • {@code rx3.scheduler.drift-tolerance}, long, default {@code 15}
  • + *
  • {@code rx3.scheduler.drift-tolerance-unit}, string, default {@code minutes}, + * supports {@code seconds} and {@code milliseconds}. + *
* @return the tolerance in nanoseconds * @since 2.0 */ @@ -133,7 +185,7 @@ public static long clockDriftTolerance() { * @since 2.0 */ public long now(@NonNull TimeUnit unit) { - return unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); + return computeNow(unit); } /** @@ -298,7 +350,7 @@ public Disposable schedulePeriodicallyDirect(@NonNull Runnable run, long initial * }); *
* - * Slowing down the rate to no more than than 1 a second. This suffers from + * Slowing down the rate to no more than 1 a second. This suffers from * the same problem as the one above I could find an {@link Flowable} * operator that limits the rate without dropping the values (aka leaky * bucket algorithm). @@ -339,8 +391,9 @@ public S when(@NonNull Function - * The default implementation of the {@link #now(TimeUnit)} method returns current - * {@link System#currentTimeMillis()} value in the desired time unit. Custom {@code Worker} implementations can override this + * The default implementation of the {@link #now(TimeUnit)} method returns current {@link System#currentTimeMillis()} + * value in the desired time unit, unless {@code rx3.scheduler.use-nanotime} (boolean) is set. When the property is set to + * {@code true}, the method uses {@link System#nanoTime()} as its basis instead. Custom {@code Worker} implementations can override this * to provide specialized time accounting (such as virtual time to be advanced programmatically). * Note that operators requiring a scheduler may rely on either of the {@code now()} calls provided by * {@code Scheduler} or {@code Worker} respectively, therefore, it is recommended they represent a logically @@ -352,7 +405,7 @@ public S when(@NonNull Function * If the {@code Worker} is disposed, the {@code schedule} methods @@ -459,7 +512,7 @@ public Disposable schedulePeriodically(@NonNull Runnable run, final long initial * @since 2.0 */ public long now(@NonNull TimeUnit unit) { - return unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); + return computeNow(unit); } /** @@ -542,9 +595,10 @@ public void run() { try { run.run(); } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); - worker.dispose(); - throw ExceptionHelper.wrapOrThrow(ex); + // Exceptions.throwIfFatal(ex); nowhere to go + dispose(); + RxJavaPlugins.onError(ex); + throw ex; } } } @@ -586,7 +640,13 @@ static final class DisposeTask implements Disposable, Runnable, SchedulerRunnabl public void run() { runner = Thread.currentThread(); try { - decoratedRun.run(); + try { + decoratedRun.run(); + } catch (Throwable ex) { + // Exceptions.throwIfFatal(e); nowhere to go + RxJavaPlugins.onError(ex); + throw ex; + } } finally { dispose(); runner = null; diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 09c67ef5a11..6cf5a3f7890 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.*; @@ -65,7 +65,7 @@ *

* The documentation for this class makes use of marble diagrams. The following legend explains these diagrams: *

- * + * *

* See {@link Flowable} or {@code Observable} for the * implementation of the Reactive Pattern for a stream or vector of values. @@ -119,7 +119,7 @@ public abstract class Single<@NonNull T> implements SingleSource { * Runs multiple {@link SingleSource}s and signals the events of the first one that signals (disposing * the rest). *

- * + * *

*
Scheduler:
*
{@code amb} does not operate by default on a particular {@link Scheduler}.
@@ -134,7 +134,7 @@ public abstract class Single<@NonNull T> implements SingleSource { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single amb(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Single amb(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new SingleAmb<>(null, sources)); } @@ -143,7 +143,7 @@ public static Single amb(@NonNull Iterable<@NonNull ? extends SingleSourc * Runs multiple {@link SingleSource}s and signals the events of the first one that signals (disposing * the rest). *

- * + * *

*
Scheduler:
*
{@code ambArray} does not operate by default on a particular {@link Scheduler}.
@@ -159,7 +159,7 @@ public static Single amb(@NonNull Iterable<@NonNull ? extends SingleSourc @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Single ambArray(@NonNull SingleSource... sources) { + public static <@NonNull T> Single ambArray(@NonNull SingleSource... sources) { Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { return error(SingleInternalHelper.emptyThrower()); @@ -176,7 +176,7 @@ public static Single ambArray(@NonNull SingleSource... sourc * Concatenate the single values, in a non-overlapping fashion, of the {@link SingleSource}s provided by * an {@link Iterable} sequence. *

- * + * *

*
Backpressure:
*
The returned {@link Flowable} honors the backpressure of the downstream consumer.
@@ -193,7 +193,7 @@ public static Single ambArray(@NonNull SingleSource... sourc @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static Flowable concat(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concat(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).concatMapSingleDelayError(Functions.identity(), false); } @@ -201,7 +201,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends Single * Concatenate the single values, in a non-overlapping fashion, of the {@link SingleSource}s provided by * an {@link ObservableSource} sequence. *

- * + * *

*
Scheduler:
*
{@code concat} does not operate by default on a particular {@link Scheduler}.
@@ -215,7 +215,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends Single @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable concat(@NonNull ObservableSource> sources) { + public static <@NonNull T> Observable concat(@NonNull ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new ObservableConcatMapSingle<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, 2)); } @@ -224,7 +224,7 @@ public static Observable concat(@NonNull ObservableSource - * + * *
*
Backpressure:
*
The returned {@link Flowable} honors the backpressure of the downstream consumer @@ -242,7 +242,7 @@ public static Observable concat(@NonNull ObservableSource Flowable concat(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { return concat(sources, 2); } @@ -250,7 +250,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Singl * Concatenate the single values, in a non-overlapping fashion, of the {@link SingleSource}s provided by * a {@link Publisher} sequence and prefetched by the specified amount. *

- * + * *

*
Backpressure:
*
The returned {@link Flowable} honors the backpressure of the downstream consumer @@ -270,7 +270,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Singl @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { + public static <@NonNull T> Flowable concat(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new FlowableConcatMapSinglePublisher<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, prefetch)); @@ -279,7 +279,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Singl /** * Returns a {@link Flowable} that emits the items emitted by two {@link SingleSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -300,7 +300,7 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Singl @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( + public static <@NonNull T> Flowable concat( @NonNull SingleSource source1, @NonNull SingleSource source2 ) { Objects.requireNonNull(source1, "source1 is null"); @@ -311,7 +311,7 @@ public static Flowable concat( /** * Returns a {@link Flowable} that emits the items emitted by three {@link SingleSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -334,7 +334,7 @@ public static Flowable concat( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( + public static <@NonNull T> Flowable concat( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3 ) { @@ -347,7 +347,7 @@ public static Flowable concat( /** * Returns a {@link Flowable} that emits the items emitted by four {@link SingleSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -372,7 +372,7 @@ public static Flowable concat( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concat( + public static <@NonNull T> Flowable concat( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4 ) { @@ -387,7 +387,7 @@ public static Flowable concat( * Concatenate the single values, in a non-overlapping fashion, of the {@link SingleSource}s provided in * an array. *

- * + * *

*
Backpressure:
*
The returned {@link Flowable} honors the backpressure of the downstream consumer.
@@ -405,7 +405,7 @@ public static Flowable concat( @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable concatArray(@NonNull SingleSource... sources) { + public static <@NonNull T> Flowable concatArray(@NonNull SingleSource... sources) { return Flowable.fromArray(sources).concatMapSingleDelayError(Functions.identity(), false); } @@ -431,7 +431,7 @@ public static Flowable concatArray(@NonNull SingleSource... @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable concatArrayDelayError(@NonNull SingleSource... sources) { + public static <@NonNull T> Flowable concatArrayDelayError(@NonNull SingleSource... sources) { return Flowable.fromArray(sources).concatMapSingleDelayError(Functions.identity(), true); } @@ -459,7 +459,7 @@ public static Flowable concatArrayDelayError(@NonNull SingleSource Flowable concatArrayEager(@NonNull SingleSource... sources) { + public static <@NonNull T> Flowable concatArrayEager(@NonNull SingleSource... sources) { return Flowable.fromArray(sources).concatMapEager(SingleInternalHelper.toFlowable()); } @@ -488,7 +488,7 @@ public static Flowable concatArrayEager(@NonNull SingleSource Flowable concatArrayEagerDelayError(@NonNull SingleSource... sources) { + public static <@NonNull T> Flowable concatArrayEagerDelayError(@NonNull SingleSource... sources) { return Flowable.fromArray(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); } @@ -515,7 +515,7 @@ public static Flowable concatArrayEagerDelayError(@NonNull SingleSource Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).concatMapSingleDelayError(Functions.identity()); } @@ -542,7 +542,7 @@ public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? exte @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { return Flowable.fromPublisher(sources).concatMapSingleDelayError(Functions.identity()); } @@ -574,14 +574,14 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { + public static <@NonNull T> Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { return Flowable.fromPublisher(sources).concatMapSingleDelayError(Functions.identity(), true, prefetch); } /** * Concatenates an {@link Iterable} sequence of {@link SingleSource}s eagerly into a single stream of values. *

- * + * *

* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * source {@code SingleSource}s. The operator buffers the values emitted by these {@code SingleSource}s and then drains them @@ -601,7 +601,7 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), false); } @@ -633,14 +633,14 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends S @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), false, maxConcurrency, 1); } /** * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values. *

- * + * *

* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these @@ -662,7 +662,7 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends S @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable()); } @@ -696,7 +696,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable(), maxConcurrency, 1); } @@ -725,7 +725,7 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); } @@ -757,7 +757,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true, maxConcurrency, 1); } @@ -788,7 +788,7 @@ public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { return Flowable.fromPublisher(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); } @@ -822,14 +822,14 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + public static <@NonNull T> Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { return Flowable.fromPublisher(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true, maxConcurrency, 1); } /** * Provides an API (via a cold {@code Single}) that bridges the reactive world with the callback-style world. *

- * + * *

* Example: *


@@ -881,7 +881,7 @@ public static  Flowable concatEagerDelayError(@NonNull Publisher<@NonNull
      * Calls a {@link Supplier} for each individual {@link SingleObserver} to return the actual {@link SingleSource} to
      * be subscribed to.
      * 

- * + * *

*
Scheduler:
*
{@code defer} does not operate by default on a particular {@link Scheduler}.
@@ -895,7 +895,7 @@ public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single defer(@NonNull Supplier> supplier) { + public static <@NonNull T> Single defer(@NonNull Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new SingleDefer<>(supplier)); } @@ -903,7 +903,7 @@ public static Single defer(@NonNull Supplier - * + * *
*
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
@@ -917,7 +917,7 @@ public static Single defer(@NonNull Supplier Single error(@NonNull Supplier supplier) { + public static <@NonNull T> Single error(@NonNull Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); return RxJavaPlugins.onAssembly(new SingleError<>(supplier)); } @@ -926,7 +926,7 @@ public static Single error(@NonNull Supplier supplie * Returns a {@code Single} that invokes a subscriber's {@link SingleObserver#onError onError} method when the * subscriber subscribes to it. *

- * + * *

*
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
@@ -944,7 +944,7 @@ public static Single error(@NonNull Supplier supplie @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single error(@NonNull Throwable throwable) { + public static <@NonNull T> Single error(@NonNull Throwable throwable) { Objects.requireNonNull(throwable, "throwable is null"); return error(Functions.justSupplier(throwable)); } @@ -957,7 +957,7 @@ public static Single error(@NonNull Throwable throwable) { * It makes passed function "lazy". * Result of the function invocation will be emitted by the {@link Single}. *

- * + * *

*
Scheduler:
*
{@code fromCallable} does not operate by default on a particular {@link Scheduler}.
@@ -990,7 +990,7 @@ public static Single error(@NonNull Throwable throwable) { /** * Converts a {@link Future} into a {@code Single} and awaits its outcome in a blocking fashion. *

- * + * *

* The operator calls {@link Future#get()}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -1026,7 +1026,7 @@ public static Single error(@NonNull Throwable throwable) { /** * Converts a {@link Future} into a {@code Single} and awaits its outcome, or timeout, in a blocking fashion. *

- * + * *

* The operator calls {@link Future#get(long, TimeUnit)}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -1080,7 +1080,7 @@ public static Single error(@NonNull Throwable throwable) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single fromMaybe(@NonNull MaybeSource maybe) { + public static <@NonNull T> Single fromMaybe(@NonNull MaybeSource maybe) { Objects.requireNonNull(maybe, "maybe is null"); return RxJavaPlugins.onAssembly(new MaybeToSingle<>(maybe, null)); } @@ -1105,7 +1105,7 @@ public static Single fromMaybe(@NonNull MaybeSource maybe) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single fromMaybe(@NonNull MaybeSource maybe, @NonNull T defaultItem) { + public static <@NonNull T> Single fromMaybe(@NonNull MaybeSource maybe, @NonNull T defaultItem) { Objects.requireNonNull(maybe, "maybe is null"); Objects.requireNonNull(defaultItem, "defaultItem is null"); return RxJavaPlugins.onAssembly(new MaybeToSingle<>(maybe, defaultItem)); @@ -1114,7 +1114,7 @@ public static Single fromMaybe(@NonNull MaybeSource maybe, @NonNull T /** * Wraps a specific {@link Publisher} into a {@code Single} and signals its single element or error. *

- * + * *

* If the source {@code Publisher} is empty, a {@link NoSuchElementException} is signaled. If * the source has more than one element, an {@link IndexOutOfBoundsException} is signaled. @@ -1146,7 +1146,7 @@ public static Single fromMaybe(@NonNull MaybeSource maybe, @NonNull T @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single fromPublisher(@NonNull Publisher<@NonNull ? extends T> publisher) { + public static <@NonNull T> Single fromPublisher(@NonNull Publisher publisher) { Objects.requireNonNull(publisher, "publisher is null"); return RxJavaPlugins.onAssembly(new SingleFromPublisher<>(publisher)); } @@ -1154,7 +1154,7 @@ public static Single fromPublisher(@NonNull Publisher<@NonNull ? extends /** * Wraps a specific {@link ObservableSource} into a {@code Single} and signals its single element or error. *

- * + * *

* If the {@code ObservableSource} is empty, a {@link NoSuchElementException} is signaled. * If the source has more than one element, an {@link IndexOutOfBoundsException} is signaled. @@ -1172,7 +1172,7 @@ public static Single fromPublisher(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single fromObservable(@NonNull ObservableSource observable) { + public static <@NonNull T> Single fromObservable(@NonNull ObservableSource observable) { Objects.requireNonNull(observable, "observable is null"); return RxJavaPlugins.onAssembly(new ObservableSingleSingle<>(observable, null)); } @@ -1185,7 +1185,7 @@ public static Single fromObservable(@NonNull ObservableSource - * + * *

*
Scheduler:
*
{@code fromSupplier} does not operate by default on a particular {@link Scheduler}.
@@ -1219,7 +1219,7 @@ public static Single fromObservable(@NonNull ObservableSource - * + * *

* To convert any object into a {@code Single} that emits that object, pass that object into the * {@code just} method. @@ -1248,7 +1248,7 @@ public static Single fromObservable(@NonNull ObservableSource - * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -1279,7 +1279,7 @@ public static Single fromObservable(@NonNull ObservableSource Flowable merge(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable merge(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).flatMapSingle(Functions.identity()); } @@ -1287,7 +1287,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends SingleS * Merges a sequence of {@link SingleSource} instances emitted by a {@link Publisher} into a single {@link Flowable} sequence, * running all {@code SingleSource}s at once. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -1318,7 +1318,7 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends SingleS @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable merge(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableFlatMapSinglePublisher<>(sources, Functions.identity(), false, Integer.MAX_VALUE)); } @@ -1327,7 +1327,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends Single * Flattens a {@link SingleSource} that emits a {@code SingleSingle} into a single {@code Single} that emits the item * emitted by the nested {@code SingleSource}, without any transformation. *

- * + * *

*
Scheduler:
*
{@code merge} does not operate by default on a particular {@link Scheduler}.
@@ -1349,7 +1349,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends Single @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single merge(@NonNull SingleSource> source) { + public static <@NonNull T> Single merge(@NonNull SingleSource> source) { Objects.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new SingleFlatMap, T>(source, Functions.identity())); } @@ -1357,7 +1357,7 @@ public static Single merge(@NonNull SingleSource - * + * *

* You can combine items emitted by multiple {@code SingleSource}s so that they appear as a single {@code Flowable}, by * using the {@code merge} method. @@ -1395,7 +1395,7 @@ public static Single merge(@NonNull SingleSource Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull SingleSource source1, @NonNull SingleSource source2 ) { Objects.requireNonNull(source1, "source1 is null"); @@ -1406,7 +1406,7 @@ public static Flowable merge( /** * Flattens three {@link SingleSource}s into one {@link Flowable} sequence, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code SingleSource}s so that they appear as a single {@code Flowable}, by * the {@code merge} method. @@ -1446,7 +1446,7 @@ public static Flowable merge( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3 ) { @@ -1459,7 +1459,7 @@ public static Flowable merge( /** * Flattens four {@link SingleSource}s into one {@link Flowable} sequence, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code SingleSource}s so that they appear as a single {@code Flowable}, by * the {@code merge} method. @@ -1501,7 +1501,7 @@ public static Flowable merge( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable merge( + public static <@NonNull T> Flowable merge( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4 ) { @@ -1547,7 +1547,7 @@ public static Flowable merge( @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable mergeArray(SingleSource... sources) { + public static <@NonNull T> Flowable mergeArray(SingleSource... sources) { return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), false, Math.max(1, sources.length)); } @@ -1583,7 +1583,7 @@ public static Flowable mergeArray(SingleSource... sources) { @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs @NonNull - public static Flowable mergeArrayDelayError(@NonNull SingleSource... sources) { + public static <@NonNull T> Flowable mergeArrayDelayError(@NonNull SingleSource... sources) { return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), true, Math.max(1, sources.length)); } @@ -1610,7 +1610,7 @@ public static Flowable mergeArrayDelayError(@NonNull SingleSource Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { return Flowable.fromIterable(sources).flatMapSingle(Functions.identity(), true, Integer.MAX_VALUE); } @@ -1637,7 +1637,7 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableFlatMapSinglePublisher<>(sources, Functions.identity(), true, Integer.MAX_VALUE)); } @@ -1672,7 +1672,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError( + public static <@NonNull T> Flowable mergeDelayError( @NonNull SingleSource source1, @NonNull SingleSource source2 ) { Objects.requireNonNull(source1, "source1 is null"); @@ -1712,7 +1712,7 @@ public static Flowable mergeDelayError( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError( + public static <@NonNull T> Flowable mergeDelayError( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3 ) { @@ -1756,7 +1756,7 @@ public static Flowable mergeDelayError( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable mergeDelayError( + public static <@NonNull T> Flowable mergeDelayError( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4 ) { @@ -1770,7 +1770,7 @@ public static Flowable mergeDelayError( /** * Returns a singleton instance of a never-signaling {@code Single} (only calls {@code onSubscribe}). *

- * + * *

*
Scheduler:
*
{@code never} does not operate by default on a particular {@link Scheduler}.
@@ -1783,14 +1783,14 @@ public static Flowable mergeDelayError( @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings("unchecked") @NonNull - public static Single never() { + public static <@NonNull T> Single never() { return RxJavaPlugins.onAssembly((Single) SingleNever.INSTANCE); } /** * Signals success with 0L value after the given delay when a {@link SingleObserver} subscribes. *

- * + * *

*
Scheduler:
*
{@code timer} operates by default on the {@code computation} {@link Scheduler}.
@@ -1812,7 +1812,7 @@ public static Single timer(long delay, @NonNull TimeUnit unit) { * Signals success with 0L value on the specified {@link Scheduler} after the given * delay when a {@link SingleObserver} subscribes. *

- * + * *

*
Scheduler:
*
you specify the {@code Scheduler} to signal on.
@@ -1838,7 +1838,7 @@ public static Single timer(long delay, @NonNull TimeUnit unit, @NonNull Sc /** * Compares two {@link SingleSource}s and emits {@code true} if they emit the same value (compared via {@link Object#equals(Object)}). *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -1853,7 +1853,7 @@ public static Single timer(long delay, @NonNull TimeUnit unit, @NonNull Sc @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single sequenceEqual(@NonNull SingleSource source1, @NonNull SingleSource source2) { // NOPMD + public static <@NonNull T> Single sequenceEqual(@NonNull SingleSource source1, @NonNull SingleSource source2) { // NOPMD Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); return RxJavaPlugins.onAssembly(new SingleEquals<>(source1, source2)); @@ -1888,7 +1888,7 @@ public static Single sequenceEqual(@NonNull SingleSource Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapSinglePublisher<>(sources, Functions.identity(), false)); } @@ -1923,7 +1923,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + public static <@NonNull T> Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); return RxJavaPlugins.onAssembly(new FlowableSwitchMapSinglePublisher<>(sources, Functions.identity(), true)); } @@ -1949,7 +1949,7 @@ public static Flowable switchOnNextDelayError(@NonNull Publisher<@NonNull @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single unsafeCreate(@NonNull SingleSource onSubscribe) { + public static <@NonNull T> Single unsafeCreate(@NonNull SingleSource onSubscribe) { Objects.requireNonNull(onSubscribe, "onSubscribe is null"); if (onSubscribe instanceof Single) { throw new IllegalArgumentException("unsafeCreate(Single) should be upgraded"); @@ -1961,7 +1961,7 @@ public static Single unsafeCreate(@NonNull SingleSource onSubscribe) { * Allows using and disposing a resource while running a {@link SingleSource} instance generated from * that resource (similar to a try-with-resources). *

- * + * *

*
Scheduler:
*
{@code using} does not operate by default on a particular {@link Scheduler}.
@@ -1982,7 +1982,7 @@ public static Single unsafeCreate(@NonNull SingleSource onSubscribe) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Single using(@NonNull Supplier resourceSupplier, + public static <@NonNull T, @NonNull U> Single using(@NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup) { return using(resourceSupplier, sourceSupplier, resourceCleanup, true); @@ -2018,7 +2018,7 @@ public static Single using(@NonNull Supplier resourceSupplier, @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single using( + public static <@NonNull T, @NonNull U> Single using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, @NonNull Consumer resourceCleanup, @@ -2047,7 +2047,7 @@ public static Single using( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single wrap(@NonNull SingleSource source) { + public static <@NonNull T> Single wrap(@NonNull SingleSource source) { Objects.requireNonNull(source, "source is null"); if (source instanceof Single) { return RxJavaPlugins.onAssembly((Single)source); @@ -2088,7 +2088,7 @@ public static Single wrap(@NonNull SingleSource source) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip(@NonNull Iterable<@NonNull ? extends SingleSource> sources, + public static <@NonNull T, @NonNull R> Single zip(@NonNull Iterable<@NonNull ? extends SingleSource> sources, @NonNull Function zipper) { Objects.requireNonNull(zipper, "zipper is null"); Objects.requireNonNull(sources, "sources is null"); @@ -2122,7 +2122,7 @@ public static Single zip(@NonNull Iterable<@NonNull ? extends SingleSo @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull BiFunction zipper ) { @@ -2162,7 +2162,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull Function3 zipper @@ -2207,7 +2207,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull Function4 zipper @@ -2257,7 +2257,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull SingleSource source5, @@ -2312,7 +2312,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull SingleSource source5, @NonNull SingleSource source6, @@ -2371,7 +2371,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull SingleSource source5, @NonNull SingleSource source6, @@ -2435,7 +2435,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull SingleSource source5, @NonNull SingleSource source6, @@ -2504,7 +2504,7 @@ public static Single zip( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single zip( + public static <@NonNull T1, @NonNull T2, @NonNull T3, @NonNull T4, @NonNull T5, @NonNull T6, @NonNull T7, @NonNull T8, @NonNull T9, @NonNull R> Single zip( @NonNull SingleSource source1, @NonNull SingleSource source2, @NonNull SingleSource source3, @NonNull SingleSource source4, @NonNull SingleSource source5, @NonNull SingleSource source6, @@ -2558,7 +2558,7 @@ public static Single zip( @NonNull @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Single zipArray(@NonNull Function zipper, @NonNull SingleSource... sources) { + public static <@NonNull T, @NonNull R> Single zipArray(@NonNull Function zipper, @NonNull SingleSource... sources) { Objects.requireNonNull(zipper, "zipper is null"); Objects.requireNonNull(sources, "sources is null"); if (sources.length == 0) { @@ -2570,7 +2570,7 @@ public static Single zipArray(@NonNull Function - * + * *
*
Scheduler:
*
{@code ambWith} does not operate by default on a particular {@link Scheduler}.
@@ -2593,7 +2593,7 @@ public final Single ambWith(@NonNull SingleSource other) { * Hides the identity of the current {@code Single}, including the {@link Disposable} that is sent * to the downstream via {@code onSubscribe()}. *

- * + * *

*
Scheduler:
*
{@code hide} does not operate by default on a particular {@link Scheduler}.
@@ -2611,7 +2611,7 @@ public final Single hide() { /** * Transform a {@code Single} by applying a particular {@link SingleTransformer} function to it. *

- * + * *

* This method operates on the {@code Single} itself whereas {@link #lift} operates on {@link SingleObserver}s. *

@@ -2633,7 +2633,7 @@ public final Single hide() { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single compose(@NonNull SingleTransformer transformer) { + public final <@NonNull R> Single compose(@NonNull SingleTransformer transformer) { return wrap(((SingleTransformer) Objects.requireNonNull(transformer, "transformer is null")).apply(this)); } @@ -2676,7 +2676,7 @@ public final Single cache() { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single cast(@NonNull Class clazz) { + public final <@NonNull U> Single cast(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return map(Functions.castFunction(clazz)); } @@ -2699,11 +2699,12 @@ public final Single cast(@NonNull Class clazz) { * @return the new {@code Single} returned from {@code mapper} when applied to the item emitted by the current {@code Single} * @throws NullPointerException if {@code mapper} is {@code null} * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single concatMap(@NonNull Function> mapper) { + public final <@NonNull R> Single concatMap(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMap<>(this, mapper)); } @@ -2753,11 +2754,12 @@ public final Completable concatMapCompletable(@NonNull FunctionReactiveX operators documentation: FlatMap + * @since 3.0.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe concatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Maybe concatMapMaybe(@NonNull Function> mapper) { return flatMapMaybe(mapper); } @@ -2765,7 +2767,7 @@ public final Maybe concatMapMaybe(@NonNull Function - * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -2792,7 +2794,7 @@ public final Flowable concatWith(@NonNull SingleSource other) { * Delays the emission of the success signal from the current {@code Single} by the specified amount. * An error signal will not be delayed. *

- * + * *

*
Scheduler:
*
{@code delay} operates by default on the {@code computation} {@link Scheduler}.
@@ -2815,7 +2817,7 @@ public final Single delay(long time, @NonNull TimeUnit unit) { /** * Delays the emission of the success or error signal from the current {@code Single} by the specified amount. *

- * + * *

*
Scheduler:
*
{@code delay} operates by default on the {@code computation} {@link Scheduler}.
@@ -2839,7 +2841,7 @@ public final Single delay(long time, @NonNull TimeUnit unit, boolean delayErr * Delays the emission of the success signal from the current {@code Single} by the specified amount. * An error signal will not be delayed. *

- * + * *

*
Scheduler:
*
you specify the {@link Scheduler} where the non-blocking wait and emission happens
@@ -2865,7 +2867,7 @@ public final Single delay(long time, @NonNull TimeUnit unit, @NonNull Schedul /** * Delays the emission of the success or error signal from the current {@code Single} by the specified amount. *

- * + * *

*
Scheduler:
*
you specify the {@link Scheduler} where the non-blocking wait and emission happens
@@ -2936,7 +2938,7 @@ public final Single delaySubscription(@NonNull CompletableSource subscription @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull SingleSource subscriptionIndicator) { + public final <@NonNull U> Single delaySubscription(@NonNull SingleSource subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new SingleDelayWithSingle<>(this, subscriptionIndicator)); } @@ -2962,7 +2964,7 @@ public final Single delaySubscription(@NonNull SingleSource subscripti @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull ObservableSource subscriptionIndicator) { + public final <@NonNull U> Single delaySubscription(@NonNull ObservableSource subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new SingleDelayWithObservable<>(this, subscriptionIndicator)); } @@ -2993,7 +2995,7 @@ public final Single delaySubscription(@NonNull ObservableSource subscr @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull Publisher subscriptionIndicator) { + public final <@NonNull U> Single delaySubscription(@NonNull Publisher subscriptionIndicator) { Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); return RxJavaPlugins.onAssembly(new SingleDelayWithPublisher<>(this, subscriptionIndicator)); } @@ -3087,7 +3089,7 @@ public final Single delaySubscription(long time, @NonNull TimeUnit unit, @Non /** * Calls the specified consumer with the success item after this item has been emitted to the downstream. *

- * + * *

* Note that the {@code doAfterSuccess} action is shared between subscriptions and as such * should be thread-safe. @@ -3112,7 +3114,7 @@ public final Single doAfterSuccess(@NonNull Consumer onAfterSucces /** * Registers an {@link Action} to be called after this {@code Single} invokes either {@code onSuccess} or {@code onError}. *

- * + * *

* Note that the {@code doAfterTerminate} action is shared between subscriptions and as such * should be thread-safe.

@@ -3147,7 +3149,7 @@ public final Single doAfterTerminate(@NonNull Action onAfterTerminate) { *

Note that the {@code onFinally} action is shared between subscriptions and as such * should be thread-safe. *

- * + * *

*
*
Scheduler:
@@ -3199,7 +3201,7 @@ public final Single doOnLifecycle(@NonNull Consumer onSub * Calls the shared consumer with the {@link Disposable} sent through the {@code onSubscribe} for each * {@link SingleObserver} that subscribes to the current {@code Single}. *

- * + * *

*
*
Scheduler:
@@ -3222,7 +3224,7 @@ public final Single doOnSubscribe(@NonNull Consumer onSub * Returns a {@code Single} instance that calls the given {@code onTerminate} callback * just before this {@code Single} completes normally or with an exception. *

- * + * *

* This differs from {@code doAfterTerminate} in that this happens before the {@code onSuccess} or * {@code onError} notification. @@ -3250,7 +3252,7 @@ public final Single doOnTerminate(@NonNull Action onTerminate) { * Calls the shared consumer with the success value sent via {@code onSuccess} for each * {@link SingleObserver} that subscribes to the current {@code Single}. *

- * + * *

*
*
Scheduler:
@@ -3295,7 +3297,7 @@ public final Single doOnEvent(@NonNull BiConsumer<@Nullable ? super T, @Nulla * Calls the shared consumer with the error sent via {@code onError} for each * {@link SingleObserver} that subscribes to the current {@code Single}. *

- * + * *

*
*
Scheduler:
@@ -3318,7 +3320,7 @@ public final Single doOnError(@NonNull Consumer onError) { * Calls the shared {@link Action} if a {@link SingleObserver} subscribed to the current {@code Single} * disposes the common {@link Disposable} it received via {@code onSubscribe}. *

- * + * *

*
*
Scheduler:
@@ -3341,7 +3343,7 @@ public final Single doOnDispose(@NonNull Action onDispose) { * Filters the success item of the {@code Single} via a predicate function and emitting it if the predicate * returns {@code true}, completing otherwise. *

- * + * *

*
Scheduler:
*
{@code filter} does not operate by default on a particular {@link Scheduler}.
@@ -3367,7 +3369,7 @@ public final Maybe filter(@NonNull Predicate predicate) { * Returns a {@code Single} that is based on applying a specified function to the item emitted by the current {@code Single}, * where that function returns a {@link SingleSource}. *

- * + * *

*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -3383,7 +3385,7 @@ public final Maybe filter(@NonNull Predicate predicate) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single flatMap(@NonNull Function> mapper) { + public final <@NonNull R> Single flatMap(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMap<>(this, mapper)); } @@ -3415,7 +3417,7 @@ public final Single flatMap(@NonNull Function Single flatMap(@NonNull Function> mapper, + public final <@NonNull U, @NonNull R> Single flatMap(@NonNull Function> mapper, @NonNull BiFunction combiner) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(combiner, "combiner is null"); @@ -3446,7 +3448,7 @@ public final Single flatMap(@NonNull Function Single flatMap( + public final <@NonNull R> Single flatMap( @NonNull Function> onSuccessMapper, @NonNull Function> onErrorMapper) { Objects.requireNonNull(onSuccessMapper, "onSuccessMapper is null"); @@ -3474,7 +3476,7 @@ public final Single flatMap( @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe flatMapMaybe(@NonNull Function> mapper) { + public final <@NonNull R> Maybe flatMapMaybe(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMapMaybe<>(this, mapper)); } @@ -3483,7 +3485,7 @@ public final Maybe flatMapMaybe(@NonNull Function - * + * *
*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer @@ -3504,7 +3506,7 @@ public final Maybe flatMapMaybe(@NonNull Function Flowable flatMapPublisher(@NonNull Function> mapper) { + public final <@NonNull R> Flowable flatMapPublisher(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMapPublisher<>(this, mapper)); } @@ -3535,7 +3537,7 @@ public final Flowable flatMapPublisher(@NonNull Function Flowable flattenAsFlowable(@NonNull Function> mapper) { + public final <@NonNull U> Flowable flattenAsFlowable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMapIterableFlowable<>(this, mapper)); } @@ -3563,7 +3565,7 @@ public final Flowable flattenAsFlowable(@NonNull Function Observable flattenAsObservable(@NonNull Function<@NonNull ? super T, @NonNull ? extends Iterable<@NonNull ? extends U>> mapper) { + public final <@NonNull U> Observable flattenAsObservable(@NonNull Function<@NonNull ? super T, @NonNull ? extends Iterable> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlatMapIterableObservable<>(this, mapper)); } @@ -3572,7 +3574,7 @@ public final Flowable flattenAsFlowable(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapObservable} does not operate by default on a particular {@link Scheduler}.
@@ -3890,7 +3892,7 @@ public final void blockingSubscribe(@NonNull SingleObserver observer) @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single lift(@NonNull SingleOperator lift) { + public final <@NonNull R> Single lift(@NonNull SingleOperator lift) { Objects.requireNonNull(lift, "lift is null"); return RxJavaPlugins.onAssembly(new SingleLift<>(this, lift)); } @@ -3899,7 +3901,7 @@ public final Single lift(@NonNull SingleOperator * Returns a {@code Single} that applies a specified function to the item emitted by the current {@code Single} and * emits the result of this function application. *

- * + * *

*
Scheduler:
*
{@code map} does not operate by default on a particular {@link Scheduler}.
@@ -3924,7 +3926,7 @@ public final Single lift(@NonNull SingleOperator * Maps the signal types of this {@code Single} into a {@link Notification} of the same kind * and emits it as a single success value to downstream. *

- * + * *

*
Scheduler:
*
{@code materialize} does not operate by default on a particular {@link Scheduler}.
@@ -3992,7 +3994,7 @@ public final Single contains(@NonNull Object item, @NonNull BiPredicate /** * Flattens this {@code Single} and another {@link SingleSource} into one {@link Flowable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code SingleSource}s so that they appear as one {@code Flowable}, by using * the {@code mergeWith} method. @@ -4037,7 +4039,7 @@ public final Flowable mergeWith(@NonNull SingleSource other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe ofType(@NonNull Class clazz) { + public final <@NonNull U> Maybe ofType(@NonNull Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return filter(Functions.isInstanceOf(clazz)).cast(clazz); } @@ -4046,7 +4048,7 @@ public final Maybe ofType(@NonNull Class clazz) { * Signals the success item or the terminal signals of the current {@code Single} on the specified {@link Scheduler}, * asynchronously. *

- * + * *

*
Scheduler:
*
you specify which {@code Scheduler} this operator will use.
@@ -4072,7 +4074,7 @@ public final Single observeOn(@NonNull Scheduler scheduler) { * Ends the flow with a success item returned by a function for the {@link Throwable} error signaled by the current * {@code Single} instead of signaling the error via {@code onError}. *

- * + * *

* By default, when a {@code Single} encounters an error that prevents it from emitting the expected item to its * subscriber, the {@code Single} invokes its subscriber's {@link SingleObserver#onError} method, and then quits @@ -4106,7 +4108,7 @@ public final Single onErrorReturn(@NonNull Function i /** * Signals the specified value as success in case the current {@code Single} signals an error. *

- * + * *

*
Scheduler:
*
{@code onErrorReturnItem} does not operate by default on a particular {@link Scheduler}.
@@ -4207,7 +4209,7 @@ public final Maybe onErrorComplete(@NonNull Predicate pred * Resumes the flow with a {@link SingleSource} returned for the failure {@link Throwable} of the current {@code Single} by a * function instead of signaling the error via {@code onError}. *

- * + * *

* By default, when a {@code Single} encounters an error that prevents it from emitting the expected item to * its {@link SingleObserver}, the {@code Single} invokes its {@code SingleObserver}'s {@code onError} method, and then quits @@ -4265,7 +4267,7 @@ public final Single onTerminateDetach() { /** * Repeatedly re-subscribes to the current {@code Single} and emits each success value as a {@link Flowable} sequence. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -4286,7 +4288,7 @@ public final Flowable repeat() { /** * Re-subscribes to the current {@code Single} at most the given number of times and emits each success value as a {@link Flowable} sequence. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -4311,7 +4313,7 @@ public final Flowable repeat(long times) { * the {@link Publisher} returned by the handler function signals a value in response to a * value signaled through the {@link Flowable} the handler receives. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer. @@ -4331,7 +4333,7 @@ public final Flowable repeat(long times) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Flowable repeatWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Flowable repeatWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return toFlowable().repeatWhen(handler); } @@ -4339,7 +4341,7 @@ public final Flowable repeatWhen(@NonNull Function, * Re-subscribes to the current {@code Single} until the given {@link BooleanSupplier} returns {@code true} * and emits the success items as a {@link Flowable} sequence. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -4536,7 +4538,7 @@ public final Single retryUntil(@NonNull BooleanSupplier stop) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single retryWhen(@NonNull Function, ? extends Publisher<@NonNull ?>> handler) { + public final Single retryWhen(@NonNull Function, @NonNull ? extends Publisher<@NonNull ?>> handler) { return toSingle(toFlowable().retryWhen(handler)); } @@ -4703,6 +4705,7 @@ public final Flowable startWith(@NonNull Publisher other) { * * @return the new {@link Disposable} instance that can be used for disposing the subscription at any time * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, DisposableContainer) */ @SchedulerSupport(SchedulerSupport.NONE) @NonNull @@ -4724,14 +4727,15 @@ public final Disposable subscribe() { * the callback that receives either the success value or the failure {@link Throwable} * (whichever is not {@code null}) * @return the new {@link Disposable} instance that can be used for disposing the subscription at any time - * @see ReactiveX operators documentation: Subscribe * @throws NullPointerException * if {@code onCallback} is {@code null} + * @see #subscribe(Consumer, Consumer, DisposableContainer) + * @see ReactiveX operators documentation: Subscribe */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Disposable subscribe(@NonNull BiConsumer onCallback) { + public final Disposable subscribe(@NonNull BiConsumer<@Nullable ? super T, @Nullable ? super Throwable> onCallback) { Objects.requireNonNull(onCallback, "onCallback is null"); BiConsumerSingleObserver observer = new BiConsumerSingleObserver<>(onCallback); @@ -4758,6 +4762,7 @@ public final Disposable subscribe(@NonNull BiConsumerReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, DisposableContainer) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -4782,9 +4787,10 @@ public final Disposable subscribe(@NonNull Consumer onSuccess) { * the {@code Consumer} you have designed to accept any error notification from the * {@code Single} * @return the new {@link Disposable} instance that can be used for disposing the subscription at any time - * @see ReactiveX operators documentation: Subscribe * @throws NullPointerException * if {@code onSuccess} or {@code onError} is {@code null} + * @see ReactiveX operators documentation: Subscribe + * @see #subscribe(Consumer, Consumer, DisposableContainer) */ @CheckReturnValue @NonNull @@ -4798,6 +4804,44 @@ public final Disposable subscribe(@NonNull Consumer onSuccess, @NonNu return observer; } + /** + * Wraps the given onXXX callbacks into a {@link Disposable} {@link SingleObserver}, + * adds it to the given {@link DisposableContainer} and ensures, that if the upstream + * terminates or this particular {@code Disposable} is disposed, the {@code SingleObserver} is removed + * from the given container. + *

+ * The {@code SingleObserver} will be removed after the callback for the terminal event has been invoked. + *

+ *
Scheduler:
+ *
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param onSuccess the callback for upstream items + * @param onError the callback for an upstream error if any + * @param container the {@code DisposableContainer} (such as {@link CompositeDisposable}) to add and remove the + * created {@code Disposable} {@code SingleObserver} + * @return the {@code Disposable} that allows disposing the particular subscription. + * @throws NullPointerException + * if {@code onSuccess}, {@code onError} + * or {@code container} is {@code null} + * @since 3.1.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Disposable subscribe( + @NonNull Consumer onSuccess, + @NonNull Consumer onError, + @NonNull DisposableContainer container) { + Objects.requireNonNull(onSuccess, "onSuccess is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(container, "container is null"); + + DisposableAutoReleaseMultiObserver observer = new DisposableAutoReleaseMultiObserver<>( + container, onSuccess, onError, Functions.EMPTY_ACTION); + container.add(observer); + subscribe(observer); + return observer; + } + @SchedulerSupport(SchedulerSupport.NONE) @Override public final void subscribe(@NonNull SingleObserver observer) { @@ -4865,7 +4909,7 @@ public final void subscribe(@NonNull SingleObserver observer) { /** * Asynchronously subscribes {@link SingleObserver}s to this {@code Single} on the specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -5167,7 +5211,7 @@ public final Single takeUntil(@NonNull CompletableSource other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single takeUntil(@NonNull Publisher other) { + public final <@NonNull E> Single takeUntil(@NonNull Publisher other) { Objects.requireNonNull(other, "other is null"); return RxJavaPlugins.onAssembly(new SingleTakeUntil<>(this, other)); } @@ -5195,7 +5239,7 @@ public final Single takeUntil(@NonNull Publisher other) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single takeUntil(@NonNull SingleSource other) { + public final <@NonNull E> Single takeUntil(@NonNull SingleSource other) { Objects.requireNonNull(other, "other is null"); return takeUntil(new SingleToFlowable(other)); } @@ -5306,7 +5350,7 @@ private Single timeout0(final long timeout, final TimeUnit unit, final Schedu /** * Calls the specified converter function during assembly time and returns its resulting value. *

- * + * *

* This allows fluent conversion to any other type. *

@@ -5349,7 +5393,7 @@ public final Completable ignoreElement() { /** * Converts this {@code Single} into a {@link Flowable}. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -5374,7 +5418,7 @@ public final Flowable toFlowable() { /** * Returns a {@link Future} representing the single value emitted by this {@code Single}. *

- * + * *

* Cancelling the {@code Future} will cancel the subscription to the current {@code Single}. *

@@ -5395,7 +5439,7 @@ public final Future toFuture() { /** * Converts this {@code Single} into a {@link Maybe}. *

- * + * *

*
Scheduler:
*
{@code toMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -5416,7 +5460,7 @@ public final Maybe toMaybe() { /** * Converts this {@code Single} into an {@link Observable}. *

- * + * *

*
Scheduler:
*
{@code toObservable} does not operate by default on a particular {@link Scheduler}.
@@ -5485,7 +5529,7 @@ public final Single unsubscribeOn(@NonNull Scheduler scheduler) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single zipWith(@NonNull SingleSource other, @NonNull BiFunction zipper) { + public final <@NonNull U, @NonNull R> Single zipWith(@NonNull SingleSource other, @NonNull BiFunction zipper) { return zip(this, other, zipper); } @@ -5554,7 +5598,7 @@ private static Single toSingle(@NonNull Flowable source) { * *

* Note that the operator takes an already instantiated, running or terminated {@code CompletionStage}. - * If the optional is to be created per consumer upon subscription, use {@link #defer(Supplier)} + * If the {@code CompletionStage} is to be created per consumer upon subscription, use {@link #defer(Supplier)} * around {@code fromCompletionStage}: *


      * Single.defer(() -> Single.fromCompletionStage(createCompletionStage()));
@@ -5578,7 +5622,7 @@ private static  Single toSingle(@NonNull Flowable source) {
     @CheckReturnValue
     @SchedulerSupport(SchedulerSupport.NONE)
     @NonNull
-    public static  Single<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
+    public static <@NonNull T> Single<@NonNull T> fromCompletionStage(@NonNull CompletionStage stage) {
         Objects.requireNonNull(stage, "stage is null");
         return RxJavaPlugins.onAssembly(new SingleFromCompletionStage<>(stage));
     }
@@ -5672,7 +5716,7 @@ public final CompletionStage toCompletionStage() {
     @SchedulerSupport(SchedulerSupport.NONE)
     @BackpressureSupport(BackpressureKind.FULL)
     @NonNull
-    public final  Flowable flattenStreamAsFlowable(@NonNull Function> mapper) {
+    public final <@NonNull R> Flowable flattenStreamAsFlowable(@NonNull Function> mapper) {
         Objects.requireNonNull(mapper, "mapper is null");
         return RxJavaPlugins.onAssembly(new SingleFlattenStreamAsFlowable<>(this, mapper));
     }
@@ -5685,7 +5729,7 @@ public final  Flowable flattenStreamAsFlowable(@NonNull Function
      * The operator closes the {@code Stream} upon cancellation and when it terminates. The exceptions raised when
      * closing a {@code Stream} are routed to the global error handler ({@link RxJavaPlugins#onError(Throwable)}.
-     * If a {@code Stream} should not be closed, turn it into an {@link Iterable} and use {@link #flattenAsFlowable(Function)}:
+     * If a {@code Stream} should not be closed, turn it into an {@link Iterable} and use {@link #flattenAsObservable(Function)}:
      * 

      * source.flattenAsObservable(item -> createStream(item)::iterator);
      * 
@@ -5713,7 +5757,7 @@ public final Flowable flattenStreamAsFlowable(@NonNull Function Observable flattenStreamAsObservable(@NonNull Function> mapper) { + public final <@NonNull R> Observable flattenStreamAsObservable(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new SingleFlattenStreamAsObservable<>(this, mapper)); } diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleConverter.java b/src/main/java/io/reactivex/rxjava3/core/SingleConverter.java index ce3a4464521..960a17d9d51 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleConverter.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleConverter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleEmitter.java b/src/main/java/io/reactivex/rxjava3/core/SingleEmitter.java index c8d0a79ec3e..4b18a816445 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleEmitter.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleEmitter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleObserver.java b/src/main/java/io/reactivex/rxjava3/core/SingleObserver.java index 281c15e5312..a110d4bcff3 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/core/SingleOnSubscribe.java index 14ff5e1f97e..e8b9e89f8ba 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleOnSubscribe.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleOnSubscribe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,13 +10,14 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; import io.reactivex.rxjava3.annotations.NonNull; /** * A functional interface that has a {@code subscribe()} method that receives - * an instance of a {@link SingleEmitter} instance that allows pushing + * a {@link SingleEmitter} instance that allows pushing * an event in a cancellation-safe manner. * * @param the value type pushed diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleOperator.java b/src/main/java/io/reactivex/rxjava3/core/SingleOperator.java index f3975b3a7fd..3b9c4a53c59 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleOperator.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleOperator.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleSource.java b/src/main/java/io/reactivex/rxjava3/core/SingleSource.java index bbeeaac40b0..16147fd55b0 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleSource.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/core/SingleTransformer.java b/src/main/java/io/reactivex/rxjava3/core/SingleTransformer.java index f3edca3430b..3ece315f978 100644 --- a/src/main/java/io/reactivex/rxjava3/core/SingleTransformer.java +++ b/src/main/java/io/reactivex/rxjava3/core/SingleTransformer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/core/package-info.java b/src/main/java/io/reactivex/rxjava3/core/package-info.java index 91717d01781..ee76f76a64a 100644 --- a/src/main/java/io/reactivex/rxjava3/core/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/core/package-info.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + /** * Base reactive classes: {@link io.reactivex.rxjava3.core.Flowable}, {@link io.reactivex.rxjava3.core.Observable}, * {@link io.reactivex.rxjava3.core.Single}, {@link io.reactivex.rxjava3.core.Maybe} and diff --git a/src/main/java/io/reactivex/rxjava3/disposables/ActionDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/ActionDisposable.java index 32ad4786566..4caad11d792 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/ActionDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/ActionDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/disposables/AutoCloseableDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/AutoCloseableDisposable.java index 08cbe9cd99c..34cdaed0eb6 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/AutoCloseableDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/AutoCloseableDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/disposables/CompositeDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/CompositeDisposable.java index f877dc13810..bcf28ec148d 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/CompositeDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/CompositeDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import java.util.*; diff --git a/src/main/java/io/reactivex/rxjava3/disposables/Disposable.java b/src/main/java/io/reactivex/rxjava3/disposables/Disposable.java index d71a452cb11..845d603171c 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/Disposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/Disposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import io.reactivex.rxjava3.annotations.NonNull; @@ -39,8 +40,8 @@ public interface Disposable { /** * Construct a {@code Disposable} by wrapping a {@link Runnable} that is * executed exactly once when the {@code Disposable} is disposed. - * @param run the Runnable to wrap - * @return the new Disposable instance + * @param run the {@code Runnable} to wrap + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code run} is {@code null} * @since 3.0.0 */ @@ -53,8 +54,8 @@ static Disposable fromRunnable(@NonNull Runnable run) { /** * Construct a {@code Disposable} by wrapping a {@link Action} that is * executed exactly once when the {@code Disposable} is disposed. - * @param action the Action to wrap - * @return the new Disposable instance + * @param action the {@code Action} to wrap + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code action} is {@code null} * @since 3.0.0 */ @@ -69,8 +70,8 @@ static Disposable fromAction(@NonNull Action action) { * cancelled exactly once when the {@code Disposable} is disposed. *

* The {@code Future} is cancelled with {@code mayInterruptIfRunning == true}. - * @param future the Future to wrap - * @return the new Disposable instance + * @param future the {@code Future} to wrap + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code future} is {@code null} * @see #fromFuture(Future, boolean) * @since 3.0.0 @@ -84,9 +85,9 @@ static Disposable fromFuture(@NonNull Future future) { /** * Construct a {@code Disposable} by wrapping a {@link Future} that is * cancelled exactly once when the {@code Disposable} is disposed. - * @param future the Future to wrap + * @param future the {@code Future} to wrap * @param allowInterrupt if true, the future cancel happens via {@code Future.cancel(true)} - * @return the new Disposable instance + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code future} is {@code null} * @since 3.0.0 */ @@ -99,8 +100,8 @@ static Disposable fromFuture(@NonNull Future future, boolean allowInterrupt) /** * Construct a {@code Disposable} by wrapping a {@link Subscription} that is * cancelled exactly once when the {@code Disposable} is disposed. - * @param subscription the Runnable to wrap - * @return the new Disposable instance + * @param subscription the {@code Runnable} to wrap + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code subscription} is {@code null} * @since 3.0.0 */ @@ -113,8 +114,8 @@ static Disposable fromSubscription(@NonNull Subscription subscription) { /** * Construct a {@code Disposable} by wrapping an {@link AutoCloseable} that is * closed exactly once when the {@code Disposable} is disposed. - * @param autoCloseable the AutoCloseable to wrap - * @return the new Disposable instance + * @param autoCloseable the {@code AutoCloseable} to wrap + * @return the new {@code Disposable} instance * @throws NullPointerException if {@code autoCloseable} is {@code null} * @since 3.0.0 */ @@ -127,8 +128,8 @@ static Disposable fromAutoCloseable(@NonNull AutoCloseable autoCloseable) { /** * Construct an {@link AutoCloseable} by wrapping a {@code Disposable} that is * disposed when the returned {@code AutoCloseable} is closed. - * @param disposable the Disposable instance - * @return the new AutoCloseable instance + * @param disposable the {@code Disposable} instance + * @return the new {@code AutoCloseable} instance * @throws NullPointerException if {@code disposable} is {@code null} * @since 3.0.0 */ diff --git a/src/main/java/io/reactivex/rxjava3/disposables/DisposableContainer.java b/src/main/java/io/reactivex/rxjava3/disposables/DisposableContainer.java index d7099fbadc2..49311e40829 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/DisposableContainer.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/DisposableContainer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/disposables/FutureDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/FutureDisposable.java index 9649bcd7d3c..d8f70ff6554 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/FutureDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/FutureDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import java.util.concurrent.Future; diff --git a/src/main/java/io/reactivex/rxjava3/disposables/ReferenceDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/ReferenceDisposable.java index eea584ab0b7..55bb24a2687 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/ReferenceDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/ReferenceDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/disposables/RunnableDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/RunnableDisposable.java index 34203e86a99..390a7912b4a 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/RunnableDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/RunnableDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/disposables/SerialDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/SerialDisposable.java index 1f408f8c944..7b1f6463a86 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/SerialDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/SerialDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/disposables/SubscriptionDisposable.java b/src/main/java/io/reactivex/rxjava3/disposables/SubscriptionDisposable.java index f6756b58de2..48c5c7ab3d1 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/SubscriptionDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/SubscriptionDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.disposables; import org.reactivestreams.Subscription; diff --git a/src/main/java/io/reactivex/rxjava3/disposables/package-info.java b/src/main/java/io/reactivex/rxjava3/disposables/package-info.java index 29812d0ab76..00ff5dd6ffc 100644 --- a/src/main/java/io/reactivex/rxjava3/disposables/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/disposables/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/CompositeException.java b/src/main/java/io/reactivex/rxjava3/exceptions/CompositeException.java index d7a3457fe49..5d2928b28fe 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/CompositeException.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/CompositeException.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.exceptions; import java.io.*; @@ -201,38 +199,41 @@ public void printStackTrace(PrintWriter s) { * Special handling for printing out a {@code CompositeException}. * Loops through all inner exceptions and prints them out. * - * @param s + * @param output * stream to print to */ - private void printStackTrace(PrintStreamOrWriter s) { - StringBuilder b = new StringBuilder(128); - b.append(this).append('\n'); + private void printStackTrace(PrintStreamOrWriter output) { + output.append(this).append("\n"); for (StackTraceElement myStackElement : getStackTrace()) { - b.append("\tat ").append(myStackElement).append('\n'); + output.append("\tat ").append(myStackElement).append("\n"); } int i = 1; for (Throwable ex : exceptions) { - b.append(" ComposedException ").append(i).append(" :\n"); - appendStackTrace(b, ex, "\t"); + output.append(" ComposedException ").append(i).append(" :\n"); + appendStackTrace(output, ex, "\t"); i++; } - s.println(b.toString()); + output.append("\n"); } - private void appendStackTrace(StringBuilder b, Throwable ex, String prefix) { - b.append(prefix).append(ex).append('\n'); + private void appendStackTrace(PrintStreamOrWriter output, Throwable ex, String prefix) { + output.append(prefix).append(ex).append('\n'); for (StackTraceElement stackElement : ex.getStackTrace()) { - b.append("\t\tat ").append(stackElement).append('\n'); + output.append("\t\tat ").append(stackElement).append('\n'); } if (ex.getCause() != null) { - b.append("\tCaused by: "); - appendStackTrace(b, ex.getCause(), ""); + output.append("\tCaused by: "); + appendStackTrace(output, ex.getCause(), ""); } } abstract static class PrintStreamOrWriter { - /** Prints the specified string as a line on this StreamOrWriter. */ - abstract void println(Object o); + /** + * Prints the object's string representation via the underlying PrintStream or PrintWriter. + * @param o the object to print + * @return this + */ + abstract PrintStreamOrWriter append(Object o); } /** @@ -246,11 +247,15 @@ static final class WrappedPrintStream extends PrintStreamOrWriter { } @Override - void println(Object o) { - printStream.println(o); + WrappedPrintStream append(Object o) { + printStream.print(o); + return this; } } + /** + * Same abstraction and implementation as in JDK to allow PrintStream and PrintWriter to share implementation. + */ static final class WrappedPrintWriter extends PrintStreamOrWriter { private final PrintWriter printWriter; @@ -259,8 +264,9 @@ static final class WrappedPrintWriter extends PrintStreamOrWriter { } @Override - void println(Object o) { - printWriter.println(o); + WrappedPrintWriter append(Object o) { + printWriter.print(o); + return this; } } diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/Exceptions.java b/src/main/java/io/reactivex/rxjava3/exceptions/Exceptions.java index 41ddbd4fed9..155a2801d27 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/Exceptions.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/Exceptions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/MissingBackpressureException.java b/src/main/java/io/reactivex/rxjava3/exceptions/MissingBackpressureException.java index f7b19a2fc2e..f0a173ba590 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/MissingBackpressureException.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/MissingBackpressureException.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,6 +20,15 @@ public final class MissingBackpressureException extends RuntimeException { private static final long serialVersionUID = 8517344746016032542L; + /** + * The default error message. + *

+ * This can happen if the downstream doesn't call {@link org.reactivestreams.Subscription#request(long)} + * in time or at all. + * @since 3.1.6 + */ + public static final String DEFAULT_MESSAGE = "Could not emit value due to lack of requests"; + /** * Constructs a MissingBackpressureException without message or cause. */ @@ -35,4 +44,13 @@ public MissingBackpressureException(String message) { super(message); } + /** + * Constructs a new {@code MissingBackpressureException} with the + * default message {@value #DEFAULT_MESSAGE}. + * @return the new {@code MissingBackpressureException} instance. + * @since 3.1.6 + */ + public static MissingBackpressureException createDefault() { + return new MissingBackpressureException(DEFAULT_MESSAGE); + } } diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedException.java b/src/main/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedException.java index d70769af39e..072b889a579 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedException.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedException.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -50,4 +50,4 @@ public OnErrorNotImplementedException(String message, @NonNull Throwable e) { public OnErrorNotImplementedException(@NonNull Throwable e) { this("The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | " + e, e); } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/ProtocolViolationException.java b/src/main/java/io/reactivex/rxjava3/exceptions/ProtocolViolationException.java index 9df2ed97625..66fab7f911d 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/ProtocolViolationException.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/ProtocolViolationException.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/QueueOverflowException.java b/src/main/java/io/reactivex/rxjava3/exceptions/QueueOverflowException.java new file mode 100644 index 00000000000..bdd8a25e6f1 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/exceptions/QueueOverflowException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.exceptions; + +/** + * Indicates an overflow happened because the upstream disregarded backpressure completely or + * {@link org.reactivestreams.Subscriber#onNext(Object)} was called concurrently from multiple threads + * without synchronization. Rarely, it is an indication of bugs inside an operator. + * @since 3.1.6 + */ +public final class QueueOverflowException extends RuntimeException { + + private static final long serialVersionUID = 8517344746016032542L; + + /** + * The message for queue overflows. + *

+ * This can happen if the upstream disregards backpressure completely or calls + * {@link org.reactivestreams.Subscriber#onNext(Object)} concurrently from multiple threads + * without synchronization. Rarely, it is an indication of bugs inside an operator. + */ + private static final String DEFAULT_MESSAGE = "Queue overflow due to illegal concurrent onNext calls or a bug in an operator"; + + /** + * Constructs a QueueOverflowException with the default message. + */ + public QueueOverflowException() { + this(DEFAULT_MESSAGE); + } + + /** + * Constructs a QueueOverflowException with the given message but no cause. + * @param message the error message + */ + public QueueOverflowException(String message) { + super(message); + } +} diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/UndeliverableException.java b/src/main/java/io/reactivex/rxjava3/exceptions/UndeliverableException.java index 08f926e9b3c..11a4c07f8a5 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/UndeliverableException.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/UndeliverableException.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/exceptions/package-info.java b/src/main/java/io/reactivex/rxjava3/exceptions/package-info.java index 05ebb5bfb3a..91de82962f9 100644 --- a/src/main/java/io/reactivex/rxjava3/exceptions/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/exceptions/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/flowables/ConnectableFlowable.java b/src/main/java/io/reactivex/rxjava3/flowables/ConnectableFlowable.java index 3e80c68cedd..133d0186c8b 100644 --- a/src/main/java/io/reactivex/rxjava3/flowables/ConnectableFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/flowables/ConnectableFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,7 +16,7 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; -import org.reactivestreams.Subscriber; +import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.*; @@ -34,12 +34,12 @@ * can wait for all intended {@link Subscriber}s to {@link Flowable#subscribe} to the {@code Flowable} * before the {@code Flowable} begins emitting items. *

- * + * *

* When the upstream terminates, the {@code ConnectableFlowable} remains in this terminated state and, - * depending on the actual underlying implementation, relays cached events to late {@link Subscriber}s. + * depending on the actual underlying implementation, relays cached events to late {@code Subscriber}s. * In order to reuse and restart this {@code ConnectableFlowable}, the {@link #reset()} method has to be called. - * When called, this {@code ConnectableFlowable} will appear as fresh, unconnected source to new {@link Subscriber}s. + * When called, this {@code ConnectableFlowable} will appear as fresh, unconnected source to new {@code Subscriber}s. * Disposing the connection will reset the {@code ConnectableFlowable} to its fresh state and there is no need to call * {@code reset()} in this case. *

@@ -48,8 +48,7 @@ * there is no unwanted signal loss due to early {@code connect()} or {@code reset()} calls while {@code Subscriber}s are * still being subscribed to to this {@code ConnectableFlowable} to receive signals from the get go. *

- * @see RxJava Wiki: - * Connectable Observable Operators + * @see RxJava Wiki: Connectable Observable Operators * @param * the type of items emitted by the {@code ConnectableFlowable} * @since 2.0.0 @@ -74,7 +73,7 @@ public abstract class ConnectableFlowable extends Flowable { public abstract void connect(@NonNull Consumer connection); /** - * Resets this ConnectableFlowable into its fresh state if it has terminated. + * Resets this {@code ConnectableFlowable} into its fresh state if it has terminated. *

* Calling this method on a fresh or active {@code ConnectableFlowable} has no effect. *

@@ -108,7 +107,7 @@ public final Disposable connect() { } /** - * Returns a {@code Flowable} that stays connected to this {@code ConnectableFlowable} as long as there + * Returns a {@link Flowable} that stays connected to this {@code ConnectableFlowable} as long as there * is at least one subscription to this {@code ConnectableFlowable}. *
*
Backpressure:
@@ -117,7 +116,7 @@ public final Disposable connect() { *
Scheduler:
*
This {@code refCount} overload does not operate on any particular {@link Scheduler}.
*
- * @return a {@link Flowable} + * @return the new {@code Flowable} instance * @see ReactiveX documentation: RefCount * @see #refCount(int) * @see #refCount(long, TimeUnit) @@ -143,7 +142,8 @@ public Flowable refCount() { *
*

History: 2.1.14 - experimental * @param subscriberCount the number of subscribers required to connect to the upstream - * @return the new Flowable instance + * @return the new {@link Flowable} instance + * @throws IllegalArgumentException if {@code subscriberCount} is non-positive * @since 2.2 */ @CheckReturnValue @@ -168,7 +168,7 @@ public final Flowable refCount(int subscriberCount) { *

History: 2.1.14 - experimental * @param timeout the time to wait before disconnecting after all subscribers unsubscribed * @param unit the time unit of the timeout - * @return the new Flowable instance + * @return the new {@link Flowable} instance * @throws NullPointerException if {@code unit} is {@code null} * @see #refCount(long, TimeUnit, Scheduler) * @since 2.2 @@ -196,7 +196,7 @@ public final Flowable refCount(long timeout, @NonNull TimeUnit unit) { * @param timeout the time to wait before disconnecting after all subscribers unsubscribed * @param unit the time unit of the timeout * @param scheduler the target scheduler to wait on before disconnecting - * @return the new Flowable instance + * @return the new {@link Flowable} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} * @since 2.2 */ @@ -223,8 +223,9 @@ public final Flowable refCount(long timeout, @NonNull TimeUnit unit, @NonNull * @param subscriberCount the number of subscribers required to connect to the upstream * @param timeout the time to wait before disconnecting after all subscribers unsubscribed * @param unit the time unit of the timeout - * @return the new Flowable instance + * @return the new {@link Flowable} instance * @throws NullPointerException if {@code unit} is {@code null} + * @throws IllegalArgumentException if {@code subscriberCount} is non-positive * @see #refCount(int, long, TimeUnit, Scheduler) * @since 2.2 */ @@ -252,7 +253,7 @@ public final Flowable refCount(int subscriberCount, long timeout, @NonNull Ti * @param timeout the time to wait before disconnecting after all subscribers unsubscribed * @param unit the time unit of the timeout * @param scheduler the target scheduler to wait on before disconnecting - * @return the new Flowable instance + * @return the new {@link Flowable} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} * @throws IllegalArgumentException if {@code subscriberCount} is non-positive * @since 2.2 @@ -269,20 +270,20 @@ public final Flowable refCount(int subscriberCount, long timeout, @NonNull Ti } /** - * Returns a Flowable that automatically connects (at most once) to this ConnectableFlowable - * when the first Subscriber subscribes. + * Returns a {@link Flowable} that automatically connects (at most once) to this {@code ConnectableFlowable} + * when the first {@link Subscriber} subscribes. *

* *

* The connection happens after the first subscription and happens at most once - * during the lifetime of the returned Flowable. If this ConnectableFlowable - * terminates, the connection is never renewed, no matter how Subscribers come + * during the lifetime of the returned {@code Flowable}. If this {@code ConnectableFlowable} + * terminates, the connection is never renewed, no matter how {@code Subscriber}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active - * connection when all {@code Subscriber}s have cancelled their {@code Subscription}s. + * connection when all {@code Subscriber}s have cancelled their {@link Subscription}s. *

* This overload does not allow disconnecting the connection established via * {@link #connect(Consumer)}. Use the {@link #autoConnect(int, Consumer)} overload - * to gain access to the {@code Disposable} representing the only connection. + * to gain access to the {@link Disposable} representing the only connection. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by @@ -291,8 +292,8 @@ public final Flowable refCount(int subscriberCount, long timeout, @NonNull Ti *
{@code autoConnect} does not operate by default on a particular {@link Scheduler}.
*
* - * @return a Flowable that automatically connects to this ConnectableFlowable - * when the first Subscriber subscribes + * @return a new {@code Flowable} instance that automatically connects to this {@code ConnectableFlowable} + * when the first {@code Subscriber} subscribes * @see #refCount() * @see #autoConnect(int, Consumer) */ @@ -304,20 +305,20 @@ public Flowable autoConnect() { return autoConnect(1); } /** - * Returns a Flowable that automatically connects (at most once) to this ConnectableFlowable - * when the specified number of Subscribers subscribe to it. + * Returns a {@link Flowable} that automatically connects (at most once) to this {@code ConnectableFlowable} + * when the specified number of {@link Subscriber}s subscribe to it. *

* *

* The connection happens after the given number of subscriptions and happens at most once - * during the lifetime of the returned Flowable. If this ConnectableFlowable - * terminates, the connection is never renewed, no matter how Subscribers come + * during the lifetime of the returned {@code Flowable}. If this {@code ConnectableFlowable} + * terminates, the connection is never renewed, no matter how {@code Subscriber}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active - * connection when all {@code Subscriber}s have cancelled their {@code Subscription}s. + * connection when all {@code Subscriber}s have cancelled their {@link Subscription}s. *

* This overload does not allow disconnecting the connection established via * {@link #connect(Consumer)}. Use the {@link #autoConnect(int, Consumer)} overload - * to gain access to the {@code Disposable} representing the only connection. + * to gain access to the {@link Disposable} representing the only connection. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by @@ -327,10 +328,10 @@ public Flowable autoConnect() { *
* * @param numberOfSubscribers the number of subscribers to await before calling connect - * on the ConnectableFlowable. A non-positive value indicates + * on the {@code ConnectableFlowable}. A non-positive value indicates * an immediate connection. - * @return a Flowable that automatically connects to this ConnectableFlowable - * when the specified number of Subscribers subscribe to it + * @return a new {@code Flowable} instance that automatically connects to this {@code ConnectableFlowable} + * when the specified number of {@code Subscriber}s subscribe to it */ @NonNull @CheckReturnValue @@ -341,17 +342,17 @@ public Flowable autoConnect(int numberOfSubscribers) { } /** - * Returns a Flowable that automatically connects (at most once) to this ConnectableFlowable - * when the specified number of Subscribers subscribe to it and calls the - * specified callback with the Subscription associated with the established connection. + * Returns a {@link Flowable} that automatically connects (at most once) to this {@code ConnectableFlowable} + * when the specified number of {@link Subscriber}s subscribe to it and calls the + * specified callback with the {@link Disposable} associated with the established connection. *

* *

* The connection happens after the given number of subscriptions and happens at most once - * during the lifetime of the returned Flowable. If this ConnectableFlowable - * terminates, the connection is never renewed, no matter how Subscribers come + * during the lifetime of the returned {@code Flowable}. If this {@code ConnectableFlowable} + * terminates, the connection is never renewed, no matter how {@code Subscriber}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active - * connection when all {@code Subscriber}s have cancelled their {@code Subscription}s. + * connection when all {@code Subscriber}s have cancelled their {@link Subscription}s. *

*
Backpressure:
*
The operator itself doesn't interfere with backpressure which is determined by @@ -361,13 +362,13 @@ public Flowable autoConnect(int numberOfSubscribers) { *
* * @param numberOfSubscribers the number of subscribers to await before calling connect - * on the ConnectableFlowable. A non-positive value indicates + * on the {@code ConnectableFlowable}. A non-positive value indicates * an immediate connection. - * @param connection the callback Consumer that will receive the Subscription representing the + * @param connection the callback {@link Consumer} that will receive the {@code Disposable} representing the * established connection - * @return a Flowable that automatically connects to this ConnectableFlowable - * when the specified number of Subscribers subscribe to it and calls the - * specified callback with the Subscription associated with the established connection + * @return a new {@code Flowable} instance that automatically connects to this {@code ConnectableFlowable} + * when the specified number of {@code Subscriber}s subscribe to it and calls the + * specified callback with the {@code Disposable} associated with the established connection * @throws NullPointerException if {@code connection} is {@code null} */ @NonNull diff --git a/src/main/java/io/reactivex/rxjava3/flowables/GroupedFlowable.java b/src/main/java/io/reactivex/rxjava3/flowables/GroupedFlowable.java index d9564c3e6e0..609fc7808fe 100644 --- a/src/main/java/io/reactivex/rxjava3/flowables/GroupedFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/flowables/GroupedFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowables; import io.reactivex.rxjava3.annotations.Nullable; diff --git a/src/main/java/io/reactivex/rxjava3/flowables/package-info.java b/src/main/java/io/reactivex/rxjava3/flowables/package-info.java index 75a6dec4e96..06475a34ea9 100644 --- a/src/main/java/io/reactivex/rxjava3/flowables/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/flowables/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/functions/Action.java b/src/main/java/io/reactivex/rxjava3/functions/Action.java index da0e76e0a62..509e5fcb64b 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Action.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Action.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/BiConsumer.java b/src/main/java/io/reactivex/rxjava3/functions/BiConsumer.java index 85ce3dbd17d..09fec68cbf3 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/BiConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/functions/BiConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/BiFunction.java b/src/main/java/io/reactivex/rxjava3/functions/BiFunction.java index 0724ef5bd1c..27aa9ee016c 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/BiFunction.java +++ b/src/main/java/io/reactivex/rxjava3/functions/BiFunction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/BiPredicate.java b/src/main/java/io/reactivex/rxjava3/functions/BiPredicate.java index 393ec86ab70..e45397aab78 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/BiPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/functions/BiPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/BooleanSupplier.java b/src/main/java/io/reactivex/rxjava3/functions/BooleanSupplier.java index b30087fbd7b..4e3b447b6e1 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/BooleanSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/functions/BooleanSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Cancellable.java b/src/main/java/io/reactivex/rxjava3/functions/Cancellable.java index b9f3420c1b5..574c8322681 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Cancellable.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Cancellable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Consumer.java b/src/main/java/io/reactivex/rxjava3/functions/Consumer.java index bf245bdcb76..3ac1806438d 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Consumer.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Consumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function.java b/src/main/java/io/reactivex/rxjava3/functions/Function.java index 0f8b2fe39ac..40e11ca3bae 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function3.java b/src/main/java/io/reactivex/rxjava3/functions/Function3.java index fb1fe5aa768..377cceaeafd 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function3.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function3.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function4.java b/src/main/java/io/reactivex/rxjava3/functions/Function4.java index 9c0af4737de..36db3858191 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function4.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function4.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function5.java b/src/main/java/io/reactivex/rxjava3/functions/Function5.java index fddaa28152e..d3fc1504c41 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function5.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function5.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function6.java b/src/main/java/io/reactivex/rxjava3/functions/Function6.java index 1f6ad10d204..2969a39f823 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function6.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function6.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function7.java b/src/main/java/io/reactivex/rxjava3/functions/Function7.java index 39a6b26916a..091b2032964 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function7.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function7.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function8.java b/src/main/java/io/reactivex/rxjava3/functions/Function8.java index 907c68cdfe5..c8e21acf9d4 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function8.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function8.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Function9.java b/src/main/java/io/reactivex/rxjava3/functions/Function9.java index a7f7518456a..0b182eb5f3c 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Function9.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Function9.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/IntFunction.java b/src/main/java/io/reactivex/rxjava3/functions/IntFunction.java index 9859bfd3c68..3a405aac263 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/IntFunction.java +++ b/src/main/java/io/reactivex/rxjava3/functions/IntFunction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.functions; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/functions/LongConsumer.java b/src/main/java/io/reactivex/rxjava3/functions/LongConsumer.java index 9af7de4f477..5b12752c1d0 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/LongConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/functions/LongConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.functions; /** diff --git a/src/main/java/io/reactivex/rxjava3/functions/Predicate.java b/src/main/java/io/reactivex/rxjava3/functions/Predicate.java index 550a365e604..1bce2d6bffe 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Predicate.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Predicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/functions/Supplier.java b/src/main/java/io/reactivex/rxjava3/functions/Supplier.java index 5a6245f05df..ebf7fdda6d9 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/Supplier.java +++ b/src/main/java/io/reactivex/rxjava3/functions/Supplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,8 +13,6 @@ package io.reactivex.rxjava3.functions; -import io.reactivex.rxjava3.annotations.NonNull; - /** * A functional interface (callback) that provides a single value or * throws an exception. @@ -25,7 +23,7 @@ * @since 3.0.0 */ @FunctionalInterface -public interface Supplier<@NonNull T> { +public interface Supplier { /** * Produces a value or throws an exception. diff --git a/src/main/java/io/reactivex/rxjava3/functions/package-info.java b/src/main/java/io/reactivex/rxjava3/functions/package-info.java index a7d92ce8fb8..ab9dad0426f 100644 --- a/src/main/java/io/reactivex/rxjava3/functions/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/functions/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposable.java index 5ebcdde15b6..c9a6bc9bc49 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposable.java index 314464e156e..863f52e91bc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/DisposableHelper.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/DisposableHelper.java index 1f2d2122d1b..79dbd855aca 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/DisposableHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/DisposableHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposable.java index 51acc86c752..fdb30932ed5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; /** * Represents a stateless empty Disposable that reports being always diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposable.java index 8a6d4dd9923..4c4b1f8a73e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.disposables; import java.util.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/disposables/SequentialDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/disposables/SequentialDisposable.java index d9922ebec80..f6aef6bdd3f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/disposables/SequentialDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/disposables/SequentialDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/functions/Functions.java b/src/main/java/io/reactivex/rxjava3/internal/functions/Functions.java index 1d3055eb2b6..e0d3dead3c5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/functions/Functions.java +++ b/src/main/java/io/reactivex/rxjava3/internal/functions/Functions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.functions; import java.util.*; @@ -281,13 +282,8 @@ public static Predicate equalsWith(T value) { return new EqualsPredicate<>(value); } - enum HashSetCallable implements Supplier>, Callable> { + enum HashSetSupplier implements Supplier> { INSTANCE; - @Override - public Set call() { - return new HashSet<>(); - } - @Override public Set get() { return new HashSet<>(); @@ -296,7 +292,7 @@ public Set get() { @SuppressWarnings({ "rawtypes", "unchecked" }) public static Supplier> createHashSet() { - return (Supplier)HashSetCallable.INSTANCE; + return (Supplier)HashSetSupplier.INSTANCE; } static final class NotificationOnNext implements Consumer { @@ -742,12 +738,7 @@ public boolean test(Object o) { } } - static final class NullProvider implements Callable, Supplier { - @Override - public Object call() { - return null; - } - + static final class NullProvider implements Supplier { @Override public Object get() { return null; diff --git a/src/main/java/io/reactivex/rxjava3/internal/functions/ObjectHelper.java b/src/main/java/io/reactivex/rxjava3/internal/functions/ObjectHelper.java index 05bceafa1d2..5bbdf22ad3f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/functions/ObjectHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/functions/ObjectHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.functions; import io.reactivex.rxjava3.functions.BiPredicate; diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java index 071db9fff8f..13732bd426d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,6 +14,9 @@ package io.reactivex.rxjava3.internal.fuseable; import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * Represents an empty, async-only {@link QueueFuseable} instance. @@ -73,4 +76,4 @@ public void dispose() { public boolean isDisposed() { return false; } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java index 8f9e12d3cbf..71f993e2267 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,6 +13,8 @@ package io.reactivex.rxjava3.internal.fuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; + /** * Represents an empty, async-only {@link QueueFuseable} instance that tracks and exposes a * canceled/disposed state. @@ -39,4 +41,4 @@ public void dispose() { public boolean isDisposed() { return disposed; } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToFlowable.java index 6ad462c7060..fe70b40a011 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,10 @@ * the operator goes from Flowable to some other reactive type and then the sequence calls * for toFlowable again: *
- * Single<Integer> single = Flowable.range(1, 10).reduce((a, b) -> a + b);
- * Flowable<Integer> flowable = single.toFlowable();
+ * {@code
+ * Single single = Flowable.range(1, 10).reduce((a, b) -> a + b);
+ * Flowable flowable = single.toFlowable();
+ * }
  * 
* * The {@code Single.toFlowable()} will check for this interface and call the {@link #fuseToFlowable()} diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToMaybe.java index 572255a7bcd..13ccd6be751 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,10 @@ * the operator goes from Maybe to some other reactive type and then the sequence calls * for toMaybe again: *
- * Single<Integer> single = Maybe.just(1).isEmpty();
- * Maybe<Integer> maybe = single.toMaybe();
+ * {@code
+ * Single single = Maybe.just(1).isEmpty();
+ * Maybe maybe = single.toMaybe();
+ * }
  * 
* * The {@code Single.toMaybe()} will check for this interface and call the {@link #fuseToMaybe()} diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToObservable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToObservable.java index 567d3c9a7c7..d7ae761e379 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/FuseToObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,10 @@ * the operator goes from Observable to some other reactive type and then the sequence calls * for toObservable again: *
- * Single<Integer> single = Observable.range(1, 10).reduce((a, b) -> a + b);
- * Observable<Integer> observable = single.toObservable();
+ * {@code
+ * Single single = Observable.range(1, 10).reduce((a, b) -> a + b);
+ * Observable observable = single.toObservable();
+ * }
  * 
* * The {@code Single.toObservable()} will check for this interface and call the {@link #fuseToObservable()} diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamCompletableSource.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamCompletableSource.java index cb6c18edd56..fddb14ef0b7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamCompletableSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamCompletableSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamMaybeSource.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamMaybeSource.java index 6f4fcd9085a..121e2937e44 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamMaybeSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamMaybeSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamObservableSource.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamObservableSource.java index 8bd340a6c06..1a1e878b650 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamObservableSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamObservableSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamPublisher.java index a412b37e1da..5a46f38555e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamSingleSource.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamSingleSource.java index dfab10fd9e3..ef833ae2ff6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamSingleSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/HasUpstreamSingleSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/package-info.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/package-info.java index b4ee8690766..339eabbfd27 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/package-info.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStage.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStage.java index 44f539bf4bf..639516d005a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStage.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStage.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletionStage; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletionStageConsumer.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletionStageConsumer.java index d92e56041e1..24102907343 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletionStageConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletionStageConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollector.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollector.java index bc408db3046..63ca949295b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.Objects; @@ -36,9 +37,9 @@ public final class FlowableCollectWithCollector extends Flowable { final Flowable source; - final Collector collector; + final Collector collector; - public FlowableCollectWithCollector(Flowable source, Collector collector) { + public FlowableCollectWithCollector(Flowable source, Collector collector) { this.source = source; this.collector = collector; } @@ -46,7 +47,7 @@ public FlowableCollectWithCollector(Flowable source, Collector colle @Override protected void subscribeActual(@NonNull Subscriber s) { A container; - BiConsumer accumulator; + BiConsumer accumulator; Function finisher; try { diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorSingle.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorSingle.java index 134de68415e..aba390e1da0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.Objects; @@ -39,9 +40,9 @@ public final class FlowableCollectWithCollectorSingle extends Single final Flowable source; - final Collector collector; + final Collector collector; - public FlowableCollectWithCollectorSingle(Flowable source, Collector collector) { + public FlowableCollectWithCollectorSingle(Flowable source, Collector collector) { this.source = source; this.collector = collector; } @@ -54,7 +55,7 @@ public Flowable fuseToFlowable() { @Override protected void subscribeActual(@NonNull SingleObserver observer) { A container; - BiConsumer accumulator; + BiConsumer accumulator; Function finisher; try { diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFirstStageSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFirstStageSubscriber.java index 5af6cc5aaca..19bfcbff6dc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFirstStageSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFirstStageSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStream.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStream.java index b01b24748a8..48ea8b6e5f0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,10 +23,12 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -172,7 +174,7 @@ public void onNext(T t) { if (sourceMode != QueueFuseable.ASYNC) { if (!queue.offer(t)) { upstream.cancel(); - onError(new MissingBackpressureException("Queue full?!")); + onError(new QueueOverflowException()); return; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStage.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStage.java index f864cdd96d6..1ee0f7786ed 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStage.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStage.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletionStage; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStream.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStream.java index 55ec854ddfd..4fd3b4eb007 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.Iterator; @@ -22,9 +23,10 @@ import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableLastStageSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableLastStageSubscriber.java index c9a93eeb0ea..0bdf3e93043 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableLastStageSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableLastStageSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptional.java index 3fdcd40a4f7..cc4ff8bdf50 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.*; @@ -18,8 +19,8 @@ import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscribers.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; /** * Map the upstream values into an Optional and emit its value if any. diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableSingleStageSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableSingleStageSubscriber.java index 8040ec6f5d8..8206a9a8ac6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableSingleStageSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableSingleStageSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriber.java index 6594b7ba5c6..66e4fddde7d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletableFuture; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowable.java index 0ac724bdf42..653642426ed 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservable.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservable.java index e7a74f0593b..404fcb8106f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStage.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStage.java index d8523b8ead5..45af605e968 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStage.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStage.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletionStage; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptional.java index 8330d5249a2..760456f2ee6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollector.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollector.java index 34132a01b33..980317750ee 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.Objects; @@ -36,9 +37,9 @@ public final class ObservableCollectWithCollector extends Observable final Observable source; - final Collector collector; + final Collector collector; - public ObservableCollectWithCollector(Observable source, Collector collector) { + public ObservableCollectWithCollector(Observable source, Collector collector) { this.source = source; this.collector = collector; } @@ -46,7 +47,7 @@ public ObservableCollectWithCollector(Observable source, Collector c @Override protected void subscribeActual(@NonNull Observer observer) { A container; - BiConsumer accumulator; + BiConsumer accumulator; Function finisher; try { diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorSingle.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorSingle.java index a919b02ab9e..fa1ccd9c8fb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.Objects; @@ -36,9 +37,9 @@ public final class ObservableCollectWithCollectorSingle extends Single< final Observable source; - final Collector collector; + final Collector collector; - public ObservableCollectWithCollectorSingle(Observable source, Collector collector) { + public ObservableCollectWithCollectorSingle(Observable source, Collector collector) { this.source = source; this.collector = collector; } @@ -51,7 +52,7 @@ public Observable fuseToObservable() { @Override protected void subscribeActual(@NonNull SingleObserver observer) { A container; - BiConsumer accumulator; + BiConsumer accumulator; Function finisher; try { diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFirstStageObserver.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFirstStageObserver.java index cda0073067c..6ac5ae51f10 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFirstStageObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFirstStageObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStream.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStream.java index 210d920aad5..72bbea2a3f9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStage.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStage.java index 262da56026e..11a5a6307ce 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStage.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStage.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletionStage; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStream.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStream.java index 90d76813037..169eeb0bcc1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.*; @@ -20,7 +21,7 @@ import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableLastStageObserver.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableLastStageObserver.java index e2f9dc2225d..b35ab3dba99 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableLastStageObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableLastStageObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptional.java index eb134482be6..a51ef1af287 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableSingleStageObserver.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableSingleStageObserver.java index fa8714397a6..c506fc36d41 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableSingleStageObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableSingleStageObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.NoSuchElementException; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageObserver.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageObserver.java index 54acae086f9..4025890f171 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletableFuture; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollector.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollector.java index c8802de3f68..7fefa11e802 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStream.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStream.java index 3f38d1fec38..beae3fee367 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptional.java index 350f59f2b24..a31be9a75ef 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptional.java index a2d454c9942..d463c7bbab9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowable.java index d7286d59329..8ed45d40b95 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservable.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservable.java index 81b2d5fd7b9..4733474f138 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStage.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStage.java index f1be64375ec..126a096a267 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStage.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStage.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.jdk8; import java.util.concurrent.CompletionStage; diff --git a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptional.java b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptional.java index 9ee9a6f803f..ad54068d341 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptional.java +++ b/src/main/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptional.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/AbstractDisposableAutoRelease.java b/src/main/java/io/reactivex/rxjava3/internal/observers/AbstractDisposableAutoRelease.java new file mode 100644 index 00000000000..e5d89a4502f --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/AbstractDisposableAutoRelease.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import java.util.concurrent.atomic.AtomicReference; + +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps lambda callbacks and when the upstream terminates or the observer gets disposed, + * removes itself from a {@link io.reactivex.rxjava3.disposables.CompositeDisposable}. + *

History: 0.18.0 @ RxJavaExtensions + * @since 3.1.0 + */ +abstract class AbstractDisposableAutoRelease +extends AtomicReference +implements Disposable, LambdaConsumerIntrospection { + + private static final long serialVersionUID = 8924480688481408726L; + + final AtomicReference composite; + + final Consumer onError; + + final Action onComplete; + + AbstractDisposableAutoRelease( + DisposableContainer composite, + Consumer onError, + Action onComplete + ) { + this.onError = onError; + this.onComplete = onComplete; + this.composite = new AtomicReference<>(composite); + } + + public final void onError(Throwable t) { + if (get() != DisposableHelper.DISPOSED) { + lazySet(DisposableHelper.DISPOSED); + try { + onError.accept(t); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(new CompositeException(t, e)); + } + } else { + RxJavaPlugins.onError(t); + } + removeSelf(); + } + + public final void onComplete() { + if (get() != DisposableHelper.DISPOSED) { + lazySet(DisposableHelper.DISPOSED); + try { + onComplete.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(e); + } + } + removeSelf(); + } + + @Override + public final void dispose() { + DisposableHelper.dispose(this); + removeSelf(); + } + + final void removeSelf() { + DisposableContainer c = composite.getAndSet(null); + if (c != null) { + c.delete(this); + } + } + + @Override + public final boolean isDisposed() { + return DisposableHelper.isDisposed(get()); + } + + public final void onSubscribe(Disposable d) { + DisposableHelper.setOnce(this, d); + } + + @Override + public final boolean hasCustomOnError() { + return onError != Functions.ON_ERROR_MISSING; + } + +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserver.java index 0beef61824e..6bd12f39403 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,7 +17,7 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicIntQueueDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicIntQueueDisposable.java index 84a5c017b58..726db3ae96f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicIntQueueDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicIntQueueDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.AtomicInteger; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; /** * An abstract QueueDisposable implementation, extending an AtomicInteger, diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposable.java index fb6fc08366d..0daaf520a57 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,7 +13,7 @@ package io.reactivex.rxjava3.internal.observers; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; /** * An abstract QueueDisposable implementation that defaults all diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BiConsumerSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BiConsumerSingleObserver.java index 2fb0221f641..1e9696cb15e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BiConsumerSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BiConsumerSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingBaseObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingBaseObserver.java index 9a128799d53..93ce06eedf1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingBaseObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingBaseObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.observers; import java.util.concurrent.CountDownLatch; diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java index da7e289e27a..a2334c21bac 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserver.java index 276848afe46..570000a55a0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingLastObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingLastObserver.java index bf745d3ed1b..c8e979cc313 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingLastObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingLastObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java index 4945730ab52..458e6db5a14 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingObserver.java index da38180751c..ff84f2a4c6f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserver.java index f6e7fed1cd9..be2da69160c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,33 +20,24 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class CallbackCompletableObserver extends AtomicReference - implements CompletableObserver, Disposable, Consumer, LambdaConsumerIntrospection { + implements CompletableObserver, Disposable, LambdaConsumerIntrospection { private static final long serialVersionUID = -4361286194466301354L; final Consumer onError; final Action onComplete; - public CallbackCompletableObserver(Action onComplete) { - this.onError = this; - this.onComplete = onComplete; - } - public CallbackCompletableObserver(Consumer onError, Action onComplete) { this.onError = onError; this.onComplete = onComplete; } - @Override - public void accept(Throwable e) { - RxJavaPlugins.onError(new OnErrorNotImplementedException(e)); - } - @Override public void onComplete() { try { @@ -86,6 +77,6 @@ public boolean isDisposed() { @Override public boolean hasCustomOnError() { - return onError != this; + return onError != Functions.ON_ERROR_MISSING; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserver.java index b29a74e4bb1..eff6e4a0c1e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposable.java b/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposable.java index 57d5f8c5c7a..084ad68571b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserver.java index a99fb49a579..4453e0ffa89 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseMultiObserver.java new file mode 100644 index 00000000000..4779ff5723a --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseMultiObserver.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.DisposableContainer; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps lambda callbacks and when the upstream terminates or this (Single | Maybe | Completable) + * observer gets disposed, removes itself from a {@link io.reactivex.rxjava3.disposables.CompositeDisposable}. + *

History: 0.18.0 @ RxJavaExtensions + * @param the element type consumed + * @since 3.1.0 + */ +public final class DisposableAutoReleaseMultiObserver +extends AbstractDisposableAutoRelease +implements SingleObserver, MaybeObserver, CompletableObserver { + + private static final long serialVersionUID = 8924480688481408726L; + + final Consumer onSuccess; + + public DisposableAutoReleaseMultiObserver( + DisposableContainer composite, + Consumer onSuccess, + Consumer onError, + Action onComplete + ) { + super(composite, onError, onComplete); + this.onSuccess = onSuccess; + } + + @Override + public void onSuccess(T t) { + if (get() != DisposableHelper.DISPOSED) { + lazySet(DisposableHelper.DISPOSED); + try { + onSuccess.accept(t); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(e); + } + } + removeSelf(); + } + +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseObserver.java new file mode 100644 index 00000000000..89435c96ed7 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableAutoReleaseObserver.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.DisposableContainer; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +/** + * Wraps lambda callbacks and when the upstream terminates or this observer gets disposed, + * removes itself from a {@link io.reactivex.rxjava3.disposables.CompositeDisposable}. + *

History: 0.18.0 @ RxJavaExtensions + * @param the element type consumed + * @since 3.1.0 + */ +public final class DisposableAutoReleaseObserver +extends AbstractDisposableAutoRelease +implements Observer { + + private static final long serialVersionUID = 8924480688481408726L; + + final Consumer onNext; + + public DisposableAutoReleaseObserver( + DisposableContainer composite, + Consumer onNext, + Consumer onError, + Action onComplete + ) { + super(composite, onError, onComplete); + this.onNext = onNext; + } + + @Override + public void onNext(T t) { + if (get() != DisposableHelper.DISPOSED) { + try { + onNext.accept(t); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + get().dispose(); + onError(e); + } + } + } + +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserver.java index 2e935140cab..529d651c677 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserver.java index 36a08269c88..e92893b9bd8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/ForEachWhileObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/ForEachWhileObserver.java index 7017239ae0c..bed185523f2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/ForEachWhileObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/ForEachWhileObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java index e2f2aeea5a2..f109aaa5a36 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureObserver.java index 515e23e6bf6..13fd2dc9bff 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -128,22 +128,15 @@ public void onNext(T t) { @Override public void onError(Throwable t) { if (error == null) { - error = t; - - for (;;) { - Disposable a = upstream.get(); - if (a == this || a == DisposableHelper.DISPOSED) { - RxJavaPlugins.onError(t); - return; - } - if (upstream.compareAndSet(a, this)) { - countDown(); - return; - } + Disposable a = upstream.get(); + if (a != this && a != DisposableHelper.DISPOSED + && upstream.compareAndSet(a, this)) { + error = t; + countDown(); + return; } - } else { - RxJavaPlugins.onError(t); } + RxJavaPlugins.onError(t); } @Override @@ -152,15 +145,12 @@ public void onComplete() { onError(new NoSuchElementException("The source is empty")); return; } - for (;;) { - Disposable a = upstream.get(); - if (a == this || a == DisposableHelper.DISPOSED) { - return; - } - if (upstream.compareAndSet(a, this)) { - countDown(); - return; - } + Disposable a = upstream.get(); + if (a == this || a == DisposableHelper.DISPOSED) { + return; + } + if (upstream.compareAndSet(a, this)) { + countDown(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserver.java index db89a98f6e0..9d6417c0e84 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,10 @@ import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.QueueDrainHelper; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Subscriber that can fuse with the upstream and calls a support interface @@ -114,8 +116,4 @@ public void setDone() { public SimpleQueue queue() { return queue; } - - public int fusionMode() { - return fusionMode; - } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverSupport.java b/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverSupport.java index ff28bd092cf..01bebaf0074 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverSupport.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverSupport.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/LambdaObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/LambdaObserver.java index c52017fa4d2..6bd5dece94a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/LambdaObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/LambdaObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserver.java index 67bc900d17d..aa25f4286c9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; /** * Abstract base class for subscribers that hold another subscriber, a queue @@ -57,10 +57,6 @@ public final boolean enter() { return wip.getAndIncrement() == 0; } - public final boolean fastEnter() { - return wip.get() == 0 && wip.compareAndSet(0, 1); - } - protected final void fastPathEmit(U value, boolean delayError, Disposable dispose) { final Observer observer = downstream; final SimplePlainQueue q = queue; diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/ResumeSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/ResumeSingleObserver.java index 90a29bef1c8..acaa71257cd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/ResumeSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/ResumeSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java index d9e929c2346..18e16383af6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java index a6e794b1fdd..320ac534274 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java index 6757350756e..3e73d1e6393 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmb.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmb.java index 14e8ae464b3..60fa3ce4c6d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmb.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmb.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletable.java index d006329aeab..13e582e7646 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCache.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCache.java index da002c0dd6c..c5fd3279d63 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCache.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCache.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcat.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcat.java index c16b847c584..00a53f3ad73 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcat.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcat.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,9 +21,8 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class CompletableConcat extends Completable { @@ -121,7 +120,7 @@ public void onSubscribe(Subscription s) { public void onNext(CompletableSource t) { if (sourceFused == QueueSubscription.NONE) { if (!queue.offer(t)) { - onError(new MissingBackpressureException()); + onError(new QueueOverflowException()); return; } } @@ -182,9 +181,8 @@ void drain() { boolean empty = cs == null; if (d && empty) { - if (once.compareAndSet(false, true)) { - downstream.onComplete(); - } + // errors never set done or call drain. + downstream.onComplete(); return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArray.java index c423c375875..e87968e7749 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatIterable.java index ef801a16461..73510018ffd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreate.java index 40046307563..b721cbb351e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDefer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDefer.java index c451413f490..2a7763bb525 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDefer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDefer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelay.java index 49c25bf6e11..c21134569bc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetach.java index efd28228fa1..d01d297495a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOn.java index 16f9fa159c9..bd213b5fc4c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinally.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinally.java index 425ed4caea8..02fa08cdb04 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinally.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinally.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnEvent.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnEvent.java index 63a408efc42..dfa24b000f8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnEvent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnEvent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableEmpty.java index e18ccc9421a..7c18a4ddc9a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableError.java index 70d4e410064..8d2cb2fcc2a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableErrorSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableErrorSupplier.java index bd4250c447c..80c95806b84 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableErrorSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableErrorSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java index 82bec67c928..53cfc2615bd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallable.java index 57764950df3..90f9266934a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservable.java index d91133e5027..25dffbbebf4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisher.java index 6baeb7a87e4..4205d1141c4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java index 60332d8db24..79f2efb4708 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingle.java index b035f142d99..d55fc303398 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplier.java index e3e29188a0f..8b45e6b5f09 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromUnsafeSource.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromUnsafeSource.java index 02857d46923..dfc0356bf7b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromUnsafeSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromUnsafeSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHide.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHide.java index 16708ee90ed..536855a7b7c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHide.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLift.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLift.java index 58356a73ddd..6749689bccb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLift.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLift.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterialize.java index 15dd320cad4..198ba94b1a6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMerge.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMerge.java index 9d916d84b6b..2528fe2f3bb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMerge.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMerge.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArray.java index ec9c6752102..56095221cca 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -86,9 +86,8 @@ public void onError(Throwable e) { @Override public void onComplete() { if (decrementAndGet() == 0) { - if (once.compareAndSet(false, true)) { - downstream.onComplete(); - } + // errors don't decrement this + downstream.onComplete(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArrayDelayError.java similarity index 96% rename from src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorArray.java rename to src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArrayDelayError.java index 549fd10a48d..85b4c612258 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeArrayDelayError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,11 +19,11 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.internal.util.AtomicThrowable; -public final class CompletableMergeDelayErrorArray extends Completable { +public final class CompletableMergeArrayDelayError extends Completable { final CompletableSource[] sources; - public CompletableMergeDelayErrorArray(CompletableSource[] sources) { + public CompletableMergeArrayDelayError(CompletableSource[] sources) { this.sources = sources; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorIterable.java index 55efbd8915a..cb629747539 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeDelayErrorIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.internal.operators.completable.CompletableMergeDelayErrorArray.*; +import io.reactivex.rxjava3.internal.operators.completable.CompletableMergeArrayDelayError.*; import io.reactivex.rxjava3.internal.util.AtomicThrowable; public final class CompletableMergeDelayErrorIterable extends Completable { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterable.java index b0e5b87bf79..3f2dce90e13 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -128,9 +128,8 @@ public void onError(Throwable e) { @Override public void onComplete() { if (wip.decrementAndGet() == 0) { - if (compareAndSet(false, true)) { - downstream.onComplete(); - } + // errors don't decrement wip + downstream.onComplete(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableNever.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableNever.java index 8c11621a7cd..17bc2cc140c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableNever.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableNever.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOn.java index 8bccc8ced0d..b48ade189fe 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorComplete.java index 6d87a4275e1..c4252e7f3b4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorComplete.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -32,15 +32,18 @@ public CompletableOnErrorComplete(CompletableSource source, Predicate predicate; - OnError(CompletableObserver observer) { + OnError(CompletableObserver observer, + Predicate predicate) { this.downstream = observer; + this.predicate = predicate; } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java index c8fa43499fa..9cd91262a55 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeek.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeek.java index 04955c69311..aeba5381b55 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeek.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeek.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNext.java index 1d3bd7a3a0c..785501511a6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOn.java index f76ac93595b..748602f9780 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilCompletable.java index bd7e519a170..364484ab10b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeout.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeout.java index 1a38bb383a1..80f40dfd723 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeout.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeout.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimer.java index 4e271af7739..b50fd5db2ed 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java index 9a6c0326a11..346267ce134 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java index 84eea97c8de..ccf1a9e5047 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToSingle.java index c35d909796e..58e47247dfc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsing.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsing.java index 3476a65b254..648e6529e23 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsing.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsing.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractBackpressureThrottlingSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractBackpressureThrottlingSubscriber.java new file mode 100644 index 00000000000..62c7d07a88d --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractBackpressureThrottlingSubscriber.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import io.reactivex.rxjava3.core.FlowableSubscriber; +import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Abstract base class for operators that throttle excessive updates from upstream in case if + * downstream {@link Subscriber} is not ready to receive updates. + * + * @param the upstream value type + * @param the downstream value type + */ +abstract class AbstractBackpressureThrottlingSubscriber extends AtomicInteger implements FlowableSubscriber, Subscription { + + private static final long serialVersionUID = -5050301752721603566L; + + final Subscriber downstream; + + Subscription upstream; + + volatile boolean done; + Throwable error; + + volatile boolean cancelled; + + final AtomicLong requested = new AtomicLong(); + + final AtomicReference current = new AtomicReference<>(); + + AbstractBackpressureThrottlingSubscriber(Subscriber downstream) { + this.downstream = downstream; + } + + @Override + public void onSubscribe(Subscription s) { + if (SubscriptionHelper.validate(this.upstream, s)) { + this.upstream = s; + downstream.onSubscribe(this); + s.request(Long.MAX_VALUE); + } + } + + @Override + public abstract void onNext(T t); + + @Override + public void onError(Throwable t) { + error = t; + done = true; + drain(); + } + + @Override + public void onComplete() { + done = true; + drain(); + } + + @Override + public void request(long n) { + if (SubscriptionHelper.validate(n)) { + BackpressureHelper.add(requested, n); + drain(); + } + } + + @Override + public void cancel() { + if (!cancelled) { + cancelled = true; + upstream.cancel(); + + if (getAndIncrement() == 0) { + current.lazySet(null); + } + } + } + + void drain() { + if (getAndIncrement() != 0) { + return; + } + final Subscriber a = downstream; + int missed = 1; + final AtomicLong r = requested; + final AtomicReference q = current; + + for (;;) { + long e = 0L; + + while (e != r.get()) { + boolean d = done; + R v = q.getAndSet(null); + boolean empty = v == null; + + if (checkTerminated(d, empty, a, q)) { + return; + } + + if (empty) { + break; + } + + a.onNext(v); + + e++; + } + + if (e == r.get() && checkTerminated(done, q.get() == null, a, q)) { + return; + } + + if (e != 0L) { + BackpressureHelper.produced(r, e); + } + + missed = addAndGet(-missed); + if (missed == 0) { + break; + } + } + } + + boolean checkTerminated(boolean d, boolean empty, Subscriber a, AtomicReference q) { + if (cancelled) { + q.lazySet(null); + return true; + } + + if (d) { + Throwable e = error; + if (e != null) { + q.lazySet(null); + a.onError(e); + return true; + } else + if (empty) { + a.onComplete(); + return true; + } + } + + return false; + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstream.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstream.java index d83f65c3474..4a9484f7434 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableIterable.java index 51015ce9189..11239d04a7a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,9 +22,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscArrayQueue; public final class BlockingFlowableIterable implements Iterable { final Flowable source; @@ -138,9 +138,12 @@ public void onSubscribe(Subscription s) { @Override public void onNext(T t) { if (!queue.offer(t)) { + // Error must be set first before calling cancel to avoid race + // with hasNext(), which checks for cancel first before checking + // for error. + error = new QueueOverflowException(); SubscriptionHelper.cancel(this); - - onError(new MissingBackpressureException("Queue full?!")); + onComplete(); } else { signalConsumer(); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatest.java index 1cc469a1b9b..7628776ae06 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecent.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecent.java index bfd206eea9c..7c41634c555 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ * Returns an Iterable that always returns the item most recently emitted by an Observable, or a * seed value if no item has yet been emitted. *

- * + * * * @param the value type */ diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNext.java index 57ca264f0cf..9704d2d2103 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,7 +27,7 @@ /** * Returns an Iterable that blocks until the Observable emits another item, then returns that item. *

- * + * * * @param the value type */ @@ -99,11 +99,8 @@ private boolean moveToNext() { if (nextNotification.isOnComplete()) { return false; } - if (nextNotification.isOnError()) { - error = nextNotification.getError(); - throw ExceptionHelper.wrapOrThrow(error); - } - throw new IllegalStateException("Should not reach here"); + error = nextNotification.getError(); + throw ExceptionHelper.wrapOrThrow(error); } catch (InterruptedException e) { subscriber.dispose(); error = e; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAll.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAll.java index 84ea50cbf7d..7f8271733de 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAll.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAll.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllSingle.java index 8d1bf998efc..03d269e738a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.Subscription; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmb.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmb.java index ff650b5719b..5646fdb9937 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmb.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmb.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAny.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAny.java index d0adcb6dbe1..b09dce4c03e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAny.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAny.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnySingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnySingle.java index 7ca8a6b4286..1b210b82d46 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnySingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnySingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.Subscription; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnect.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnect.java index c8bb4a7d1a5..8d4b428c2b9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnect.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnect.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingSubscribe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingSubscribe.java index 26287a0ccc9..22cede1410c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingSubscribe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingSubscribe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBuffer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBuffer.java index 04f5ae182e5..a1cb792f08b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBuffer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBuffer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -133,6 +133,7 @@ public void onError(Throwable t) { RxJavaPlugins.onError(t); return; } + buffer = null; done = true; downstream.onError(t); } @@ -145,8 +146,9 @@ public void onComplete() { done = true; C b = buffer; + buffer = null; - if (b != null && !b.isEmpty()) { + if (b != null) { downstream.onNext(b); } downstream.onComplete(); @@ -390,7 +392,7 @@ public void onNext(T t) { C b = bs.peek(); - if (b != null && b.size() + 1 == size) { + if (b.size() + 1 == size) { bs.poll(); b.add(t); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferBoundary.java index 251144a1d23..b009b1bc250 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,9 +22,9 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableBufferBoundary, Open, Close> diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferExactBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferExactBoundary.java index 8d23e3c7bc1..3e2abefdd98 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferExactBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferExactBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,7 +45,7 @@ protected void subscribeActual(Subscriber s) { } static final class BufferExactBoundarySubscriber, B> - extends QueueDrainSubscriber implements FlowableSubscriber, Subscription, Disposable { + extends QueueDrainSubscriber implements Subscription, Disposable { final Supplier bufferSupplier; final Publisher boundary; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTimed.java index 854e0460ede..89749acaefc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCache.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCache.java index 25d5fb71a32..ee52769e699 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCache.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCache.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollect.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollect.java index b8751a23f90..8f45d624042 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollect.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollect.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollectSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollectSingle.java index f159911fba0..714bc92eea1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollectSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCollectSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.Subscription; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatest.java index 392de62d220..ac947b9541c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,7 +13,6 @@ package io.reactivex.rxjava3.internal.operators.flowable; -import java.util.Iterator; import java.util.Objects; import java.util.concurrent.atomic.*; @@ -24,9 +23,9 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.operators.flowable.FlowableMap.MapSubscriber; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -73,75 +72,46 @@ public FlowableCombineLatest(@NonNull Iterable> @SuppressWarnings("unchecked") @Override public void subscribeActual(Subscriber s) { - Publisher[] a = array; - int n; - if (a == null) { - n = 0; - a = new Publisher[8]; - - Iterator> it; + Publisher[] sources = array; + int count; + if (sources == null) { + count = 0; + sources = new Publisher[8]; try { - it = Objects.requireNonNull(iterable.iterator(), "The iterator returned is null"); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - EmptySubscription.error(e, s); - return; - } - - for (;;) { - - boolean b; - - try { - b = it.hasNext(); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - EmptySubscription.error(e, s); - return; - } - - if (!b) { - break; - } - - Publisher p; - - try { - p = Objects.requireNonNull(it.next(), "The publisher returned by the iterator is null"); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - EmptySubscription.error(e, s); - return; - } - - if (n == a.length) { - Publisher[] c = new Publisher[n + (n >> 2)]; - System.arraycopy(a, 0, c, 0, n); - a = c; + for (Publisher p : iterable) { + if (count == sources.length) { + Publisher[] b = new Publisher[count + (count >> 2)]; + System.arraycopy(sources, 0, b, 0, count); + sources = b; + } + sources[count++] = Objects.requireNonNull(p, "The Iterator returned a null Publisher"); } - a[n++] = p; + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + EmptySubscription.error(ex, s); + return; } } else { - n = a.length; + count = sources.length; } - if (n == 0) { + if (count == 0) { EmptySubscription.complete(s); return; } - if (n == 1) { - a[0].subscribe(new MapSubscriber<>(s, new SingletonArrayFunc())); + if (count == 1) { + sources[0].subscribe(new MapSubscriber<>(s, new SingletonArrayFunc())); return; } CombineLatestCoordinator coordinator = - new CombineLatestCoordinator<>(s, combiner, n, bufferSize, delayErrors); + new CombineLatestCoordinator<>(s, combiner, count, bufferSize, delayErrors); s.onSubscribe(coordinator); - coordinator.subscribe(a, n); + coordinator.subscribe(sources, count); } static final class CombineLatestCoordinator @@ -173,7 +143,7 @@ static final class CombineLatestCoordinator volatile boolean done; - final AtomicReference error; + final AtomicThrowable error; CombineLatestCoordinator(Subscriber actual, Function combiner, int n, @@ -189,7 +159,7 @@ static final class CombineLatestCoordinator this.latest = new Object[n]; this.queue = new SpscLinkedArrayQueue<>(bufferSize); this.requested = new AtomicLong(); - this.error = new AtomicReference<>(); + this.error = new AtomicThrowable(); this.delayErrors = delayErrors; } @@ -205,6 +175,7 @@ public void request(long n) { public void cancel() { cancelled = true; cancelAll(); + drain(); } void subscribe(Publisher[] sources, int n) { @@ -411,6 +382,7 @@ boolean checkTerminated(boolean d, boolean empty, Subscriber a, SpscLinkedArr if (cancelled) { cancelAll(); q.clear(); + error.tryTerminateAndReport(); return true; } @@ -418,13 +390,7 @@ boolean checkTerminated(boolean d, boolean empty, Subscriber a, SpscLinkedArr if (delayErrors) { if (empty) { cancelAll(); - Throwable e = ExceptionHelper.terminate(error); - - if (e != null && e != ExceptionHelper.TERMINATED) { - a.onError(e); - } else { - a.onComplete(); - } + error.tryTerminateConsumer(a); return true; } } else { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatArray.java index 81834bba614..34d4248514c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMap.java index 98d8ea44107..5d1b6e4c33b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,20 +10,22 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.*; import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; public final class FlowableConcatMap extends AbstractFlowableWithUpstream { @@ -150,7 +152,7 @@ public final void onNext(T t) { if (sourceMode != QueueSubscription.ASYNC) { if (!queue.offer(t)) { upstream.cancel(); - onError(new IllegalStateException("Queue full?!")); + onError(new QueueOverflowException()); return; } } @@ -195,35 +197,19 @@ void subscribeActual() { @Override public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - inner.cancel(); - - if (getAndIncrement() == 0) { - errors.tryTerminateConsumer(downstream); - } - } + inner.cancel(); + HalfSerializer.onError(downstream, t, this, errors); } @Override public void innerNext(R value) { - if (get() == 0 && compareAndSet(0, 1)) { - downstream.onNext(value); - if (compareAndSet(1, 0)) { - return; - } - errors.tryTerminateConsumer(downstream); - } + HalfSerializer.onNext(downstream, value, this, errors); } @Override public void innerError(Throwable e) { - if (errors.tryAddThrowableOrReport(e)) { - upstream.cancel(); - - if (getAndIncrement() == 0) { - errors.tryTerminateConsumer(downstream); - } - } + upstream.cancel(); + HalfSerializer.onError(downstream, e, this, errors); } @Override @@ -318,17 +304,13 @@ void drain() { } if (inner.isUnbounded()) { - if (get() == 0 && compareAndSet(0, 1)) { - downstream.onNext(vr); - if (!compareAndSet(1, 0)) { - errors.tryTerminateConsumer(downstream); - return; - } + if (!HalfSerializer.onNext(downstream, vr, this, errors)) { + return; } continue; } else { active = true; - inner.setSubscription(new WeakScalarSubscription<>(vr, inner)); + inner.setSubscription(new SimpleScalarSubscription<>(vr, inner)); } } else { @@ -345,20 +327,22 @@ void drain() { } } - static final class WeakScalarSubscription implements Subscription { + static final class SimpleScalarSubscription + extends AtomicBoolean + implements Subscription { + private static final long serialVersionUID = -7606889335172043256L; + final Subscriber downstream; final T value; - boolean once; - WeakScalarSubscription(T value, Subscriber downstream) { + SimpleScalarSubscription(T value, Subscriber downstream) { this.value = value; this.downstream = downstream; } @Override public void request(long n) { - if (n > 0 && !once) { - once = true; + if (n > 0L && compareAndSet(false, true)) { Subscriber a = downstream; a.onNext(value); a.onComplete(); @@ -527,7 +511,7 @@ void drain() { continue; } else { active = true; - inner.setSubscription(new WeakScalarSubscription<>(vr, inner)); + inner.setSubscription(new SimpleScalarSubscription<>(vr, inner)); } } else { active = true; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEager.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEager.java index ea39af45a24..dc423d89fc0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEager.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEager.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,11 +21,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscribers.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class FlowableConcatMapEager extends AbstractFlowableWithUpstream { @@ -200,7 +200,7 @@ public void innerNext(InnerQueuedSubscriber inner, R value) { drain(); } else { inner.cancel(); - innerError(inner, new MissingBackpressureException()); + innerError(inner, MissingBackpressureException.createDefault()); } } @@ -318,7 +318,7 @@ public void drain() { e++; - inner.requestOne(); + inner.request(1L); } if (e == r) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerPublisher.java index 36d465d1908..218f90c2a69 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapScheduler.java index d59677efa1e..707d10a19ea 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.Objects; @@ -18,13 +19,14 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatMap.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; public final class FlowableConcatMapScheduler extends AbstractFlowableWithUpstream { @@ -149,7 +151,7 @@ public final void onNext(T t) { if (sourceMode != QueueSubscription.ASYNC) { if (!queue.offer(t)) { upstream.cancel(); - onError(new IllegalStateException("Queue full?!")); + onError(new QueueOverflowException()); return; } } @@ -204,9 +206,13 @@ public void onError(Throwable t) { } } + boolean tryEnter() { + return get() == 0 && compareAndSet(0, 1); + } + @Override public void innerNext(R value) { - if (get() == 0 && compareAndSet(0, 1)) { + if (tryEnter()) { downstream.onNext(value); if (compareAndSet(1, 0)) { return; @@ -325,12 +331,12 @@ public void run() { return; } - if (vr == null) { + if (vr == null || cancelled) { continue; } if (inner.isUnbounded()) { - if (get() == 0 && compareAndSet(0, 1)) { + if (tryEnter()) { downstream.onNext(vr); if (!compareAndSet(1, 0)) { errors.tryTerminateConsumer(downstream); @@ -341,7 +347,7 @@ public void run() { continue; } else { active = true; - inner.setSubscription(new WeakScalarSubscription<>(vr, inner)); + inner.setSubscription(new SimpleScalarSubscription<>(vr, inner)); } } else { @@ -515,7 +521,7 @@ public void run() { vr = null; } - if (vr == null) { + if (vr == null || cancelled) { continue; } @@ -524,7 +530,7 @@ public void run() { continue; } else { active = true; - inner.setSubscription(new WeakScalarSubscription<>(vr, inner)); + inner.setSubscription(new SimpleScalarSubscription<>(vr, inner)); } } else { active = true; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletable.java index 31729e450f0..81ac13776a8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybe.java index b7db7fd0935..e82076533a4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingle.java index c93ee51ba8e..bfe900ab2e5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCount.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCount.java index 7858180b09d..2c32dd4d766 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCount.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCount.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountSingle.java index 928f36209c2..750f722dbc1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreate.java index b7091c31f99..1e87c4b7e65 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,10 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Cancellable; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableCreate extends Flowable { @@ -442,7 +442,7 @@ static final class ErrorAsyncEmitter extends NoOverflowBaseAsyncEmitter { @Override void onOverflow() { - onError(new MissingBackpressureException("create: could not emit value due to lack of requests")); + onError(new MissingBackpressureException("create: " + MissingBackpressureException.DEFAULT_MESSAGE)); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounce.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounce.java index 16c666b2838..51838a18645 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounce.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounce.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -148,7 +148,7 @@ void emit(long idx, T value) { BackpressureHelper.produced(this, 1); } else { cancel(); - downstream.onError(new MissingBackpressureException("Could not deliver value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTimed.java index 82ae29d4976..b9e5dff7f31 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,6 +16,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.*; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; @@ -32,19 +34,20 @@ public final class FlowableDebounceTimed extends AbstractFlowableWithUpstream final long timeout; final TimeUnit unit; final Scheduler scheduler; + final Consumer onDropped; - public FlowableDebounceTimed(Flowable source, long timeout, TimeUnit unit, Scheduler scheduler) { + public FlowableDebounceTimed(Flowable source, long timeout, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { source.subscribe(new DebounceTimedSubscriber<>( - new SerializedSubscriber<>(s), - timeout, unit, scheduler.createWorker())); + new SerializedSubscriber<>(s), timeout, unit, scheduler.createWorker(), onDropped)); } static final class DebounceTimedSubscriber extends AtomicLong @@ -55,20 +58,22 @@ static final class DebounceTimedSubscriber extends AtomicLong final long timeout; final TimeUnit unit; final Scheduler.Worker worker; + final Consumer onDropped; Subscription upstream; - Disposable timer; + DebounceEmitter timer; volatile long index; boolean done; - DebounceTimedSubscriber(Subscriber actual, long timeout, TimeUnit unit, Worker worker) { + DebounceTimedSubscriber(Subscriber actual, long timeout, TimeUnit unit, Worker worker, Consumer onDropped) { this.downstream = actual; this.timeout = timeout; this.unit = unit; this.worker = worker; + this.onDropped = onDropped; } @Override @@ -88,15 +93,26 @@ public void onNext(T t) { long idx = index + 1; index = idx; - Disposable d = timer; - if (d != null) { - d.dispose(); + DebounceEmitter currentEmitter = timer; + if (currentEmitter != null) { + currentEmitter.dispose(); + } + + if (onDropped != null && currentEmitter != null) { + try { + onDropped.accept(currentEmitter.value); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + done = true; + downstream.onError(ex); + worker.dispose(); + } } - DebounceEmitter de = new DebounceEmitter<>(t, idx, this); - timer = de; - d = worker.schedule(de, timeout, unit); - de.setResource(d); + DebounceEmitter newEmitter = new DebounceEmitter<>(t, idx, this); + timer = newEmitter; + newEmitter.setResource(worker.schedule(newEmitter, timeout, unit)); } @Override @@ -121,15 +137,13 @@ public void onComplete() { } done = true; - Disposable d = timer; + DebounceEmitter d = timer; if (d != null) { d.dispose(); } - @SuppressWarnings("unchecked") - DebounceEmitter de = (DebounceEmitter)d; - if (de != null) { - de.emit(); + if (d != null) { + d.emit(); } downstream.onComplete(); @@ -159,7 +173,7 @@ void emit(long idx, T t, DebounceEmitter emitter) { emitter.dispose(); } else { cancel(); - downstream.onError(new MissingBackpressureException("Could not deliver value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefer.java index 6c3d8f90082..b3ea3f1ecc5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelay.java index e66acd39e9d..a7de73213ae 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -111,7 +111,9 @@ final class OnNext implements Runnable { @Override public void run() { - downstream.onNext(t); + if (!w.isDisposed()) { + downstream.onNext(t); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOther.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOther.java index c4e199c7e24..2f12cc6e4e7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOther.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOther.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.concurrent.atomic.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerialize.java index dc2de8e389c..10806f5776f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetach.java index e03ee6094b5..8d755b8ad36 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinct.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinct.java index bc624296114..7c3c777c269 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinct.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinct.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,10 @@ import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscribers.BasicFuseableSubscriber; import io.reactivex.rxjava3.internal.subscriptions.EmptySubscription; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableDistinct extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChanged.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChanged.java index 6eb323625d8..2c597556ec2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChanged.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChanged.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,8 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscribers.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; public final class FlowableDistinctUntilChanged extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNext.java index 7aa451e1f6b..763e93a54a4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,8 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscribers.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; /** * Calls a consumer after pushing the current item to the downstream. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinally.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinally.java index 9373819291d..71da8532274 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinally.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinally.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Action; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEach.java index 2e6d45d5e73..3284a2e5075 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,9 +19,9 @@ import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscribers.*; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableDoOnEach extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycle.java index a75881d2ba0..8b56c38c705 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAt.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAt.java index 91c9c0bee76..eecd3d1c174 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAt.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAt.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybe.java index fc30483fd25..f62439c577f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java index a474b032809..b6b16a3e404 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtSingle.java index b743b6a3b78..95b32bde6d1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableEmpty.java index 4a9bbe7d320..3606ac57d64 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,8 +16,8 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; import io.reactivex.rxjava3.internal.subscriptions.EmptySubscription; +import io.reactivex.rxjava3.operators.ScalarSupplier; /** * A source Flowable that signals an onSubscribe() + onComplete() only. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableError.java index f65410ff116..190eb53c6be 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilter.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilter.java index 790881a1609..74a4413e36f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilter.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.functions.Predicate; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscribers.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueSubscription; public final class FlowableFilter extends AbstractFlowableWithUpstream { final Predicate predicate; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMap.java index 0a671cf88a7..c250d3b1651 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableFlatMap extends AbstractFlowableWithUpstream { @@ -150,14 +149,14 @@ public void onNext(T t) { if (u != null) { tryEmitScalar(u); } else { - if (maxConcurrency != Integer.MAX_VALUE && !cancelled - && ++scalarEmitted == scalarLimit) { + if (maxConcurrency != Integer.MAX_VALUE + && !cancelled && ++scalarEmitted == scalarLimit) { scalarEmitted = 0; upstream.request(scalarLimit); } } } else { - InnerSubscriber inner = new InnerSubscriber<>(this, uniqueId++); + InnerSubscriber inner = new InnerSubscriber<>(this, bufferSize, uniqueId++); if (addInner(inner)) { p.subscribe(inner); } @@ -234,8 +233,8 @@ void tryEmitScalar(U value) { if (r != Long.MAX_VALUE) { requested.decrementAndGet(); } - if (maxConcurrency != Integer.MAX_VALUE && !cancelled - && ++scalarEmitted == scalarLimit) { + if (maxConcurrency != Integer.MAX_VALUE + && !cancelled && ++scalarEmitted == scalarLimit) { scalarEmitted = 0; upstream.request(scalarLimit); } @@ -244,8 +243,7 @@ void tryEmitScalar(U value) { q = getMainQueue(); } if (!q.offer(value)) { - onError(new IllegalStateException("Scalar queue full?!")); - return; + onError(new QueueOverflowException()); } } if (decrementAndGet() == 0) { @@ -254,7 +252,7 @@ void tryEmitScalar(U value) { } else { SimpleQueue q = getMainQueue(); if (!q.offer(value)) { - onError(new IllegalStateException("Scalar queue full?!")); + onError(new QueueOverflowException()); return; } if (getAndIncrement() != 0) { @@ -264,15 +262,6 @@ void tryEmitScalar(U value) { drainLoop(); } - SimpleQueue getInnerQueue(InnerSubscriber inner) { - SimpleQueue q = inner.queue; - if (q == null) { - q = new SpscArrayQueue<>(bufferSize); - inner.queue = q; - } - return q; - } - void tryEmit(U value, InnerSubscriber inner) { if (get() == 0 && compareAndSet(0, 1)) { long r = requested.get(); @@ -285,11 +274,11 @@ void tryEmit(U value, InnerSubscriber inner) { inner.requestMore(1); } else { if (q == null) { - q = getInnerQueue(inner); + q = new SpscArrayQueue<>(bufferSize); + inner.queue = q; } if (!q.offer(value)) { - onError(new MissingBackpressureException("Inner queue full?!")); - return; + onError(new QueueOverflowException()); } } if (decrementAndGet() == 0) { @@ -302,7 +291,7 @@ void tryEmit(U value, InnerSubscriber inner) { inner.queue = q; } if (!q.offer(value)) { - onError(new MissingBackpressureException("Inner queue full?!")); + onError(new QueueOverflowException()); return; } if (getAndIncrement() != 0) { @@ -384,35 +373,30 @@ void drainLoop() { long replenishMain = 0; if (svq != null) { - for (;;) { - long scalarEmission = 0; - U o = null; - while (r != 0L) { - o = svq.poll(); + long scalarEmission = 0; + U o = null; + while (r != 0L) { + o = svq.poll(); - if (checkTerminate()) { - return; - } - if (o == null) { - break; - } - - child.onNext(o); - - replenishMain++; - scalarEmission++; - r--; - } - if (scalarEmission != 0L) { - if (unbounded) { - r = Long.MAX_VALUE; - } else { - r = requested.addAndGet(-scalarEmission); - } + if (checkTerminate()) { + return; } - if (r == 0L || o == null) { + if (o == null) { break; } + + child.onNext(o); + + replenishMain++; + scalarEmission++; + r--; + } + if (scalarEmission != 0L) { + if (unbounded) { + r = Long.MAX_VALUE; + } else { + r = requested.addAndGet(-scalarEmission); + } } } @@ -462,15 +446,15 @@ void drainLoop() { U o = null; for (;;) { - if (checkTerminate()) { - return; - } SimpleQueue q = is.queue; if (q == null) { break; } long produced = 0; while (r != 0L) { + if (checkTerminate()) { + return; + } try { o = q.poll(); @@ -495,10 +479,6 @@ void drainLoop() { child.onNext(o); - if (checkTerminate()) { - return; - } - r--; produced++; } @@ -571,15 +551,12 @@ void clearScalarQueue() { } void disposeAll() { - InnerSubscriber[] a = subscribers.get(); + InnerSubscriber[] a = subscribers.getAndSet(CANCELLED); if (a != CANCELLED) { - a = subscribers.getAndSet(CANCELLED); - if (a != CANCELLED) { - for (InnerSubscriber inner : a) { - inner.dispose(); - } - errors.tryTerminateAndReport(); + for (InnerSubscriber inner : a) { + inner.dispose(); } + errors.tryTerminateAndReport(); } } @@ -611,10 +588,10 @@ static final class InnerSubscriber extends AtomicReference long produced; int fusionMode; - InnerSubscriber(MergeSubscriber parent, long id) { + InnerSubscriber(MergeSubscriber parent, int bufferSize, long id) { this.id = id; this.parent = parent; - this.bufferSize = parent.bufferSize; + this.bufferSize = bufferSize; this.limit = bufferSize >> 2; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletable.java index 945e6a877ee..b69a6e2895f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -138,9 +138,7 @@ public void onError(Throwable e) { cancelled = true; upstream.cancel(); set.dispose(); - if (getAndSet(0) > 0) { - errors.tryTerminateConsumer(downstream); - } + errors.tryTerminateConsumer(downstream); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableCompletable.java index 00445c8018b..2d604e5157d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -146,9 +146,7 @@ public void onError(Throwable e) { disposed = true; upstream.cancel(); set.dispose(); - if (getAndSet(0) > 0) { - errors.tryTerminateConsumer(downstream); - } + errors.tryTerminateConsumer(downstream); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybe.java index 1036e73973f..2936fa9066d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,9 +23,9 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Maps upstream values into MaybeSources and merges their signals into one sequence. @@ -174,7 +174,7 @@ void innerSuccess(InnerObserver inner, R value) { SpscLinkedArrayQueue q = queue.get(); - if (d && (q == null || q.isEmpty())) { + if (checkTerminate(d, q)) { errors.tryTerminateConsumer(downstream); return; } @@ -205,16 +205,15 @@ void innerSuccess(InnerObserver inner, R value) { } SpscLinkedArrayQueue getOrCreateQueue() { - for (;;) { - SpscLinkedArrayQueue current = queue.get(); - if (current != null) { - return current; - } - current = new SpscLinkedArrayQueue<>(Flowable.bufferSize()); - if (queue.compareAndSet(null, current)) { - return current; - } + SpscLinkedArrayQueue current = queue.get(); + if (current != null) { + return current; } + current = new SpscLinkedArrayQueue<>(Flowable.bufferSize()); + if (queue.compareAndSet(null, current)) { + return current; + } + return queue.get(); } void innerError(InnerObserver inner, Throwable e) { @@ -240,7 +239,7 @@ void innerComplete(InnerObserver inner) { boolean d = active.decrementAndGet() == 0; SpscLinkedArrayQueue q = queue.get(); - if (d && (q == null || q.isEmpty())) { + if (checkTerminate(d, q)) { errors.tryTerminateConsumer(downstream); return; } @@ -261,6 +260,10 @@ void innerComplete(InnerObserver inner) { } } + static boolean checkTerminate(boolean d, SpscLinkedArrayQueue q) { + return d && (q == null || q.isEmpty()); + } + void drain() { if (getAndIncrement() == 0) { drainLoop(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java index f3006070525..acc527215c4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingle.java index d0c9002669a..f5277d603ab 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,9 +23,9 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Maps upstream values into SingleSources and merges their signals into one sequence. @@ -205,16 +205,15 @@ void innerSuccess(InnerObserver inner, R value) { } SpscLinkedArrayQueue getOrCreateQueue() { - for (;;) { - SpscLinkedArrayQueue current = queue.get(); - if (current != null) { - return current; - } - current = new SpscLinkedArrayQueue<>(Flowable.bufferSize()); - if (queue.compareAndSet(null, current)) { - return current; - } + SpscLinkedArrayQueue current = queue.get(); + if (current != null) { + return current; + } + current = new SpscLinkedArrayQueue<>(Flowable.bufferSize()); + if (queue.compareAndSet(null, current)) { + return current; } + return queue.get(); } void innerError(InnerObserver inner, Throwable e) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java index 457a7285236..570ef96f783 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterable.java index 06f0b650e6c..0b9164e0cd6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableFlattenIterable extends AbstractFlowableWithUpstream { @@ -179,7 +180,7 @@ public void onNext(T t) { return; } if (fusionMode == NONE && !queue.offer(t)) { - onError(new MissingBackpressureException("Queue is full?!")); + onError(new QueueOverflowException()); return; } drain(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java index 2d683e7601b..693f40ddb41 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArray.java index 9b9a4c66f4f..1b13bcff3bb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,9 +17,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import java.util.Objects; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallable.java index 603f09abaee..e2a331d2f0c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java index 78b37325ca1..c4b15b947db 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromFuture.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromFuture.java index 57dc02774fe..0fef3682875 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromFuture.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromFuture.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterable.java index 7ae3f3e7d1e..314f0f2f54a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,9 +21,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; public final class FlowableFromIterable extends Flowable { @@ -73,14 +73,14 @@ public static void subscribe(Subscriber s, Iterator abstract static class BaseRangeSubscription extends BasicQueueSubscription { private static final long serialVersionUID = -2252972430506210021L; - Iterator it; + Iterator iterator; volatile boolean cancelled; boolean once; BaseRangeSubscription(Iterator it) { - this.it = it; + this.iterator = it; } @Override @@ -91,27 +91,34 @@ public final int requestFusion(int mode) { @Nullable @Override public final T poll() { - if (it == null) { + if (iterator == null) { return null; } if (!once) { once = true; } else { - if (!it.hasNext()) { + if (!iterator.hasNext()) { return null; } } - return Objects.requireNonNull(it.next(), "Iterator.next() returned a null value"); + return Objects.requireNonNull(iterator.next(), "Iterator.next() returned a null value"); } @Override public final boolean isEmpty() { - return it == null || !it.hasNext(); + Iterator it = this.iterator; + if (it != null) { + if (!once || it.hasNext()) { + return false; + } + clear(); + } + return true; } @Override public final void clear() { - it = null; + iterator = null; } @Override @@ -150,7 +157,7 @@ static final class IteratorSubscription extends BaseRangeSubscription { @Override void fastPath() { - Iterator it = this.it; + Iterator it = this.iterator; Subscriber a = downstream; for (;;) { if (cancelled) { @@ -204,7 +211,7 @@ void fastPath() { @Override void slowPath(long r) { long e = 0L; - Iterator it = this.it; + Iterator it = this.iterator; Subscriber a = downstream; for (;;) { @@ -286,7 +293,7 @@ static final class IteratorConditionalSubscription extends BaseRangeSubscript @Override void fastPath() { - Iterator it = this.it; + Iterator it = this.iterator; ConditionalSubscriber a = downstream; for (;;) { if (cancelled) { @@ -340,7 +347,7 @@ void fastPath() { @Override void slowPath(long r) { long e = 0L; - Iterator it = this.it; + Iterator it = this.iterator; ConditionalSubscriber a = downstream; for (;;) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java index 459228f5497..664dbf4acf3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromPublisher.java index df575a0274f..a021846388f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java index b163f1b7ee3..0d503d46684 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplier.java index 84fbae7eec0..ca2a331396c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerate.java index 2feda7ad97e..3639d64eeba 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java index 9a42e927bcf..50e641ffc1c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,9 +24,9 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.flowables.GroupedFlowable; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableGroupBy extends AbstractFlowableWithUpstream> { @@ -168,7 +168,7 @@ public void onNext(T t) { if (emittedGroups != get()) { downstream.onNext(group); } else { - MissingBackpressureException mbe = new MissingBackpressureException(groupHangWarning(emittedGroups)); + MissingBackpressureException mbe = groupHangWarning(emittedGroups); mbe.initCause(ex); onError(mbe); return; @@ -194,13 +194,13 @@ public void onNext(T t) { } } else { upstream.cancel(); - onError(new MissingBackpressureException(groupHangWarning(emittedGroups))); + onError(groupHangWarning(emittedGroups)); } } } - static String groupHangWarning(long n) { - return "Unable to emit a new group (#" + n + ") due to lack of requests. Please make sure the downstream can always accept a new group as well as each group is consumed in order for the whole operator to be able to proceed."; + static MissingBackpressureException groupHangWarning(long n) { + return new MissingBackpressureException("Unable to emit a new group (#" + n + ") due to lack of requests. Please make sure the downstream can always accept a new group as well as each group is consumed in order for the whole operator to be able to proceed."); } @Override @@ -214,9 +214,7 @@ public void onError(Throwable t) { g.onError(t); } groups.clear(); - if (evictedGroups != null) { - evictedGroups.clear(); - } + completeEvictions(); downstream.onError(t); } @@ -226,10 +224,10 @@ public void onComplete() { for (GroupedUnicast g : groups.values()) { g.onComplete(); } + groups.clear(); - if (evictedGroups != null) { - evictedGroups.clear(); - } + completeEvictions(); + done = true; downstream.onComplete(); } @@ -259,8 +257,9 @@ private void completeEvictions() { int count = 0; GroupedUnicast evictedGroup; while ((evictedGroup = evictedGroups.poll()) != null) { - evictedGroup.onComplete(); - count++; + if (evictedGroup.state.tryComplete()) { + count++; + } } if (count != 0) { groupCount.addAndGet(-count); @@ -270,9 +269,10 @@ private void completeEvictions() { public void cancel(K key) { Object mapKey = key != null ? key : NULL_KEY; - groups.remove(mapKey); - if (groupCount.decrementAndGet() == 0) { - upstream.cancel(); + if (groups.remove(mapKey) != null) { + if (groupCount.decrementAndGet() == 0) { + upstream.cancel(); + } } } @@ -382,6 +382,8 @@ static final class State extends BasicIntQueueSubscription implements P static final int ABANDONED = 2; static final int ABANDONED_HAS_SUBSCRIBER = ABANDONED | HAS_SUBSCRIBER; + final AtomicBoolean evictOnce = new AtomicBoolean(); + State(int bufferSize, GroupBySubscriber parent, K key, boolean delayError) { this.queue = new SpscLinkedArrayQueue<>(bufferSize); this.parent = parent; @@ -443,9 +445,18 @@ public void onComplete() { drain(); } + boolean tryComplete() { + boolean canEvict = evictOnce.compareAndSet(false, true); + done = true; + drain(); + return canEvict; + } + void cancelParent() { if ((once.get() & ABANDONED) == 0) { - parent.cancel(key); + if (evictOnce.compareAndSet(false, true)) { + parent.cancel(key); + } } } @@ -517,37 +528,44 @@ void drainNormal() { final SpscLinkedArrayQueue q = queue; final boolean delayError = this.delayError; Subscriber a = actual.get(); + final AtomicBoolean cancelled = this.cancelled; + + outer: for (;;) { - if (a != null) { - long r = requested.get(); - long e = 0; + if (cancelled.get()) { + cleanupQueue(0, false); + } else { + if (a != null) { + long r = requested.get(); + long e = 0; - while (e != r) { - boolean d = done; - T v = q.poll(); - boolean empty = v == null; + while (e != r) { + boolean d = done; + T v = q.poll(); + boolean empty = v == null; - if (checkTerminated(d, empty, a, delayError, e)) { - return; - } + if (checkTerminated(d, empty, a, delayError, e, !empty)) { + continue outer; + } - if (empty) { - break; - } + if (empty) { + break; + } - a.onNext(v); + a.onNext(v); - e++; - } + e++; + } - if (e == r && checkTerminated(done, q.isEmpty(), a, delayError, e)) { - return; - } + if (e == r && checkTerminated(done, q.isEmpty(), a, delayError, e, false)) { + continue outer; + } - if (e != 0L) { - BackpressureHelper.produced(requested, e); - // replenish based on this batch run - requestParent(e); + if (e != 0L) { + BackpressureHelper.produced(requested, e); + // replenish based on this batch run + requestParent(e); + } } } @@ -567,28 +585,45 @@ void requestParent(long e) { } } - boolean checkTerminated(boolean d, boolean empty, Subscriber a, boolean delayError, long emitted) { + void cleanupQueue(long emitted, boolean polled) { + // if this group is canceled, all accumulated emissions and + // remaining items in the queue should be requested + // so that other groups can proceed + while (queue.poll() != null) { + emitted++; + } + + replenishParent(emitted, polled); + } + + void replenishParent(long emitted, boolean polled) { + if (polled) { + emitted++; + } + if (emitted != 0L) { + requestParent(emitted); + } + } + + boolean checkTerminated(boolean d, boolean empty, Subscriber a, + boolean delayError, long emitted, boolean polled) { if (cancelled.get()) { - // if this group is canceled, all accumulated emissions and - // remaining items in the queue should be requested - // so that other groups can proceed - while (queue.poll() != null) { - emitted++; - } - if (emitted != 0L) { - requestParent(emitted); - } + cleanupQueue(emitted, polled); return true; } if (d) { if (delayError) { if (empty) { + cancelled.lazySet(true); Throwable e = error; if (e != null) { a.onError(e); } else { a.onComplete(); + // completion doesn't mean the parent has completed + // because of evicted groups + replenishParent(emitted, polled); } return true; } @@ -596,11 +631,17 @@ boolean checkTerminated(boolean d, boolean empty, Subscriber a, boole Throwable e = error; if (e != null) { queue.clear(); + cancelled.lazySet(true); a.onError(e); return true; } else if (empty) { + cancelled.lazySet(true); a.onComplete(); + + // completion doesn't mean the parent has completed + // because of evicted groups + replenishParent(emitted, polled); return true; } } @@ -611,10 +652,13 @@ boolean checkTerminated(boolean d, boolean empty, Subscriber a, boole @Override public int requestFusion(int mode) { + // FIXME fusion mode causes hangs + /* if ((mode & ASYNC) != 0) { outputFused = true; return ASYNC; } + */ return NONE; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoin.java index a950de7a96f..c9619c48b70 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoin.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; @@ -25,10 +22,10 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; @@ -279,7 +276,7 @@ void drain() { a.onNext(w); BackpressureHelper.produced(requested, 1); } else { - fail(new MissingBackpressureException("Could not emit value due to lack of requests"), a, q); + fail(MissingBackpressureException.createDefault(), a, q); return; } @@ -330,7 +327,7 @@ else if (mode == LEFT_CLOSE) { up.onComplete(); } } - else if (mode == RIGHT_CLOSE) { + else { LeftRightEndSubscriber end = (LeftRightEndSubscriber)val; rights.remove(end.index); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHide.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHide.java index 17d84f178a1..bc9b47011b6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHide.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElements.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElements.java index 9afee2e50d0..20f546feee8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElements.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElements.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.QueueSubscription; public final class FlowableIgnoreElements extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsCompletable.java index 4eaced342e5..19d8546d2df 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelper.java index 41dc08d9202..781d4758724 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.Objects; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInterval.java index 9ef04ea11c0..98fbe6dee16 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -93,7 +93,7 @@ public void run() { downstream.onNext(count++); BackpressureHelper.produced(this, 1); } else { - downstream.onError(new MissingBackpressureException("Can't deliver value " + count + " due to lack of requests")); + downstream.onError(new MissingBackpressureException("Could not emit value " + count + " due to lack of requests")); DisposableHelper.dispose(resource); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRange.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRange.java index e9580f40c61..cfa605882df 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRange.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRange.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -114,7 +114,7 @@ public void run() { decrementAndGet(); } } else { - downstream.onError(new MissingBackpressureException("Can't deliver value " + count + " due to lack of requests")); + downstream.onError(new MissingBackpressureException("Could not emit value " + count + " due to lack of requests")); DisposableHelper.dispose(resource); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoin.java index 01cf71023f2..9cda3d457db 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoin.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,11 +22,11 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; import io.reactivex.rxjava3.internal.operators.flowable.FlowableGroupJoin.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableJoin extends AbstractFlowableWithUpstream { @@ -260,7 +260,7 @@ void drain() { e++; } else { - ExceptionHelper.addThrowable(error, new MissingBackpressureException("Could not emit value due to lack of requests")); + ExceptionHelper.addThrowable(error, MissingBackpressureException.createDefault()); q.clear(); cancelAll(); errorAll(a); @@ -321,7 +321,7 @@ else if (mode == RIGHT_VALUE) { e++; } else { - ExceptionHelper.addThrowable(error, new MissingBackpressureException("Could not emit value due to lack of requests")); + ExceptionHelper.addThrowable(error, MissingBackpressureException.createDefault()); q.clear(); cancelAll(); errorAll(a); @@ -339,7 +339,7 @@ else if (mode == LEFT_CLOSE) { lefts.remove(end.index); disposables.remove(end); } - else if (mode == RIGHT_CLOSE) { + else { LeftRightEndSubscriber end = (LeftRightEndSubscriber)val; rights.remove(end.index); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJust.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJust.java index d17c9644faf..2926d49509c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJust.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJust.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,8 +16,8 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; import io.reactivex.rxjava3.internal.subscriptions.ScalarSubscription; +import io.reactivex.rxjava3.operators.ScalarSupplier; /** * Represents a constant scalar value. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastMaybe.java index 936e68c2112..056dfe92018 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastSingle.java index 70346f3555c..ef4fb1a0156 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLift.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLift.java index 5f92e95652f..99e4075bc4d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLift.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLift.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMap.java index 208baca0b25..90ad6c2883a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,8 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscribers.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import java.util.Objects; @@ -115,7 +115,12 @@ public void onNext(T t) { @Override public boolean tryOnNext(T t) { if (done) { - return false; + return true; + } + + if (sourceMode != NONE) { + downstream.tryOnNext(null); + return true; } U v; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotification.java index b01d6dc5a07..be2d78062e7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotification.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotification.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapPublisher.java index 159efcea6c1..cc8ccb8fe82 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterialize.java index 2b361427b18..7a806b8d5df 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletable.java index a0725a1d647..ccd48a78fad 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybe.java index 7d3be91bea5..e7581bcaed4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,10 +20,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; /** * Merges an Observable and a Maybe by emitting the items of the Observable and the success diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingle.java index 997ad3fa2e9..b0f3e8b3eda 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,10 +20,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; /** * Merges an Observable and a Maybe by emitting the items of the Observable and the success diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableNever.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableNever.java index 9dc0611920a..83aeb1533d4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableNever.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableNever.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.Subscriber; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOn.java index 3a4f237e5bb..576debbf2b7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,10 +21,12 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableObserveOn extends AbstractFlowableWithUpstream { @@ -111,7 +113,7 @@ public final void onNext(T t) { if (!queue.offer(t)) { upstream.cancel(); - error = new MissingBackpressureException("Queue is full?!"); + error = new QueueOverflowException(); done = true; } trySchedule(); @@ -242,8 +244,7 @@ public final boolean isEmpty() { } } - static final class ObserveOnSubscriber extends BaseObserveOnSubscriber - implements FlowableSubscriber { + static final class ObserveOnSubscriber extends BaseObserveOnSubscriber { private static final long serialVersionUID = -4547113800637756442L; @@ -350,15 +351,10 @@ void runSync() { return; } - int w = get(); - if (missed == w) { - produced = e; - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + produced = e; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } @@ -593,15 +589,10 @@ void runSync() { return; } - int w = get(); - if (missed == w) { - produced = e; - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + produced = e; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } @@ -662,16 +653,11 @@ void runAsync() { return; } - int w = get(); - if (missed == w) { - produced = emitted; - consumed = polled; - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + produced = emitted; + consumed = polled; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBuffer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBuffer.java index 19d28291ba0..db58b68a103 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBuffer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBuffer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,30 +20,31 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.functions.Action; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.*; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.*; public final class FlowableOnBackpressureBuffer extends AbstractFlowableWithUpstream { final int bufferSize; final boolean unbounded; final boolean delayError; final Action onOverflow; + final Consumer onDropped; public FlowableOnBackpressureBuffer(Flowable source, int bufferSize, boolean unbounded, - boolean delayError, Action onOverflow) { + boolean delayError, Action onOverflow, Consumer onDropped) { super(source); this.bufferSize = bufferSize; this.unbounded = unbounded; this.delayError = delayError; this.onOverflow = onOverflow; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { - source.subscribe(new BackpressureBufferSubscriber<>(s, bufferSize, unbounded, delayError, onOverflow)); + source.subscribe(new BackpressureBufferSubscriber<>(s, bufferSize, unbounded, delayError, onOverflow, onDropped)); } static final class BackpressureBufferSubscriber extends BasicIntQueueSubscription implements FlowableSubscriber { @@ -54,6 +55,7 @@ static final class BackpressureBufferSubscriber extends BasicIntQueueSubscrip final SimplePlainQueue queue; final boolean delayError; final Action onOverflow; + final Consumer onDropped; Subscription upstream; @@ -67,10 +69,11 @@ static final class BackpressureBufferSubscriber extends BasicIntQueueSubscrip boolean outputFused; BackpressureBufferSubscriber(Subscriber actual, int bufferSize, - boolean unbounded, boolean delayError, Action onOverflow) { + boolean unbounded, boolean delayError, Action onOverflow, Consumer onDropped) { this.downstream = actual; this.onOverflow = onOverflow; this.delayError = delayError; + this.onDropped = onDropped; SimplePlainQueue q; @@ -99,6 +102,7 @@ public void onNext(T t) { MissingBackpressureException ex = new MissingBackpressureException("Buffer is full"); try { onOverflow.run(); + onDropped.accept(t); } catch (Throwable e) { Exceptions.throwIfFatal(e); ex.initCause(e); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategy.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategy.java index 6e458356b66..7963fb7d409 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategy.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategy.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.functions.Action; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -38,17 +38,21 @@ public final class FlowableOnBackpressureBufferStrategy extends AbstractFlowa final BackpressureOverflowStrategy strategy; + final Consumer onDropped; + public FlowableOnBackpressureBufferStrategy(Flowable source, - long bufferSize, Action onOverflow, BackpressureOverflowStrategy strategy) { + long bufferSize, Action onOverflow, BackpressureOverflowStrategy strategy, + Consumer onDropped) { super(source); this.bufferSize = bufferSize; this.onOverflow = onOverflow; this.strategy = strategy; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { - source.subscribe(new OnBackpressureBufferStrategySubscriber<>(s, onOverflow, strategy, bufferSize)); + source.subscribe(new OnBackpressureBufferStrategySubscriber<>(s, onOverflow, strategy, bufferSize, onDropped)); } static final class OnBackpressureBufferStrategySubscriber @@ -61,6 +65,8 @@ static final class OnBackpressureBufferStrategySubscriber final Action onOverflow; + final Consumer onDropped; + final BackpressureOverflowStrategy strategy; final long bufferSize; @@ -77,13 +83,15 @@ static final class OnBackpressureBufferStrategySubscriber Throwable error; OnBackpressureBufferStrategySubscriber(Subscriber actual, Action onOverflow, - BackpressureOverflowStrategy strategy, long bufferSize) { + BackpressureOverflowStrategy strategy, long bufferSize, + Consumer onDropped) { this.downstream = actual; this.onOverflow = onOverflow; this.strategy = strategy; this.bufferSize = bufferSize; this.requested = new AtomicLong(); this.deque = new ArrayDeque<>(); + this.onDropped = onDropped; } @Override @@ -104,44 +112,60 @@ public void onNext(T t) { } boolean callOnOverflow = false; boolean callError = false; + boolean callDrain = false; Deque dq = deque; + T toDrop = null; synchronized (dq) { if (dq.size() == bufferSize) { switch (strategy) { case DROP_LATEST: - dq.pollLast(); + toDrop = dq.pollLast(); dq.offer(t); callOnOverflow = true; break; case DROP_OLDEST: - dq.poll(); + toDrop = dq.poll(); dq.offer(t); callOnOverflow = true; break; default: // signal error + toDrop = t; callError = true; break; } } else { dq.offer(t); + callDrain = true; } } - if (callOnOverflow) { - if (onOverflow != null) { - try { - onOverflow.run(); - } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); - upstream.cancel(); - onError(ex); - } + if (callOnOverflow && onOverflow != null) { + try { + onOverflow.run(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + onError(ex); } - } else if (callError) { + } + + if (onDropped != null && toDrop != null) { + try { + onDropped.accept(toDrop); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + onError(ex); + } + } + + if (callError) { upstream.cancel(); - onError(new MissingBackpressureException()); - } else { + onError(MissingBackpressureException.createDefault()); + } + + if (callDrain) { drain(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDrop.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDrop.java index 0db3cd3cc25..799c5dbca19 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDrop.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDrop.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureError.java index b85e1281fb2..acaf165069f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureError.java @@ -1,11 +1,11 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at - *

+ * * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. @@ -65,7 +65,8 @@ public void onNext(T t) { downstream.onNext(t); BackpressureHelper.produced(this, 1); } else { - onError(new MissingBackpressureException("could not emit value due to lack of requests")); + upstream.cancel(); + onError(MissingBackpressureException.createDefault()); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatest.java index 6123475ef00..155e284e93a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,159 +13,50 @@ package io.reactivex.rxjava3.internal.operators.flowable; -import java.util.concurrent.atomic.*; - -import org.reactivestreams.*; - -import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; -import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; +import org.reactivestreams.Subscriber; public final class FlowableOnBackpressureLatest extends AbstractFlowableWithUpstream { - public FlowableOnBackpressureLatest(Flowable source) { + final Consumer onDropped; + + public FlowableOnBackpressureLatest(Flowable source, Consumer onDropped) { super(source); + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { - source.subscribe(new BackpressureLatestSubscriber<>(s)); + source.subscribe(new BackpressureLatestSubscriber<>(s, onDropped)); } - static final class BackpressureLatestSubscriber extends AtomicInteger implements FlowableSubscriber, Subscription { + static final class BackpressureLatestSubscriber extends AbstractBackpressureThrottlingSubscriber { private static final long serialVersionUID = 163080509307634843L; - final Subscriber downstream; - - Subscription upstream; - - volatile boolean done; - Throwable error; - - volatile boolean cancelled; - - final AtomicLong requested = new AtomicLong(); + final Consumer onDropped; - final AtomicReference current = new AtomicReference<>(); - - BackpressureLatestSubscriber(Subscriber downstream) { - this.downstream = downstream; - } - - @Override - public void onSubscribe(Subscription s) { - if (SubscriptionHelper.validate(this.upstream, s)) { - this.upstream = s; - downstream.onSubscribe(this); - s.request(Long.MAX_VALUE); - } + BackpressureLatestSubscriber(Subscriber downstream, + Consumer onDropped) { + super(downstream); + this.onDropped = onDropped; } @Override public void onNext(T t) { - current.lazySet(t); - drain(); - } - - @Override - public void onError(Throwable t) { - error = t; - done = true; - drain(); - } - - @Override - public void onComplete() { - done = true; - drain(); - } - - @Override - public void request(long n) { - if (SubscriptionHelper.validate(n)) { - BackpressureHelper.add(requested, n); - drain(); - } - } - - @Override - public void cancel() { - if (!cancelled) { - cancelled = true; - upstream.cancel(); - - if (getAndIncrement() == 0) { - current.lazySet(null); + T oldValue = current.getAndSet(t); + if (onDropped != null && oldValue != null) { + try { + onDropped.accept(oldValue); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + downstream.onError(ex); } } - } - - void drain() { - if (getAndIncrement() != 0) { - return; - } - final Subscriber a = downstream; - int missed = 1; - final AtomicLong r = requested; - final AtomicReference q = current; - - for (;;) { - long e = 0L; - - while (e != r.get()) { - boolean d = done; - T v = q.getAndSet(null); - boolean empty = v == null; - - if (checkTerminated(d, empty, a, q)) { - return; - } - - if (empty) { - break; - } - - a.onNext(v); - - e++; - } - - if (e == r.get() && checkTerminated(done, q.get() == null, a, q)) { - return; - } - - if (e != 0L) { - BackpressureHelper.produced(r, e); - } - - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } - } - - boolean checkTerminated(boolean d, boolean empty, Subscriber a, AtomicReference q) { - if (cancelled) { - q.lazySet(null); - return true; - } - - if (d) { - Throwable e = error; - if (e != null) { - q.lazySet(null); - a.onError(e); - return true; - } else - if (empty) { - a.onComplete(); - return true; - } - } - - return false; + drain(); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduce.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduce.java new file mode 100644 index 00000000000..9a6abab89ca --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduce.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.BiFunction; +import org.reactivestreams.Subscriber; + +import java.util.Objects; + +public final class FlowableOnBackpressureReduce extends AbstractFlowableWithUpstream { + + final BiFunction reducer; + + public FlowableOnBackpressureReduce(@NonNull Flowable source, @NonNull BiFunction reducer) { + super(source); + this.reducer = reducer; + } + + @Override + protected void subscribeActual(@NonNull Subscriber s) { + source.subscribe(new BackpressureReduceSubscriber<>(s, reducer)); + } + + static final class BackpressureReduceSubscriber extends AbstractBackpressureThrottlingSubscriber { + + private static final long serialVersionUID = 821363947659780367L; + + final BiFunction reducer; + + BackpressureReduceSubscriber(@NonNull Subscriber downstream, @NonNull BiFunction reducer) { + super(downstream); + this.reducer = reducer; + } + + @Override + public void onNext(T t) { + T v = current.get(); + if (v != null) { + v = current.getAndSet(null); + } + if (v == null) { + current.lazySet(t); + } else { + try { + current.lazySet(Objects.requireNonNull(reducer.apply(v, t), "The reducer returned a null value")); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + onError(ex); + return; + } + } + drain(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWith.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWith.java new file mode 100644 index 00000000000..faed7232406 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWith.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.BiFunction; +import io.reactivex.rxjava3.functions.Supplier; +import org.reactivestreams.Subscriber; + +import java.util.Objects; + +public final class FlowableOnBackpressureReduceWith extends AbstractFlowableWithUpstream { + + final BiFunction reducer; + final Supplier supplier; + + public FlowableOnBackpressureReduceWith(@NonNull Flowable source, + @NonNull Supplier supplier, + @NonNull BiFunction reducer) { + super(source); + this.reducer = reducer; + this.supplier = supplier; + } + + @Override + protected void subscribeActual(@NonNull Subscriber s) { + source.subscribe(new BackpressureReduceWithSubscriber<>(s, supplier, reducer)); + } + + static final class BackpressureReduceWithSubscriber extends AbstractBackpressureThrottlingSubscriber { + + private static final long serialVersionUID = 8255923705960622424L; + + final BiFunction reducer; + final Supplier supplier; + + BackpressureReduceWithSubscriber(@NonNull Subscriber downstream, + @NonNull Supplier supplier, + @NonNull BiFunction reducer) { + super(downstream); + this.reducer = reducer; + this.supplier = supplier; + } + + @Override + public void onNext(T t) { + R v = current.get(); + if (v != null) { + v = current.getAndSet(null); + } + try { + if (v == null) { + current.lazySet(Objects.requireNonNull( + reducer.apply(Objects.requireNonNull(supplier.get(), "The supplier returned a null value"), t), + "The reducer returned a null value" + )); + } else { + current.lazySet(Objects.requireNonNull(reducer.apply(v, t), "The reducer returned a null value")); + } + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + onError(ex); + return; + } + drain(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java index c477917f353..a0999f25c43 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorNext.java index 7c9de4a748b..cb33b81a2ff 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturn.java index 4fe88985a4f..85a375fac9c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublish.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublish.java index 49e75fc1fd4..b05bc8b748b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublish.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublish.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,9 +23,11 @@ import io.reactivex.rxjava3.flowables.ConnectableFlowable; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -60,14 +62,6 @@ public Publisher source() { return source; } - /** - * The internal buffer size of this FlowablePublishAlt operator. - * @return The internal buffer size of this FlowablePublishAlt operator. - */ - public int publishBufferSize() { - return bufferSize; - } - @Override public void connect(Consumer connection) { PublishConnection conn; @@ -232,7 +226,7 @@ public void onSubscribe(Subscription s) { public void onNext(T t) { // we expect upstream to honor backpressure requests if (sourceMode == QueueSubscription.NONE && !queue.offer(t)) { - onError(new MissingBackpressureException("Prefetch queue is full?!")); + onError(new QueueOverflowException()); return; } // since many things can happen concurrently, we have a common dispatch diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticast.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticast.java index 05e0e7a9074..08d0e400586 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticast.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticast.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; @@ -22,12 +19,12 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -124,7 +121,7 @@ public void cancel() { } } - static final class MulticastProcessor extends Flowable implements FlowableSubscriber, Disposable { + static final class MulticastProcessor extends Flowable implements FlowableSubscriber { @SuppressWarnings("rawtypes") static final MulticastSubscription[] EMPTY = new MulticastSubscription[0]; @@ -192,19 +189,19 @@ public void onSubscribe(Subscription s) { } } - @Override - public void dispose() { - SubscriptionHelper.cancel(upstream); - if (wip.getAndIncrement() == 0) { - SimpleQueue q = queue; - if (q != null) { - q.clear(); + void dispose() { + if (!done) { + SubscriptionHelper.cancel(upstream); + if (wip.getAndIncrement() == 0) { + SimpleQueue q = queue; + if (q != null) { + q.clear(); + } } } } - @Override - public boolean isDisposed() { + boolean isDisposed() { return upstream.get() == SubscriptionHelper.CANCELLED; } @@ -215,7 +212,7 @@ public void onNext(T t) { } if (sourceMode == QueueSubscription.NONE && !queue.offer(t)) { upstream.get().cancel(); - onError(new MissingBackpressureException()); + onError(MissingBackpressureException.createDefault()); return; } drain(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRange.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRange.java index 9c14349eb97..e2e3b9a6fbd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRange.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRange.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,9 +17,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; /** * Emits a range of integer values. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLong.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLong.java index 8ae2f333ae6..3be56da6ef8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLong.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLong.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,9 +17,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; /** * Emits a range of long values. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduce.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduce.java index 2aa1d71db05..99bc8615194 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduce.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduce.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceMaybe.java index aded7967b88..6541fee6bb9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceSeedSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceSeedSingle.java index 715cb49c0af..a5a8cc40cba 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceSeedSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceSeedSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingle.java index b2aaf836d74..9d27a19668f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCount.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCount.java index 1bce5a4dd75..0c9f17b0bd7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCount.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCount.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeat.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeat.java index 3acb03fb76c..ffc90b8f4b4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeat.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeat.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatUntil.java index 70df0e949d8..1d527fa59c2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatWhen.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatWhen.java index 5371930b5f4..a2bfa250e55 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatWhen.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatWhen.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplay.java index db8718a4336..11489490c73 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -118,10 +118,11 @@ public static ConnectableFlowable create(Flowable source, } /** - * Creates a OperatorReplay instance to replay values of the given source observable. - * @param source the source observable - * @param bufferFactory the factory to instantiate the appropriate buffer when the observable becomes active - * @return the connectable observable + * Creates a OperatorReplay instance to replay values of the given source {@code Flowable}. + * @param the value type + * @param source the source {@code Flowable} to use + * @param bufferFactory the factory to instantiate the appropriate buffer when the {@code Flowable} becomes active + * @return the {@code ConnectableFlowable} instance */ static ConnectableFlowable create(Flowable source, final Supplier> bufferFactory) { @@ -179,7 +180,7 @@ public void connect(Consumer connection) { } // create a new subscriber-to-source - ReplaySubscriber u = new ReplaySubscriber<>(buf); + ReplaySubscriber u = new ReplaySubscriber<>(buf, current); // try setting it as the current subscriber-to-source if (!current.compareAndSet(ps, u)) { // did not work, perhaps a new subscriber arrived @@ -246,14 +247,16 @@ static final class ReplaySubscriber final AtomicInteger management; - /** Contains the maximum element index the child Subscribers requested so far. Accessed while emitting is true. */ - long maxChildRequested; - /** Counts the outstanding upstream requests until the producer arrives. */ - long maxUpstreamRequested; + /** Tracks the amount already requested from the upstream. */ + long requestedFromUpstream; + + /** The current connection. */ + final AtomicReference> current; @SuppressWarnings("unchecked") - ReplaySubscriber(ReplayBuffer buffer) { + ReplaySubscriber(ReplayBuffer buffer, AtomicReference> current) { this.buffer = buffer; + this.current = current; this.management = new AtomicInteger(); this.subscribers = new AtomicReference<>(EMPTY); this.shouldConnect = new AtomicBoolean(); @@ -268,9 +271,7 @@ public boolean isDisposed() { @Override public void dispose() { subscribers.set(TERMINATED); - // unlike OperatorPublish, we can't null out the terminated so - // late subscribers can still get replay - // current.compareAndSet(ReplaySubscriber.this, null); + current.compareAndSet(ReplaySubscriber.this, null); // we don't care if it fails because it means the current has // been replaced in the meantime SubscriptionHelper.cancel(this); @@ -284,9 +285,6 @@ public void dispose() { */ @SuppressWarnings("unchecked") boolean add(InnerSubscription producer) { - if (producer == null) { - throw new NullPointerException(); - } // the state can change so we do a CAS loop to achieve atomicity for (;;) { // get the current producer array @@ -415,7 +413,8 @@ public void onComplete() { * Coordinates the request amounts of various child Subscribers. */ void manageRequests() { - if (management.getAndIncrement() != 0) { + AtomicInteger m = management; + if (m.getAndIncrement() != 0) { return; } int missed = 1; @@ -424,46 +423,29 @@ void manageRequests() { if (isDisposed()) { return; } + Subscription p = get(); - InnerSubscription[] a = subscribers.get(); - - long ri = maxChildRequested; - long maxTotalRequests = ri; - - for (InnerSubscription rp : a) { - maxTotalRequests = Math.max(maxTotalRequests, rp.totalRequested.get()); - } + // only request when there is an upstream Subscription available + if (p != null) { + // how many items were requested so far + long alreadyRequested = requestedFromUpstream; + long downstreamMaxRequest = alreadyRequested; - long ur = maxUpstreamRequested; - Subscription p = get(); + // find out the maximum total requested of the current subscribers + for (InnerSubscription rp : subscribers.get()) { + downstreamMaxRequest = Math.max(downstreamMaxRequest, rp.totalRequested.get()); + } - long diff = maxTotalRequests - ri; - if (diff != 0L) { - maxChildRequested = maxTotalRequests; - if (p != null) { - if (ur != 0L) { - maxUpstreamRequested = 0L; - p.request(ur + diff); - } else { - p.request(diff); - } - } else { - // collect upstream request amounts until there is a producer for them - long u = ur + diff; - if (u < 0) { - u = Long.MAX_VALUE; - } - maxUpstreamRequested = u; + // how much more to request from the upstream + long diff = downstreamMaxRequest - alreadyRequested; + if (diff != 0L) { + // save the new maximum requested + requestedFromUpstream = downstreamMaxRequest; + p.request(diff); } - } else - // if there were outstanding upstream requests and we have a producer - if (ur != 0L && p != null) { - maxUpstreamRequested = 0L; - // fire the accumulated requests - p.request(ur); } - missed = management.addAndGet(-missed); + missed = m.addAndGet(-missed); if (missed == 0) { break; } @@ -563,6 +545,7 @@ public void dispose() { } /** * Convenience method to auto-cast the index object. + * @param type to cast index object * @return the current index object */ @SuppressWarnings("unchecked") @@ -668,6 +651,8 @@ public void replay(InnerSubscription output) { output.dispose(); if (!NotificationLite.isError(o) && !NotificationLite.isComplete(o)) { child.onError(err); + } else { + RxJavaPlugins.onError(err); } return; } @@ -717,7 +702,7 @@ static final class Node extends AtomicReference { * * @param the value type */ - static class BoundedReplayBuffer extends AtomicReference implements ReplayBuffer { + abstract static class BoundedReplayBuffer extends AtomicReference implements ReplayBuffer { private static final long serialVersionUID = 2346567790059478686L; @@ -829,11 +814,6 @@ public final void replay(InnerSubscription output) { output.emitting = true; } for (;;) { - if (output.isDisposed()) { - output.index = null; - return; - } - long r = output.get(); boolean unbounded = r == Long.MAX_VALUE; // NOPMD long e = 0L; @@ -847,6 +827,11 @@ public final void replay(InnerSubscription output) { } while (r != 0) { + if (output.isDisposed()) { + output.index = null; + return; + } + Node v = node.get(); if (v != null) { Object o = leaveTransform(v.value); @@ -861,6 +846,8 @@ public final void replay(InnerSubscription output) { output.dispose(); if (!NotificationLite.isError(o) && !NotificationLite.isComplete(o)) { output.child.onError(err); + } else { + RxJavaPlugins.onError(err); } return; } @@ -870,10 +857,11 @@ public final void replay(InnerSubscription output) { } else { break; } - if (output.isDisposed()) { - output.index = null; - return; - } + } + + if (r == 0 && output.isDisposed()) { + output.index = null; + return; } if (e != 0L) { @@ -917,9 +905,7 @@ Object leaveTransform(Object value) { * Override this method to truncate a non-terminated buffer * based on its current properties. */ - void truncate() { - - } + abstract void truncate(); /** * Override this method to truncate a terminated buffer * based on its properties (i.e., truncate but the very last node). @@ -1021,7 +1007,7 @@ void truncate() { int e = 0; for (;;) { - if (next != null && size > 1) { // never truncate the very last item just added + if (size > 1) { // never truncate the very last item just added if (size > limit) { e++; size--; @@ -1056,7 +1042,7 @@ void truncateFinal() { int e = 0; for (;;) { - if (next != null && size > 1) { + if (size > 1) { Timed v = (Timed)next.value; if (v.time() <= timeLimit) { e++; @@ -1149,31 +1135,6 @@ public void accept(Disposable r) { } } - static final class ConnectableFlowableReplay extends ConnectableFlowable { - private final ConnectableFlowable cf; - private final Flowable flowable; - - ConnectableFlowableReplay(ConnectableFlowable cf, Flowable flowable) { - this.cf = cf; - this.flowable = flowable; - } - - @Override - public void connect(Consumer connection) { - cf.connect(connection); - } - - @Override - public void reset() { - cf.reset(); - } - - @Override - protected void subscribeActual(Subscriber s) { - flowable.subscribe(s); - } - } - static final class ReplayBufferSupplier implements Supplier> { final int bufferSize; @@ -1241,7 +1202,7 @@ public void subscribe(Subscriber child) { return; } // create a new subscriber to source - ReplaySubscriber u = new ReplaySubscriber<>(buf); + ReplaySubscriber u = new ReplaySubscriber<>(buf, curr); // let's try setting it as the current subscriber-to-source if (!curr.compareAndSet(null, u)) { // didn't work, maybe someone else did it or the current subscriber diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryBiPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryBiPredicate.java index 62b4852849a..8c8a0e960e9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryBiPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryBiPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryPredicate.java index 75350871c49..a954a093005 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWhen.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWhen.java index f4129d7be81..9babc654721 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWhen.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWhen.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSamplePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSamplePublisher.java index 4a20a2b95f3..19474d2cc0f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSamplePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSamplePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -129,7 +129,7 @@ void emit() { BackpressureHelper.produced(requested, 1); } else { cancel(); - downstream.onError(new MissingBackpressureException("Couldn't emit value due to lack of requests!")); + downstream.onError(MissingBackpressureException.createDefault()); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTimed.java index 17e1644749f..40551f4a8ed 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,6 +16,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.*; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; @@ -29,24 +31,25 @@ public final class FlowableSampleTimed extends AbstractFlowableWithUpstream onDropped; - public FlowableSampleTimed(Flowable source, long period, TimeUnit unit, Scheduler scheduler, boolean emitLast) { + public FlowableSampleTimed(Flowable source, long period, TimeUnit unit, Scheduler scheduler, boolean emitLast, Consumer onDropped) { super(source); this.period = period; this.unit = unit; this.scheduler = scheduler; this.emitLast = emitLast; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { SerializedSubscriber serial = new SerializedSubscriber<>(s); if (emitLast) { - source.subscribe(new SampleTimedEmitLast<>(serial, period, unit, scheduler)); + source.subscribe(new SampleTimedEmitLast<>(serial, period, unit, scheduler, onDropped)); } else { - source.subscribe(new SampleTimedNoLast<>(serial, period, unit, scheduler)); + source.subscribe(new SampleTimedNoLast<>(serial, period, unit, scheduler, onDropped)); } } @@ -58,6 +61,7 @@ abstract static class SampleTimedSubscriber extends AtomicReference implem final long period; final TimeUnit unit; final Scheduler scheduler; + final Consumer onDropped; final AtomicLong requested = new AtomicLong(); @@ -65,11 +69,12 @@ abstract static class SampleTimedSubscriber extends AtomicReference implem Subscription upstream; - SampleTimedSubscriber(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler) { + SampleTimedSubscriber(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { this.downstream = actual; this.period = period; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override @@ -84,7 +89,17 @@ public void onSubscribe(Subscription s) { @Override public void onNext(T t) { - lazySet(t); + T oldValue = getAndSet(t); + if (oldValue != null && onDropped != null) { + try { + onDropped.accept(oldValue); + } catch (Throwable throwable) { + Exceptions.throwIfFatal(throwable); + cancelTimer(); + upstream.cancel(); + downstream.onError(throwable); + } + } } @Override @@ -125,7 +140,7 @@ void emit() { BackpressureHelper.produced(requested, 1); } else { cancel(); - downstream.onError(new MissingBackpressureException("Couldn't emit value due to lack of requests!")); + downstream.onError(MissingBackpressureException.createDefault()); } } } @@ -137,8 +152,8 @@ static final class SampleTimedNoLast extends SampleTimedSubscriber { private static final long serialVersionUID = -7139995637533111443L; - SampleTimedNoLast(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler) { - super(actual, period, unit, scheduler); + SampleTimedNoLast(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { + super(actual, period, unit, scheduler, onDropped); } @Override @@ -158,8 +173,8 @@ static final class SampleTimedEmitLast extends SampleTimedSubscriber { final AtomicInteger wip; - SampleTimedEmitLast(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler) { - super(actual, period, unit, scheduler); + SampleTimedEmitLast(Subscriber actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { + super(actual, period, unit, scheduler, onDropped); this.wip = new AtomicInteger(1); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMap.java index 4abae183b4f..cb6471b878d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScan.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScan.java index 01991892041..84c348adfb0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScan.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScan.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanSeed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanSeed.java index 21c88ab7bfe..2ffbc6c8e24 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanSeed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanSeed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.Objects; @@ -20,10 +21,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableScanSeed extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqual.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqual.java index cc65e1d37e8..8dadbe01617 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqual.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqual.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,10 +20,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.BiPredicate; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; public final class FlowableSequenceEqual extends Flowable { final Publisher first; @@ -299,7 +300,7 @@ public void onSubscribe(Subscription s) { public void onNext(T t) { if (sourceMode == QueueSubscription.NONE) { if (!queue.offer(t)) { - onError(new MissingBackpressureException()); + onError(MissingBackpressureException.createDefault()); return; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualSingle.java index 05d99e4e49b..5ede5990f9d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,6 +25,7 @@ import io.reactivex.rxjava3.internal.operators.flowable.FlowableSequenceEqual.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableSequenceEqualSingle extends Single implements FuseToFlowable { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerialized.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerialized.java index 2cd7df33690..4c43ff9c6f8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerialized.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerialized.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.Subscriber; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingle.java index 068385289a4..02077e5444d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleMaybe.java index fac74c9cd86..51beeff27c9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleSingle.java index c24b45a760f..8a4f7fe339e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkip.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkip.java index 2aecef3e106..d9c2f49d1ef 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkip.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkip.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLast.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLast.java index 5908d6d0b0c..9f19ee86ba6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLast.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLast.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimed.java index b56224cbdf5..66f7d240f50 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,9 +19,9 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class FlowableSkipLastTimed extends AbstractFlowableWithUpstream { final long time; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntil.java index 8de843142ce..a7c51f99411 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,9 +18,9 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; public final class FlowableSkipUntil extends AbstractFlowableWithUpstream { final Publisher other; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhile.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhile.java index 62ee5ebdbea..be88184f380 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhile.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhile.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOn.java index b7fdd91e9f3..7d4a51f0f2d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmpty.java index b2ad9db0d09..1d45216f149 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchMap.java index 7c6c1006caf..4d4521c655a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,10 +21,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class FlowableSwitchMap extends AbstractFlowableWithUpstream { @@ -180,12 +181,9 @@ public void cancel() { @SuppressWarnings("unchecked") void disposeInner() { - SwitchMapInnerSubscriber a = active.get(); - if (a != CANCELLED) { - a = active.getAndSet((SwitchMapInnerSubscriber)CANCELLED); - if (a != CANCELLED && a != null) { - a.cancel(); - } + SwitchMapInnerSubscriber a = active.getAndSet((SwitchMapInnerSubscriber)CANCELLED); + if (a != CANCELLED && a != null) { + a.cancel(); } } @@ -201,7 +199,6 @@ void drain() { for (;;) { if (cancelled) { - active.lazySet(null); return; } @@ -228,26 +225,6 @@ void drain() { SwitchMapInnerSubscriber inner = active.get(); SimpleQueue q = inner != null ? inner.queue : null; if (q != null) { - if (inner.done) { - if (!delayErrors) { - Throwable err = errors.get(); - if (err != null) { - disposeInner(); - errors.tryTerminateConsumer(a); - return; - } else - if (q.isEmpty()) { - active.compareAndSet(inner, null); - continue; - } - } else { - if (q.isEmpty()) { - active.compareAndSet(inner, null); - continue; - } - } - } - long r = requested.get(); long e = 0L; boolean retry = false; @@ -306,6 +283,28 @@ void drain() { e++; } + if (e == r) { + if (inner.done) { + if (!delayErrors) { + Throwable err = errors.get(); + if (err != null) { + disposeInner(); + errors.tryTerminateConsumer(a); + return; + } else + if (q.isEmpty()) { + active.compareAndSet(inner, null); + continue; + } + } else { + if (q.isEmpty()) { + active.compareAndSet(inner, null); + continue; + } + } + } + } + if (e != 0L) { if (!cancelled) { if (r != Long.MAX_VALUE) { @@ -382,7 +381,7 @@ public void onNext(R t) { SwitchMapSubscriber p = parent; if (index == p.unique) { if (fusionMode == QueueSubscription.NONE && !queue.offer(t)) { - onError(new MissingBackpressureException("Queue full?!")); + onError(new QueueOverflowException()); return; } p.drain(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTake.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTake.java index 15d06f087fe..ea5ca1c4e13 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTake.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTake.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLast.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLast.java index 062135b47c9..ad26f45124a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLast.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLast.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -119,8 +119,12 @@ void drain() { a.onNext(v); e++; } - if (e != 0L && r != Long.MAX_VALUE) { - r = requested.addAndGet(-e); + if (isEmpty()) { + a.onComplete(); + return; + } + if (e != 0L) { + r = BackpressureHelper.produced(requested, e); } } } while (wip.decrementAndGet() != 0); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOne.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOne.java index e4b674704d0..43d3bf44462 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOne.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOne.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimed.java index a7c2ab3343b..b42b5717ce3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,9 +19,9 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class FlowableTakeLastTimed extends AbstractFlowableWithUpstream { final long count; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakePublisher.java index 9a30bda905f..b105b34ca21 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntil.java index 9c927cca5d8..6ea62f6975c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicate.java index a8ec19c22a4..a57bb14c0ab 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhile.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhile.java index 5bcd8157d34..ea8d4f13eb6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhile.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhile.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTimed.java index 918e2ea6d75..44499ec2556 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,6 +16,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; @@ -32,44 +34,53 @@ public final class FlowableThrottleFirstTimed extends AbstractFlowableWithUps final long timeout; final TimeUnit unit; final Scheduler scheduler; + final Consumer onDropped; - public FlowableThrottleFirstTimed(Flowable source, long timeout, TimeUnit unit, Scheduler scheduler) { + public FlowableThrottleFirstTimed(Flowable source, + long timeout, + TimeUnit unit, + Scheduler scheduler, + Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { source.subscribe(new DebounceTimedSubscriber<>( new SerializedSubscriber<>(s), - timeout, unit, scheduler.createWorker())); + timeout, unit, scheduler.createWorker(), + onDropped)); } static final class DebounceTimedSubscriber extends AtomicLong implements FlowableSubscriber, Subscription, Runnable { - private static final long serialVersionUID = -9102637559663639004L; + final Subscriber downstream; final long timeout; final TimeUnit unit; final Scheduler.Worker worker; - + final Consumer onDropped; Subscription upstream; - final SequentialDisposable timer = new SequentialDisposable(); - volatile boolean gate; - boolean done; - DebounceTimedSubscriber(Subscriber actual, long timeout, TimeUnit unit, Worker worker) { + DebounceTimedSubscriber(Subscriber actual, + long timeout, + TimeUnit unit, + Worker worker, + Consumer onDropped) { this.downstream = actual; this.timeout = timeout; this.unit = unit; this.worker = worker; + this.onDropped = onDropped; } @Override @@ -94,9 +105,10 @@ public void onNext(T t) { downstream.onNext(t); BackpressureHelper.produced(this, 1); } else { + upstream.cancel(); done = true; - cancel(); - downstream.onError(new MissingBackpressureException("Could not deliver value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); + worker.dispose(); return; } @@ -106,6 +118,16 @@ public void onNext(T t) { } timer.replace(worker.schedule(this, timeout, unit)); + } else if (onDropped != null) { + try { + onDropped.accept(t); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + done = true; + downstream.onError(ex); + worker.dispose(); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatest.java index 989eaaf4b2a..e28e5f09dfe 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,9 +19,11 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.MissingBackpressureException; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Emits the next or latest item when the given time elapses. @@ -44,19 +46,24 @@ public final class FlowableThrottleLatest extends AbstractFlowableWithUpstrea final boolean emitLast; + final Consumer onDropped; + public FlowableThrottleLatest(Flowable source, - long timeout, TimeUnit unit, Scheduler scheduler, - boolean emitLast) { + long timeout, TimeUnit unit, + Scheduler scheduler, + boolean emitLast, + Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; this.emitLast = emitLast; + this.onDropped = onDropped; } @Override protected void subscribeActual(Subscriber s) { - source.subscribe(new ThrottleLatestSubscriber<>(s, timeout, unit, scheduler.createWorker(), emitLast)); + source.subscribe(new ThrottleLatestSubscriber<>(s, timeout, unit, scheduler.createWorker(), emitLast, onDropped)); } static final class ThrottleLatestSubscriber @@ -79,6 +86,8 @@ static final class ThrottleLatestSubscriber final AtomicLong requested; + final Consumer onDropped; + Subscription upstream; volatile boolean done; @@ -93,8 +102,10 @@ static final class ThrottleLatestSubscriber boolean timerRunning; ThrottleLatestSubscriber(Subscriber downstream, - long timeout, TimeUnit unit, Scheduler.Worker worker, - boolean emitLast) { + long timeout, TimeUnit unit, + Scheduler.Worker worker, + boolean emitLast, + Consumer onDropped) { this.downstream = downstream; this.timeout = timeout; this.unit = unit; @@ -102,6 +113,7 @@ static final class ThrottleLatestSubscriber this.emitLast = emitLast; this.latest = new AtomicReference<>(); this.requested = new AtomicLong(); + this.onDropped = onDropped; } @Override @@ -115,7 +127,17 @@ public void onSubscribe(Subscription s) { @Override public void onNext(T t) { - latest.set(t); + T old = latest.getAndSet(t); + if (onDropped != null && old != null) { + try { + onDropped.accept(old); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + error = ex; + done = true; + } + } drain(); } @@ -145,6 +167,22 @@ public void cancel() { upstream.cancel(); worker.dispose(); if (getAndIncrement() == 0) { + clear(); + } + } + + void clear() { + if (onDropped != null) { + T v = latest.getAndSet(null); + if (v != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } else { latest.lazySet(null); } } @@ -170,14 +208,27 @@ void drain() { for (;;) { if (cancelled) { - latest.lazySet(null); + clear(); return; } boolean d = done; + Throwable error = this.error; if (d && error != null) { - latest.lazySet(null); + if (onDropped != null) { + T v = latest.getAndSet(null); + if (v != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + error = new CompositeException(error, ex); + } + } + } else { + latest.lazySet(null); + } downstream.onError(error); worker.dispose(); return; @@ -187,19 +238,31 @@ void drain() { boolean empty = v == null; if (d) { - if (!empty && emitLast) { + if (!empty) { v = latest.getAndSet(null); - long e = emitted; - if (e != requested.get()) { - emitted = e + 1; - downstream.onNext(v); - downstream.onComplete(); + if (emitLast) { + long e = emitted; + if (e != requested.get()) { + emitted = e + 1; + downstream.onNext(v); + downstream.onComplete(); + } else { + tryDropAndSignalMBE(v); + } } else { - downstream.onError(new MissingBackpressureException( - "Could not emit final value due to lack of requests")); + if (onDropped != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(ex); + worker.dispose(); + return; + } + } + downstream.onComplete(); } } else { - latest.lazySet(null); downstream.onComplete(); } worker.dispose(); @@ -222,8 +285,7 @@ void drain() { emitted = e + 1; } else { upstream.cancel(); - downstream.onError(new MissingBackpressureException( - "Could not emit value due to lack of requests")); + tryDropAndSignalMBE(v); worker.dispose(); return; } @@ -242,5 +304,18 @@ void drain() { } } } + + void tryDropAndSignalMBE(T valueToDrop) { + Throwable errorToSignal = MissingBackpressureException.createDefault(); + if (onDropped != null) { + try { + onDropped.accept(valueToDrop); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + errorToSignal = new CompositeException(errorToSignal, ex); + } + } + downstream.onError(errorToSignal); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeInterval.java index eb9ec1fbd9f..1601814c987 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeout.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeout.java index 976ab10a05c..506132f5953 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeout.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeout.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTimed.java index 351099500e9..67d612011da 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimer.java index 6c172320def..db45fe2e98d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -78,7 +78,7 @@ public void run() { downstream.onComplete(); } else { lazySet(EmptyDisposable.INSTANCE); - downstream.onError(new MissingBackpressureException("Can't deliver value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToList.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToList.java index 18d8a86de4b..3f03d93112e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToList.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToList.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -46,7 +46,7 @@ protected void subscribeActual(Subscriber s) { static final class ToListSubscriber> extends DeferredScalarSubscription - implements FlowableSubscriber, Subscription { + implements FlowableSubscriber { private static final long serialVersionUID = -8134157938864266736L; Subscription upstream; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListSingle.java index aea4eb32701..5e65b48e089 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOn.java index ee9d8f3cc7d..dd8c4ce4cf3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsing.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsing.java index 5a5b177d35b..8f34a6e4140 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsing.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsing.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -117,7 +117,6 @@ public void onError(Throwable t) { } } - upstream.cancel(); if (innerError != null) { downstream.onError(new CompositeException(t, innerError)); } else { @@ -125,7 +124,6 @@ public void onError(Throwable t) { } } else { downstream.onError(t); - upstream.cancel(); disposeResource(); } } @@ -143,11 +141,9 @@ public void onComplete() { } } - upstream.cancel(); downstream.onComplete(); } else { downstream.onComplete(); - upstream.cancel(); disposeResource(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindow.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindow.java index e00ed99edf5..85ab5a5e0b1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindow.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindow.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,11 +19,10 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; -import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.processors.UnicastProcessor; public final class FlowableWindow extends AbstractFlowableWithUpstream> { final long size; @@ -358,10 +357,6 @@ public void onSubscribe(Subscription s) { @Override public void onNext(T t) { - if (done) { - return; - } - long i = index; UnicastProcessor newWindow = null; @@ -407,11 +402,6 @@ public void onNext(T t) { @Override public void onError(Throwable t) { - if (done) { - RxJavaPlugins.onError(t); - return; - } - for (Processor w : windows) { w.onError(t); } @@ -424,10 +414,6 @@ public void onError(Throwable t) { @Override public void onComplete() { - if (done) { - return; - } - for (Processor w : windows) { w.onComplete(); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundary.java index c86d3faab1d..2aad69dcb5e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -248,7 +248,7 @@ void drain() { } else { SubscriptionHelper.cancel(upstream); boundarySubscriber.dispose(); - errors.tryAddThrowableOrReport(new MissingBackpressureException("Could not deliver a window due to lack of requests")); + errors.tryAddThrowableOrReport(MissingBackpressureException.createDefault()); done = true; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundarySelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundarySelector.java index f6248b33555..d6bffae2e13 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundarySelector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowBoundarySelector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,10 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; @@ -272,7 +272,7 @@ void drain() { upstream.cancel(); startSubscriber.cancel(); resources.dispose(); - error.tryAddThrowableOrReport(new MissingBackpressureException(FlowableWindowTimed.missingBackpressureMessage(emitted))); + error.tryAddThrowableOrReport(FlowableWindowTimed.missingBackpressureMessage(emitted)); upstreamDone = true; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowSubscribeIntercept.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowSubscribeIntercept.java index 8f6cf0a2dac..8ef2204c97c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowSubscribeIntercept.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowSubscribeIntercept.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,4 +45,4 @@ protected void subscribeActual(Subscriber s) { boolean tryAbandon() { return !once.get() && once.compareAndSet(false, true); } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowTimed.java index 89b49e857a8..39e7de59ada 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,10 +23,10 @@ import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.internal.disposables.SequentialDisposable; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.SimplePlainQueue; import io.reactivex.rxjava3.processors.UnicastProcessor; public final class FlowableWindowTimed extends AbstractFlowableWithUpstream> { @@ -213,7 +213,7 @@ void createFirstWindow() { upstream.request(Long.MAX_VALUE); } else { upstream.cancel(); - downstream.onError(new MissingBackpressureException(missingBackpressureMessage(emitted))); + downstream.onError(missingBackpressureMessage(emitted)); cleanupResources(); upstreamCancelled = true; @@ -282,7 +282,7 @@ else if (!isEmpty) { cleanupResources(); upstreamCancelled = true; - downstream.onError(new MissingBackpressureException(missingBackpressureMessage(emitted))); + downstream.onError(missingBackpressureMessage(emitted)); } else { emitted++; @@ -386,7 +386,7 @@ void createFirstWindow() { upstream.request(Long.MAX_VALUE); } else { upstream.cancel(); - downstream.onError(new MissingBackpressureException(missingBackpressureMessage(emitted))); + downstream.onError(missingBackpressureMessage(emitted)); cleanupResources(); upstreamCancelled = true; @@ -499,7 +499,7 @@ UnicastProcessor createNewWindow(UnicastProcessor window) { cleanupResources(); upstreamCancelled = true; - downstream.onError(new MissingBackpressureException(missingBackpressureMessage(emitted))); + downstream.onError(missingBackpressureMessage(emitted)); } else { this.emitted = ++emitted; @@ -584,7 +584,7 @@ void createFirstWindow() { upstream.request(Long.MAX_VALUE); } else { upstream.cancel(); - downstream.onError(new MissingBackpressureException(missingBackpressureMessage(emitted))); + downstream.onError(missingBackpressureMessage(emitted)); cleanupResources(); upstreamCancelled = true; @@ -654,7 +654,7 @@ void drain() { } } else { upstream.cancel(); - Throwable ex = new MissingBackpressureException(missingBackpressureMessage(emitted)); + Throwable ex = missingBackpressureMessage(emitted); for (UnicastProcessor window : windows) { window.onError(ex); } @@ -717,8 +717,8 @@ public void run() { } } - static String missingBackpressureMessage(long index) { - return "Unable to emit the next window (#" + index + ") due to lack of requests. Please make sure the downstream is ready to consume windows."; + static MissingBackpressureException missingBackpressureMessage(long index) { + return new MissingBackpressureException("Unable to emit the next window (#" + index + ") due to lack of requests. Please make sure the downstream is ready to consume windows."); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFrom.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFrom.java index 81d3544dd0f..cad9f3c0ca3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFrom.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFrom.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.BiFunction; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.subscribers.SerializedSubscriber; public final class FlowableWithLatestFrom extends AbstractFlowableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromMany.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromMany.java index be9166a16dd..77d05277292 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromMany.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromMany.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.Arrays; @@ -22,9 +23,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZip.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZip.java index 77011a5a2de..de680b19afb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZip.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZip.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; public final class FlowableZip extends Flowable { @@ -191,23 +192,12 @@ void drain() { for (int j = 0; j < n; j++) { ZipSubscriber inner = qs[j]; if (values[j] == null) { + boolean d = inner.done; + SimpleQueue q = inner.queue; + T v = null; try { - boolean d = inner.done; - SimpleQueue q = inner.queue; - T v = q != null ? q.poll() : null; - - boolean sourceEmpty = v == null; - if (d && sourceEmpty) { - cancelAll(); - errors.tryTerminateConsumer(a); - return; - } - if (!sourceEmpty) { - values[j] = v; - } else { - empty = true; - } + v = q != null ? q.poll() : null; } catch (Throwable ex) { Exceptions.throwIfFatal(ex); @@ -217,6 +207,18 @@ void drain() { errors.tryTerminateConsumer(a); return; } + d = true; + } + + boolean sourceEmpty = v == null; + if (d && sourceEmpty) { + cancelAll(); + errors.tryTerminateConsumer(a); + return; + } + if (!sourceEmpty) { + values[j] = v; + } else { empty = true; } } @@ -259,20 +261,11 @@ void drain() { for (int j = 0; j < n; j++) { ZipSubscriber inner = qs[j]; if (values[j] == null) { + boolean d = inner.done; + SimpleQueue q = inner.queue; + T v = null; try { - boolean d = inner.done; - SimpleQueue q = inner.queue; - T v = q != null ? q.poll() : null; - - boolean empty = v == null; - if (d && empty) { - cancelAll(); - errors.tryTerminateConsumer(a); - return; - } - if (!empty) { - values[j] = v; - } + v = q != null ? q.poll() : null; } catch (Throwable ex) { Exceptions.throwIfFatal(ex); errors.tryAddThrowableOrReport(ex); @@ -281,6 +274,16 @@ void drain() { errors.tryTerminateConsumer(a); return; } + d = true; + } + boolean empty = v == null; + if (d && empty) { + cancelAll(); + errors.tryTerminateConsumer(a); + return; + } + if (!empty) { + values[j] = v; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterable.java index 1fb9777a50a..25d4df529d8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstream.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstream.java index ed559c96dc1..348bb482271 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmb.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmb.java index b87390e847a..802075b2aba 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmb.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmb.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCache.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCache.java index 05c15937072..f9080a12829 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCache.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCache.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserver.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserver.java index 774511f291c..c94c7d49292 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArray.java index f77a59c364f..889e229b649 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayDelayError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayDelayError.java index e889adfe1a3..3b4b87399ae 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayDelayError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayDelayError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterable.java index ee6e87cbe07..b777f4c751e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContains.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContains.java index 8737c6ae372..c1154067f53 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContains.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContains.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCount.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCount.java index d687e6ac1e7..cd2bececf10 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCount.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCount.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreate.java index 24293b895b2..1a6bc60d313 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDefer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDefer.java index ccba4e00413..a1ffacef747 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDefer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDefer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java index 3e6922a339b..5f130107819 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherPublisher.java index 7797a968a5a..eebddc3c872 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionOtherPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionOtherPublisher.java index 7de18c70a50..7cd54da714b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionOtherPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionOtherPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayWithCompletable.java index 6bdc5d1a98e..ecbd84a274a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java index d5d3ed25cd8..80b76d3171e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetach.java index 595c3629171..7dad3b0cf27 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccess.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccess.java index 28943223f0e..c8f47997892 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccess.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccess.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinally.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinally.java index 0078cf88b12..0d8dfe8de27 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinally.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinally.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEvent.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEvent.java index eccc36c6068..a2771dcb8ce 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEvent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEvent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java index 3355c790145..03993293620 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.maybe; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminate.java index 7443b147a06..6c3494ac964 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmpty.java index 4b3361998ed..a803b84fa9d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; /** * Signals an onComplete. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualSingle.java index ddcfc7b3c5c..bf940b82234 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeError.java index fc2f50066ef..ed9c391f021 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorCallable.java index 20bb1e03a8c..360b7299337 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilter.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilter.java index 2ddf5fff277..833edb75f3e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilter.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingle.java index 05354478819..aa3cae5e5cc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelector.java index da5cfe56b89..c57caee8f7f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletable.java index 10fc003bf8a..1611fddfff7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowable.java index 40ca98c3516..322a73177f3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservable.java index c5c24995b1c..2018274b1a0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java index ffe6ee5e20a..d91bd46da66 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java index 999b22f8364..e88dd6fc3d2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatten.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatten.java index 21d306095c8..485cf69ea1a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatten.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatten.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromAction.java index 5bdf86f9047..3d9cf428cfa 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromAction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromAction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallable.java index 088f2e14f02..592b02fad24 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java index 5cb73e821c8..f6ad406e356 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFuture.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFuture.java index acc93b3ea62..e506a322659 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFuture.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFuture.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnable.java index 4c83bbeee74..a102e4b9451 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingle.java index c74a73ee25c..8fe691b7675 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplier.java index 38f0afdb62d..6eaf31ee641 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHide.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHide.java index 4dcddd0c276..2f87b5fddd1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHide.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElement.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElement.java index 1c9242548d8..dcdbd2cd73b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElement.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElement.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementCompletable.java index 6e9c1e9d679..42f40c92f1e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmpty.java index 64fb3046ba7..a9642b92fe8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingle.java index a7fa1882b82..b4795a2985c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJust.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJust.java index 54dacb3c7d6..7e6fc6dfa67 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJust.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJust.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; /** * Signals a constant value. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeLift.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeLift.java index 8e40bbd45d2..a5a6d768777 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeLift.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeLift.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMap.java index 167e21d7fbb..2d637fdd432 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterialize.java index 2690bc47976..022d92bbe89 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArray.java index e550b16fbac..82f6d62ddf8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,9 +22,9 @@ import io.reactivex.rxjava3.annotations.Nullable; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.*; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Run all MaybeSources of an array at once and signal their values as they become available. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeNever.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeNever.java index 9690c283598..a9c35c9b672 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeNever.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeNever.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeObserveOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeObserveOn.java index 7bf03b080e6..5afb4beaf31 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeObserveOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeObserveOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java index 277e207eaff..46c15bcb2a4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorNext.java index 97fdd7b5376..a3e975570da 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java index 190856d5c7c..6d14b2c8cd7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeek.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeek.java index 3b5427ba0fd..58c69839a1b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeek.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeek.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOn.java index 543b7c2b6ac..7ec1a6ad712 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmpty.java index 3be260441c4..c432b3c6744 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingle.java index 142e39f1f67..29e77a3e56e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -124,4 +124,4 @@ public void onError(Throwable e) { } } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilMaybe.java index 6c9498c065d..e99011e509f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisher.java index e86cc7c324c..8e57a5ee84a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java index af30ee3a1d8..9580976d893 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutMaybe.java index 03783489a34..2a2581c5f3c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisher.java index 76545730f31..e89a8d0bc96 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimer.java index a374c44ced0..2b9033c66b3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowable.java index c31ad262abd..5ce9f661033 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservable.java index 4b279186219..65ef0ced1b7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToPublisher.java index 914021c9145..8f1f10d28d9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java index 807b9cac511..48ab0134e34 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsafeCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsafeCreate.java index 35621c1bbf0..462a2525b14 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsafeCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsafeCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOn.java index 2f07161dc92..b1d8cb6f65a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsing.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsing.java index 0e490d6f40f..74e4250e5fa 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsing.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsing.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArray.java index b155e019fc9..ac7514fb685 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -73,7 +73,7 @@ static final class ZipCoordinator extends AtomicInteger implements Disposa final ZipMaybeObserver[] observers; - final Object[] values; + Object[] values; @SuppressWarnings("unchecked") ZipCoordinator(MaybeObserver observer, int n, Function zipper) { @@ -99,11 +99,16 @@ public void dispose() { for (ZipMaybeObserver d : observers) { d.dispose(); } + + values = null; } } void innerSuccess(T value, int index) { - values[index] = value; + Object[] values = this.values; + if (values != null) { + values[index] = value; + } if (decrementAndGet() == 0) { R v; @@ -111,10 +116,12 @@ void innerSuccess(T value, int index) { v = Objects.requireNonNull(zipper.apply(values), "The zipper returned a null value"); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); + this.values = null; downstream.onError(ex); return; } + this.values = null; downstream.onSuccess(v); } } @@ -133,6 +140,7 @@ void disposeExcept(int index) { void innerError(Throwable ex, int index) { if (getAndSet(0) > 0) { disposeExcept(index); + values = null; downstream.onError(ex); } else { RxJavaPlugins.onError(ex); @@ -142,6 +150,7 @@ void innerError(Throwable ex, int index) { void innerComplete(int index) { if (getAndSet(0) > 0) { disposeExcept(index); + values = null; downstream.onComplete(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterable.java index 839b3739200..b247ca4ded5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservable.java index 2a3263a50a9..9f46c097f60 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisher.java index c9017d0af6c..7004181bcc9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainObserver.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainObserver.java new file mode 100644 index 00000000000..d2d29b12135 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainObserver.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.mixed; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; + +/** + * Base class for implementing concatMapX main observers. + * + * @param the upstream value type + * @since 3.0.10 + */ +public abstract class ConcatMapXMainObserver extends AtomicInteger +implements Observer, Disposable { + + private static final long serialVersionUID = -3214213361171757852L; + + final AtomicThrowable errors; + + final int prefetch; + + final ErrorMode errorMode; + + SimpleQueue queue; + + Disposable upstream; + + volatile boolean done; + + volatile boolean disposed; + + public ConcatMapXMainObserver(int prefetch, ErrorMode errorMode) { + this.errorMode = errorMode; + this.errors = new AtomicThrowable(); + this.prefetch = prefetch; + } + + @Override + public final void onSubscribe(Disposable d) { + if (DisposableHelper.validate(upstream, d)) { + upstream = d; + if (d instanceof QueueDisposable) { + @SuppressWarnings("unchecked") + QueueDisposable qd = (QueueDisposable)d; + int mode = qd.requestFusion(QueueFuseable.ANY | QueueFuseable.BOUNDARY); + if (mode == QueueFuseable.SYNC) { + queue = qd; + done = true; + + onSubscribeDownstream(); + + drain(); + return; + } + else if (mode == QueueFuseable.ASYNC) { + queue = qd; + + onSubscribeDownstream(); + + return; + } + } + + queue = new SpscLinkedArrayQueue<>(prefetch); + onSubscribeDownstream(); + } + } + + @Override + public final void onNext(T t) { + // In async fusion mode, t is a drain indicator + if (t != null) { + queue.offer(t); + } + drain(); + } + + @Override + public final void onError(Throwable t) { + if (errors.tryAddThrowableOrReport(t)) { + if (errorMode == ErrorMode.IMMEDIATE) { + disposeInner(); + } + done = true; + drain(); + } + } + + @Override + public final void onComplete() { + done = true; + drain(); + } + + @Override + public final void dispose() { + disposed = true; + upstream.dispose(); + disposeInner(); + errors.tryTerminateAndReport(); + if (getAndIncrement() == 0) { + queue.clear(); + clearValue(); + } + } + + @Override + public final boolean isDisposed() { + return disposed; + } + + /** + * Override this to clear values when the downstream disposes. + */ + void clearValue() { + } + + /** + * Typically, this should be {@code downstream.onSubscribe(this)}. + */ + abstract void onSubscribeDownstream(); + + /** + * Typically, this should be {@code inner.dispose()}. + */ + abstract void disposeInner(); + + /** + * Implement the serialized inner subscribing and value emission here. + */ + abstract void drain(); +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainSubscriber.java new file mode 100644 index 00000000000..03e4c568d69 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ConcatMapXMainSubscriber.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.mixed; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.reactivestreams.Subscription; + +import io.reactivex.rxjava3.core.FlowableSubscriber; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; + +/** + * Base class for implementing concatMapX main subscribers. + * + * @param the upstream value type + * @since 3.0.10 + */ +public abstract class ConcatMapXMainSubscriber extends AtomicInteger +implements FlowableSubscriber { + + private static final long serialVersionUID = -3214213361171757852L; + + final AtomicThrowable errors; + + final int prefetch; + + final ErrorMode errorMode; + + SimpleQueue queue; + + Subscription upstream; + + volatile boolean done; + + volatile boolean cancelled; + + boolean syncFused; + + public ConcatMapXMainSubscriber(int prefetch, ErrorMode errorMode) { + this.errorMode = errorMode; + this.errors = new AtomicThrowable(); + this.prefetch = prefetch; + } + + @Override + public final void onSubscribe(Subscription s) { + if (SubscriptionHelper.validate(upstream, s)) { + upstream = s; + if (s instanceof QueueSubscription) { + @SuppressWarnings("unchecked") + QueueSubscription qs = (QueueSubscription)s; + int mode = qs.requestFusion(QueueFuseable.ANY | QueueFuseable.BOUNDARY); + if (mode == QueueFuseable.SYNC) { + queue = qs; + syncFused = true; + done = true; + + onSubscribeDownstream(); + + drain(); + return; + } + else if (mode == QueueFuseable.ASYNC) { + queue = qs; + + onSubscribeDownstream(); + + upstream.request(prefetch); + return; + } + } + + queue = new SpscArrayQueue<>(prefetch); + onSubscribeDownstream(); + upstream.request(prefetch); + } + } + + @Override + public final void onNext(T t) { + // In async fusion mode, t is a drain indicator + if (t != null) { + if (!queue.offer(t)) { + upstream.cancel(); + onError(new QueueOverflowException()); + return; + } + } + drain(); + } + + @Override + public final void onError(Throwable t) { + if (errors.tryAddThrowableOrReport(t)) { + if (errorMode == ErrorMode.IMMEDIATE) { + disposeInner(); + } + done = true; + drain(); + } + } + + @Override + public final void onComplete() { + done = true; + drain(); + } + + final void stop() { + cancelled = true; + upstream.cancel(); + disposeInner(); + errors.tryTerminateAndReport(); + if (getAndIncrement() == 0) { + queue.clear(); + clearValue(); + } + } + + /** + * Override this to clear values when the downstream disposes. + */ + void clearValue() { + } + + /** + * Typically, this should be {@code downstream.onSubscribe(this);}. + */ + abstract void onSubscribeDownstream(); + + /** + * Typically, this should be {@code inner.dispose()}. + */ + abstract void disposeInner(); + + /** + * Implement the serialized inner subscribing and value emission here. + */ + abstract void drain(); +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletable.java index e4a3f36c054..ab93e4c27ff 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,19 +14,15 @@ package io.reactivex.rxjava3.internal.operators.mixed; import java.util.Objects; -import java.util.concurrent.atomic.*; - -import org.reactivestreams.Subscription; +import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; -import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps the upstream items into {@link CompletableSource}s and subscribes to them one after the @@ -61,8 +57,8 @@ protected void subscribeActual(CompletableObserver observer) { } static final class ConcatMapCompletableObserver - extends AtomicInteger - implements FlowableSubscriber, Disposable { + extends ConcatMapXMainSubscriber + implements Disposable { private static final long serialVersionUID = 3610901111000061034L; @@ -70,93 +66,39 @@ static final class ConcatMapCompletableObserver final Function mapper; - final ErrorMode errorMode; - - final AtomicThrowable errors; - final ConcatMapInnerObserver inner; - final int prefetch; - - final SimplePlainQueue queue; - - Subscription upstream; - volatile boolean active; - volatile boolean done; - - volatile boolean disposed; - int consumed; ConcatMapCompletableObserver(CompletableObserver downstream, Function mapper, ErrorMode errorMode, int prefetch) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.errorMode = errorMode; - this.prefetch = prefetch; - this.errors = new AtomicThrowable(); this.inner = new ConcatMapInnerObserver(this); - this.queue = new SpscArrayQueue<>(prefetch); - } - - @Override - public void onSubscribe(Subscription s) { - if (SubscriptionHelper.validate(upstream, s)) { - this.upstream = s; - downstream.onSubscribe(this); - s.request(prefetch); - } - } - - @Override - public void onNext(T t) { - if (queue.offer(t)) { - drain(); - } else { - upstream.cancel(); - onError(new MissingBackpressureException("Queue full?!")); - } } @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - inner.dispose(); - errors.tryTerminateConsumer(downstream); - if (getAndIncrement() == 0) { - queue.clear(); - } - } else { - done = true; - drain(); - } - } + void onSubscribeDownstream() { + downstream.onSubscribe(this); } @Override - public void onComplete() { - done = true; - drain(); + void disposeInner() { + inner.dispose(); } @Override public void dispose() { - disposed = true; - upstream.cancel(); - inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - } + stop(); } @Override public boolean isDisposed() { - return disposed; + return cancelled; } void innerError(Throwable ex) { @@ -179,29 +121,45 @@ void innerComplete() { drain(); } + @Override void drain() { if (getAndIncrement() != 0) { return; } + ErrorMode errorMode = this.errorMode; + SimpleQueue queue = this.queue; + AtomicThrowable errors = this.errors; + boolean syncFused = this.syncFused; + do { - if (disposed) { + if (cancelled) { queue.clear(); return; } - if (!active) { - - if (errorMode == ErrorMode.BOUNDARY) { - if (errors.get() != null) { - queue.clear(); - errors.tryTerminateConsumer(downstream); - return; - } + if (errors.get() != null) { + if (errorMode == ErrorMode.IMMEDIATE + || (errorMode == ErrorMode.BOUNDARY && !active)) { + queue.clear(); + errors.tryTerminateConsumer(downstream); + return; } + } + + if (!active) { boolean d = done; - T v = queue.poll(); + T v; + try { + v = queue.poll(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + errors.tryAddThrowableOrReport(ex); + errors.tryTerminateConsumer(downstream); + return; + } boolean empty = v == null; if (d && empty) { @@ -212,12 +170,15 @@ void drain() { if (!empty) { int limit = prefetch - (prefetch >> 1); - int c = consumed + 1; - if (c == limit) { - consumed = 0; - upstream.request(limit); - } else { - consumed = c; + + if (!syncFused) { + int c = consumed + 1; + if (c == limit) { + consumed = 0; + upstream.request(limit); + } else { + consumed = c; + } } CompletableSource cs; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybe.java index 5f71148e0d6..944ac69311c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,13 +20,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; -import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps each upstream item into a {@link MaybeSource}, subscribes to them one after the other terminates @@ -62,8 +60,7 @@ protected void subscribeActual(Subscriber s) { } static final class ConcatMapMaybeSubscriber - extends AtomicInteger - implements FlowableSubscriber, Subscription { + extends ConcatMapXMainSubscriber implements Subscription { private static final long serialVersionUID = -9140123220065488293L; @@ -71,24 +68,10 @@ static final class ConcatMapMaybeSubscriber final Function> mapper; - final int prefetch; - final AtomicLong requested; - final AtomicThrowable errors; - final ConcatMapMaybeObserver inner; - final SimplePlainQueue queue; - - final ErrorMode errorMode; - - Subscription upstream; - - volatile boolean done; - - volatile boolean cancelled; - long emitted; int consumed; @@ -107,50 +90,16 @@ static final class ConcatMapMaybeSubscriber ConcatMapMaybeSubscriber(Subscriber downstream, Function> mapper, int prefetch, ErrorMode errorMode) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.prefetch = prefetch; - this.errorMode = errorMode; this.requested = new AtomicLong(); - this.errors = new AtomicThrowable(); this.inner = new ConcatMapMaybeObserver<>(this); - this.queue = new SpscArrayQueue<>(prefetch); - } - - @Override - public void onSubscribe(Subscription s) { - if (SubscriptionHelper.validate(upstream, s)) { - upstream = s; - downstream.onSubscribe(this); - s.request(prefetch); - } - } - - @Override - public void onNext(T t) { - if (!queue.offer(t)) { - upstream.cancel(); - onError(new MissingBackpressureException("queue full?!")); - return; - } - drain(); - } - - @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - inner.dispose(); - } - done = true; - drain(); - } } @Override - public void onComplete() { - done = true; - drain(); + void onSubscribeDownstream() { + downstream.onSubscribe(this); } @Override @@ -161,14 +110,7 @@ public void request(long n) { @Override public void cancel() { - cancelled = true; - upstream.cancel(); - inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - item = null; - } + stop(); } void innerSuccess(R item) { @@ -192,6 +134,17 @@ void innerError(Throwable ex) { } } + @Override + void clearValue() { + item = null; + } + + @Override + void disposeInner() { + inner.dispose(); + } + + @Override void drain() { if (getAndIncrement() != 0) { return; @@ -200,10 +153,11 @@ void drain() { int missed = 1; Subscriber downstream = this.downstream; ErrorMode errorMode = this.errorMode; - SimplePlainQueue queue = this.queue; + SimpleQueue queue = this.queue; AtomicThrowable errors = this.errors; AtomicLong requested = this.requested; int limit = prefetch - (prefetch >> 1); + boolean syncFused = this.syncFused; for (;;) { @@ -228,7 +182,16 @@ void drain() { if (s == STATE_INACTIVE) { boolean d = done; - T v = queue.poll(); + T v; + try { + v = queue.poll(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + errors.tryAddThrowableOrReport(ex); + errors.tryTerminateConsumer(downstream); + return; + } boolean empty = v == null; if (d && empty) { @@ -240,12 +203,14 @@ void drain() { break; } - int c = consumed + 1; - if (c == limit) { - consumed = 0; - upstream.request(limit); - } else { - consumed = c; + if (!syncFused) { + int c = consumed + 1; + if (c == limit) { + consumed = 0; + upstream.request(limit); + } else { + consumed = c; + } } MaybeSource ms; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java index 8651cdcb60c..42c1f732c20 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingle.java index f6cd9395462..5c18b6b2587 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,13 +20,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; -import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps each upstream item into a {@link SingleSource}, subscribes to them one after the other terminates @@ -62,8 +60,7 @@ protected void subscribeActual(Subscriber s) { } static final class ConcatMapSingleSubscriber - extends AtomicInteger - implements FlowableSubscriber, Subscription { + extends ConcatMapXMainSubscriber implements Subscription { private static final long serialVersionUID = -9140123220065488293L; @@ -71,24 +68,10 @@ static final class ConcatMapSingleSubscriber final Function> mapper; - final int prefetch; - final AtomicLong requested; - final AtomicThrowable errors; - final ConcatMapSingleObserver inner; - final SimplePlainQueue queue; - - final ErrorMode errorMode; - - Subscription upstream; - - volatile boolean done; - - volatile boolean cancelled; - long emitted; int consumed; @@ -107,68 +90,37 @@ static final class ConcatMapSingleSubscriber ConcatMapSingleSubscriber(Subscriber downstream, Function> mapper, int prefetch, ErrorMode errorMode) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.prefetch = prefetch; - this.errorMode = errorMode; this.requested = new AtomicLong(); - this.errors = new AtomicThrowable(); this.inner = new ConcatMapSingleObserver<>(this); - this.queue = new SpscArrayQueue<>(prefetch); } @Override - public void onSubscribe(Subscription s) { - if (SubscriptionHelper.validate(upstream, s)) { - upstream = s; - downstream.onSubscribe(this); - s.request(prefetch); - } + void onSubscribeDownstream() { + downstream.onSubscribe(this); } @Override - public void onNext(T t) { - if (!queue.offer(t)) { - upstream.cancel(); - onError(new MissingBackpressureException("queue full?!")); - return; - } + public void request(long n) { + BackpressureHelper.add(requested, n); drain(); } @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - inner.dispose(); - } - done = true; - drain(); - } - } - - @Override - public void onComplete() { - done = true; - drain(); + public void cancel() { + stop(); } @Override - public void request(long n) { - BackpressureHelper.add(requested, n); - drain(); + void clearValue() { + item = null; } @Override - public void cancel() { - cancelled = true; - upstream.cancel(); + void disposeInner() { inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - item = null; - } } void innerSuccess(R item) { @@ -187,6 +139,7 @@ void innerError(Throwable ex) { } } + @Override void drain() { if (getAndIncrement() != 0) { return; @@ -195,10 +148,11 @@ void drain() { int missed = 1; Subscriber downstream = this.downstream; ErrorMode errorMode = this.errorMode; - SimplePlainQueue queue = this.queue; + SimpleQueue queue = this.queue; AtomicThrowable errors = this.errors; AtomicLong requested = this.requested; int limit = prefetch - (prefetch >> 1); + boolean syncFused = this.syncFused; for (;;) { @@ -223,7 +177,16 @@ void drain() { if (s == STATE_INACTIVE) { boolean d = done; - T v = queue.poll(); + T v; + try { + v = queue.poll(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.cancel(); + errors.tryAddThrowableOrReport(ex); + errors.tryTerminateConsumer(downstream); + return; + } boolean empty = v == null; if (d && empty) { @@ -235,12 +198,14 @@ void drain() { break; } - int c = consumed + 1; - if (c == limit) { - consumed = 0; - upstream.request(limit); - } else { - consumed = c; + if (!syncFused) { + int c = consumed + 1; + if (c == limit) { + consumed = 0; + upstream.request(limit); + } else { + consumed = c; + } } SingleSource ss; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java index 5b34314d810..0e1986180a9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletable.java index 1bc0fb709e8..9ca61ab15a2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletablePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletablePublisher.java index 5752027c230..9eae52029e8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletablePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletablePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybe.java index 7933b4ec139..3eab4e0d622 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybePublisher.java index 41696133e9a..319247c2952 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingle.java index 4fe83126e55..59c9cb7f8f7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSinglePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSinglePublisher.java index e64f839046d..31ace1bf2dc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSinglePublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSinglePublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaterializeSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaterializeSingleObserver.java index d9cb5592ac9..3f1c540d7df 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaterializeSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaterializeSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java index ef1dc5f023c..09e634f944a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java index 82a6d5da7dd..b6d2afeb2d0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletable.java index 2295f4397ed..f9d91b170a6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,16 +14,15 @@ package io.reactivex.rxjava3.internal.operators.mixed; import java.util.Objects; -import java.util.concurrent.atomic.*; +import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps the upstream items into {@link CompletableSource}s and subscribes to them one after the @@ -60,8 +59,7 @@ protected void subscribeActual(CompletableObserver observer) { } static final class ConcatMapCompletableObserver - extends AtomicInteger - implements Observer, Disposable { + extends ConcatMapXMainObserver { private static final long serialVersionUID = 3610901111000061034L; @@ -69,122 +67,36 @@ static final class ConcatMapCompletableObserver final Function mapper; - final ErrorMode errorMode; - - final AtomicThrowable errors; - final ConcatMapInnerObserver inner; - final int prefetch; - - SimpleQueue queue; - - Disposable upstream; - volatile boolean active; - volatile boolean done; - - volatile boolean disposed; - ConcatMapCompletableObserver(CompletableObserver downstream, Function mapper, ErrorMode errorMode, int prefetch) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.errorMode = errorMode; - this.prefetch = prefetch; - this.errors = new AtomicThrowable(); this.inner = new ConcatMapInnerObserver(this); } @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.validate(upstream, d)) { - this.upstream = d; - if (d instanceof QueueDisposable) { - @SuppressWarnings("unchecked") - QueueDisposable qd = (QueueDisposable) d; - - int m = qd.requestFusion(QueueDisposable.ANY); - if (m == QueueDisposable.SYNC) { - queue = qd; - done = true; - downstream.onSubscribe(this); - drain(); - return; - } - if (m == QueueDisposable.ASYNC) { - queue = qd; - downstream.onSubscribe(this); - return; - } - } - queue = new SpscLinkedArrayQueue<>(prefetch); - downstream.onSubscribe(this); - } - } - - @Override - public void onNext(T t) { - if (t != null) { - queue.offer(t); - } - drain(); + void onSubscribeDownstream() { + downstream.onSubscribe(this); } @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - disposed = true; - inner.dispose(); - errors.tryTerminateConsumer(downstream); - if (getAndIncrement() == 0) { - queue.clear(); - } - } else { - done = true; - drain(); - } - } - } - - @Override - public void onComplete() { - done = true; - drain(); - } - - @Override - public void dispose() { - disposed = true; - upstream.dispose(); + void disposeInner() { inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - } - } - - @Override - public boolean isDisposed() { - return disposed; } void innerError(Throwable ex) { if (errors.tryAddThrowableOrReport(ex)) { - if (errorMode == ErrorMode.IMMEDIATE) { - disposed = true; + if (errorMode != ErrorMode.END) { upstream.dispose(); - errors.tryTerminateConsumer(downstream); - if (getAndIncrement() == 0) { - queue.clear(); - } - } else { - active = false; - drain(); } + active = false; + drain(); } } @@ -193,6 +105,7 @@ void innerComplete() { drain(); } + @Override void drain() { if (getAndIncrement() != 0) { return; @@ -200,6 +113,7 @@ void drain() { AtomicThrowable errors = this.errors; ErrorMode errorMode = this.errorMode; + SimpleQueue queue = this.queue; do { if (disposed) { @@ -207,16 +121,17 @@ void drain() { return; } - if (!active) { - - if (errorMode == ErrorMode.BOUNDARY) { - if (errors.get() != null) { - disposed = true; - queue.clear(); - errors.tryTerminateConsumer(downstream); - return; - } + if (errors.get() != null) { + if (errorMode == ErrorMode.IMMEDIATE + || (errorMode == ErrorMode.BOUNDARY && !active)) { + disposed = true; + queue.clear(); + errors.tryTerminateConsumer(downstream); + return; } + } + + if (!active) { boolean d = done; boolean empty = true; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybe.java index 1177d5a06e6..7e85104dd7b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,16 +14,15 @@ package io.reactivex.rxjava3.internal.operators.mixed; import java.util.Objects; -import java.util.concurrent.atomic.*; +import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps each upstream item into a {@link MaybeSource}, subscribes to them one after the other terminates @@ -61,8 +60,7 @@ protected void subscribeActual(Observer observer) { } static final class ConcatMapMaybeMainObserver - extends AtomicInteger - implements Observer, Disposable { + extends ConcatMapXMainObserver { private static final long serialVersionUID = -9140123220065488293L; @@ -70,20 +68,8 @@ static final class ConcatMapMaybeMainObserver final Function> mapper; - final AtomicThrowable errors; - final ConcatMapMaybeObserver inner; - final SimplePlainQueue queue; - - final ErrorMode errorMode; - - Disposable upstream; - - volatile boolean done; - - volatile boolean cancelled; - R item; volatile int state; @@ -98,60 +84,20 @@ static final class ConcatMapMaybeMainObserver ConcatMapMaybeMainObserver(Observer downstream, Function> mapper, int prefetch, ErrorMode errorMode) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.errorMode = errorMode; - this.errors = new AtomicThrowable(); this.inner = new ConcatMapMaybeObserver<>(this); - this.queue = new SpscLinkedArrayQueue<>(prefetch); } @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.validate(upstream, d)) { - upstream = d; - downstream.onSubscribe(this); - } + void onSubscribeDownstream() { + downstream.onSubscribe(this); } @Override - public void onNext(T t) { - queue.offer(t); - drain(); - } - - @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - inner.dispose(); - } - done = true; - drain(); - } - } - - @Override - public void onComplete() { - done = true; - drain(); - } - - @Override - public void dispose() { - cancelled = true; - upstream.dispose(); - inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - item = null; - } - } - - @Override - public boolean isDisposed() { - return cancelled; + void clearValue() { + item = null; } void innerSuccess(R item) { @@ -175,6 +121,12 @@ void innerError(Throwable ex) { } } + @Override + void disposeInner() { + inner.dispose(); + } + + @Override void drain() { if (getAndIncrement() != 0) { return; @@ -183,13 +135,13 @@ void drain() { int missed = 1; Observer downstream = this.downstream; ErrorMode errorMode = this.errorMode; - SimplePlainQueue queue = this.queue; + SimpleQueue queue = this.queue; AtomicThrowable errors = this.errors; for (;;) { for (;;) { - if (cancelled) { + if (disposed) { queue.clear(); item = null; break; @@ -209,7 +161,18 @@ void drain() { if (s == STATE_INACTIVE) { boolean d = done; - T v = queue.poll(); + T v; + + try { + v = queue.poll(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + disposed = true; + upstream.dispose(); + errors.tryAddThrowableOrReport(ex); + errors.tryTerminateConsumer(downstream); + return; + } boolean empty = v == null; if (d && empty) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java index 70d913cd42b..b57940a5e7c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,16 +14,15 @@ package io.reactivex.rxjava3.internal.operators.mixed; import java.util.Objects; -import java.util.concurrent.atomic.*; +import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Maps each upstream item into a {@link SingleSource}, subscribes to them one after the other terminates @@ -61,8 +60,7 @@ protected void subscribeActual(Observer observer) { } static final class ConcatMapSingleMainObserver - extends AtomicInteger - implements Observer, Disposable { + extends ConcatMapXMainObserver { private static final long serialVersionUID = -9140123220065488293L; @@ -70,20 +68,8 @@ static final class ConcatMapSingleMainObserver final Function> mapper; - final AtomicThrowable errors; - final ConcatMapSingleObserver inner; - final SimplePlainQueue queue; - - final ErrorMode errorMode; - - Disposable upstream; - - volatile boolean done; - - volatile boolean cancelled; - R item; volatile int state; @@ -98,78 +84,44 @@ static final class ConcatMapSingleMainObserver ConcatMapSingleMainObserver(Observer downstream, Function> mapper, int prefetch, ErrorMode errorMode) { + super(prefetch, errorMode); this.downstream = downstream; this.mapper = mapper; - this.errorMode = errorMode; - this.errors = new AtomicThrowable(); this.inner = new ConcatMapSingleObserver<>(this); - this.queue = new SpscLinkedArrayQueue<>(prefetch); } - @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.validate(upstream, d)) { - upstream = d; - downstream.onSubscribe(this); - } - } - - @Override - public void onNext(T t) { - queue.offer(t); + void innerSuccess(R item) { + this.item = item; + this.state = STATE_RESULT_VALUE; drain(); } - @Override - public void onError(Throwable t) { - if (errors.tryAddThrowableOrReport(t)) { - if (errorMode == ErrorMode.IMMEDIATE) { - inner.dispose(); + void innerError(Throwable ex) { + if (errors.tryAddThrowableOrReport(ex)) { + if (errorMode != ErrorMode.END) { + upstream.dispose(); } - done = true; + this.state = STATE_INACTIVE; drain(); } } @Override - public void onComplete() { - done = true; - drain(); - } - - @Override - public void dispose() { - cancelled = true; - upstream.dispose(); + void disposeInner() { inner.dispose(); - errors.tryTerminateAndReport(); - if (getAndIncrement() == 0) { - queue.clear(); - item = null; - } } @Override - public boolean isDisposed() { - return cancelled; + void onSubscribeDownstream() { + downstream.onSubscribe(this); } - void innerSuccess(R item) { - this.item = item; - this.state = STATE_RESULT_VALUE; - drain(); - } - - void innerError(Throwable ex) { - if (errors.tryAddThrowableOrReport(ex)) { - if (errorMode != ErrorMode.END) { - upstream.dispose(); - } - this.state = STATE_INACTIVE; - drain(); - } + @Override + void clearValue() { + item = null; } + @Override void drain() { if (getAndIncrement() != 0) { return; @@ -178,13 +130,13 @@ void drain() { int missed = 1; Observer downstream = this.downstream; ErrorMode errorMode = this.errorMode; - SimplePlainQueue queue = this.queue; + SimpleQueue queue = this.queue; AtomicThrowable errors = this.errors; for (;;) { for (;;) { - if (cancelled) { + if (disposed) { queue.clear(); item = null; break; @@ -204,7 +156,18 @@ void drain() { if (s == STATE_INACTIVE) { boolean d = done; - T v = queue.poll(); + T v; + + try { + v = queue.poll(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + disposed = true; + upstream.dispose(); + errors.tryAddThrowableOrReport(ex); + errors.tryTerminateConsumer(downstream); + return; + } boolean empty = v == null; if (d && empty) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletable.java index bb6ec70f850..b751afdbb0a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybe.java index f4c9bf6c0c8..fe394df1e8d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingle.java index f5db39d5d58..ca0e2953e05 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelper.java index d7fe0e34458..2ed6301e42d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -78,6 +78,7 @@ static boolean tryAsCompletable(Object source, * Try subscribing to a {@link MaybeSource} mapped from * a scalar source (which implements {@link Supplier}). * @param the upstream value type + * @param the downstream value type * @param source the source reactive type ({@code Flowable} or {@code Observable}) * possibly implementing {@link Supplier}. * @param mapper the function that turns the scalar upstream value into a @@ -117,6 +118,7 @@ static boolean tryAsMaybe(Object source, * Try subscribing to a {@link SingleSource} mapped from * a scalar source (which implements {@link Supplier}). * @param the upstream value type + * @param the downstream value type * @param source the source reactive type ({@code Flowable} or {@code Observable}) * possibly implementing {@link Supplier}. * @param mapper the function that turns the scalar upstream value into a diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java index b2562d8dbad..5db75158907 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstream.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstream.java index 2225cb2d2a8..dcad29a5d8e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstream.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableIterable.java index dce3e2bc212..561571febff 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,8 +20,8 @@ import io.reactivex.rxjava3.core.ObservableSource; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class BlockingObservableIterable implements Iterable { final ObservableSource source; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatest.java index e431db42a7e..4aca95b210b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecent.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecent.java index 1332351cacb..0b2ea5bd34d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ * Returns an Iterable that always returns the item most recently emitted by an Observable, or a * seed value if no item has yet been emitted. *

- * + * * * @param the value type */ diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNext.java index 53aed40999f..2bbfe2b036d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ /** * Returns an Iterable that blocks until the Observable emits another item, then returns that item. *

- * + * * * @param the value type */ diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAll.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAll.java index 3f62b4732ce..0f365414c67 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAll.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAll.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllSingle.java index 8c167d4c47a..89e4e38a163 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmb.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmb.java index 8bc43aa41cf..f8841956c68 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmb.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmb.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -115,9 +115,8 @@ public boolean win(int index) { } return true; } - return false; } - return w == index; + return false; } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAny.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAny.java index bda497f7ed8..fad20eb6e29 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAny.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAny.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnySingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnySingle.java index 6e263a0d480..ff7875fb54a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnySingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnySingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnect.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnect.java index 393a9a3f946..d00a2fc2912 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnect.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnect.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingSubscribe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingSubscribe.java index fe06c2099f0..e173785760a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingSubscribe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingSubscribe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBuffer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBuffer.java index 2688212575d..6f94a97cc6d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBuffer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBuffer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferBoundary.java index 4b0027f4fe2..4b0fafb1882 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,8 +22,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableBufferBoundary, Open, Close> diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferExactBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferExactBoundary.java index 849222505ee..bb650589085 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferExactBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferExactBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -43,7 +43,7 @@ protected void subscribeActual(Observer t) { } static final class BufferExactBoundaryObserver, B> - extends QueueDrainObserver implements Observer, Disposable { + extends QueueDrainObserver implements Disposable { final Supplier bufferSupplier; final ObservableSource boundary; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTimed.java index 8a7becc241e..7628a8f685d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -121,11 +121,9 @@ public void onSubscribe(Disposable d) { downstream.onSubscribe(this); - if (!cancelled) { + if (!DisposableHelper.isDisposed(timer.get())) { Disposable task = scheduler.schedulePeriodicallyDirect(this, timespan, timespan, unit); - if (!timer.compareAndSet(null, task)) { - task.dispose(); - } + DisposableHelper.set(timer, task); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCache.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCache.java index c3e7447e6e3..99e11259a6f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCache.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCache.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,23 +24,7 @@ * * @param the source element type */ -public final class ObservableCache extends AbstractObservableWithUpstream -implements Observer { - - /** - * The subscription to the source should happen at most once. - */ - final AtomicBoolean once; - - /** - * The number of items per cached nodes. - */ - final int capacityHint; - - /** - * The current known array of observer state to notify. - */ - final AtomicReference[]> observers; +public final class ObservableCache extends AbstractObservableWithUpstream { /** * A shared instance of an empty array of observers to avoid creating @@ -56,61 +40,49 @@ public final class ObservableCache extends AbstractObservableWithUpstream head; - - /** - * The current tail of the linked structure holding the items. - */ - Node tail; - - /** - * How many items have been put into the tail node so far. + * The subscription to the source should happen at most once. */ - int tailOffset; + final AtomicBoolean once; /** - * If {@link #observers} is {@link #TERMINATED}, this holds the terminal error if not null. + * Responsible caching events from the source and multicasting them to each downstream. */ - Throwable error; + final Multicaster multicaster; /** - * True if the source has terminated. + * The first node in a singly linked list. Each node has the capacity to hold a specific number of events, and each + * points exclusively to the next node (if present). When a new downstream arrives, the subscription is + * initialized with a reference to the "head" node, and any events present in the linked list are replayed. As + * events are replayed to the new downstream, its 'node' reference advances through the linked list, discarding each + * node reference once all events in that node have been replayed. Consequently, once {@code this} instance goes out + * of scope, the prefix of nodes up to the first node that is still being replayed becomes unreachable and eligible + * for collection. */ - volatile boolean done; + final Node head; /** * Constructs an empty, non-connected cache. * @param source the source to subscribe to for the first incoming observer * @param capacityHint the number of items expected (reduce allocation frequency) */ - @SuppressWarnings("unchecked") public ObservableCache(Observable source, int capacityHint) { super(source); - this.capacityHint = capacityHint; this.once = new AtomicBoolean(); Node n = new Node<>(capacityHint); this.head = n; - this.tail = n; - this.observers = new AtomicReference<>(EMPTY); + this.multicaster = new Multicaster<>(capacityHint, n); } @Override protected void subscribeActual(Observer t) { - CacheDisposable consumer = new CacheDisposable<>(t, this); + CacheDisposable consumer = new CacheDisposable<>(t, multicaster, head); t.onSubscribe(consumer); - add(consumer); + multicaster.add(consumer); if (!once.get() && once.compareAndSet(false, true)) { - source.subscribe(this); + source.subscribe(multicaster); } else { - replay(consumer); + multicaster.replay(consumer); } } @@ -127,7 +99,7 @@ protected void subscribeActual(Observer t) { * @return true if the cache has observers */ /* public */ boolean hasObservers() { - return observers.get().length != 0; + return multicaster.get().length != 0; } /** @@ -135,194 +107,241 @@ protected void subscribeActual(Observer t) { * @return the number of currently cached event count */ /* public */ long cachedEventCount() { - return size; + return multicaster.size; } - /** - * Atomically adds the consumer to the {@link #observers} copy-on-write array - * if the source has not yet terminated. - * @param consumer the consumer to add - */ - void add(CacheDisposable consumer) { - for (;;) { - CacheDisposable[] current = observers.get(); - if (current == TERMINATED) { - return; - } - int n = current.length; + static final class Multicaster extends AtomicReference[]> implements Observer { - @SuppressWarnings("unchecked") - CacheDisposable[] next = new CacheDisposable[n + 1]; - System.arraycopy(current, 0, next, 0, n); - next[n] = consumer; + /** */ + private static final long serialVersionUID = 8514643269016498691L; - if (observers.compareAndSet(current, next)) { - return; - } - } - } + /** + * The number of items per cached nodes. + */ + final int capacityHint; - /** - * Atomically removes the consumer from the {@link #observers} copy-on-write array. - * @param consumer the consumer to remove - */ - @SuppressWarnings("unchecked") - void remove(CacheDisposable consumer) { - for (;;) { - CacheDisposable[] current = observers.get(); - int n = current.length; - if (n == 0) { - return; - } + /** + * The total number of elements in the list available for reads. + */ + volatile long size; - int j = -1; - for (int i = 0; i < n; i++) { - if (current[i] == consumer) { - j = i; - break; - } - } + /** + * The current tail of the linked structure holding the items. + */ + Node tail; - if (j < 0) { - return; - } - CacheDisposable[] next; + /** + * How many items have been put into the tail node so far. + */ + int tailOffset; - if (n == 1) { - next = EMPTY; - } else { - next = new CacheDisposable[n - 1]; - System.arraycopy(current, 0, next, 0, j); - System.arraycopy(current, j + 1, next, j, n - j - 1); - } + /** + * If the observers are {@link #TERMINATED}, this holds the terminal error if not null. + */ + Throwable error; - if (observers.compareAndSet(current, next)) { - return; - } - } - } + /** + * True if the source has terminated. + */ + volatile boolean done; - /** - * Replays the contents of this cache to the given consumer based on its - * current state and number of items requested by it. - * @param consumer the consumer to continue replaying items to - */ - void replay(CacheDisposable consumer) { - // make sure there is only one replay going on at a time - if (consumer.getAndIncrement() != 0) { - return; + @SuppressWarnings("unchecked") + Multicaster(int capacityHint, final Node head) { + super(EMPTY); + this.tail = head; + this.capacityHint = capacityHint; } - // see if there were more replay request in the meantime - int missed = 1; - // read out state into locals upfront to avoid being re-read due to volatile reads - long index = consumer.index; - int offset = consumer.offset; - Node node = consumer.node; - Observer downstream = consumer.downstream; - int capacity = capacityHint; - - for (;;) { - // if the consumer got disposed, clear the node and quit - if (consumer.disposed) { - consumer.node = null; - return; + /** + * Atomically adds the consumer to the observers copy-on-write array + * if the source has not yet terminated. + * @param consumer the consumer to add + */ + void add(CacheDisposable consumer) { + for (;;) { + CacheDisposable[] current = get(); + if (current == TERMINATED) { + return; + } + int n = current.length; + + @SuppressWarnings("unchecked") + CacheDisposable[] next = new CacheDisposable[n + 1]; + System.arraycopy(current, 0, next, 0, n); + next[n] = consumer; + + if (compareAndSet(current, next)) { + return; + } } + } - // first see if the source has terminated, read order matters! - boolean sourceDone = done; - // and if the number of items is the same as this consumer has received - boolean empty = size == index; - - // if the source is done and we have all items so far, terminate the consumer - if (sourceDone && empty) { - // release the node object to avoid leaks through retained consumers - consumer.node = null; - // if error is not null then the source failed - Throwable ex = error; - if (ex != null) { - downstream.onError(ex); + /** + * Atomically removes the consumer from the observers copy-on-write array. + * @param consumer the consumer to remove + */ + @SuppressWarnings("unchecked") + void remove(CacheDisposable consumer) { + for (;;) { + CacheDisposable[] current = get(); + int n = current.length; + if (n == 0) { + return; + } + + int j = -1; + for (int i = 0; i < n; i++) { + if (current[i] == consumer) { + j = i; + break; + } + } + + if (j < 0) { + return; + } + CacheDisposable[] next; + + if (n == 1) { + next = EMPTY; } else { - downstream.onComplete(); + next = new CacheDisposable[n - 1]; + System.arraycopy(current, 0, next, 0, j); + System.arraycopy(current, j + 1, next, j, n - j - 1); } + + if (compareAndSet(current, next)) { + return; + } + } + } + + /** + * Replays the contents of this cache to the given consumer based on its + * current state and number of items requested by it. + * @param consumer the consumer to continue replaying items to + */ + void replay(CacheDisposable consumer) { + // make sure there is only one replay going on at a time + if (consumer.getAndIncrement() != 0) { return; } - // there are still items not sent to the consumer - if (!empty) { - // if the offset in the current node has reached the node capacity - if (offset == capacity) { - // switch to the subsequent node - node = node.next; - // reset the in-node offset - offset = 0; + // see if there were more replay request in the meantime + int missed = 1; + // read out state into locals upfront to avoid being re-read due to volatile reads + long index = consumer.index; + int offset = consumer.offset; + Node node = consumer.node; + Observer downstream = consumer.downstream; + int capacity = capacityHint; + + for (;;) { + // if the consumer got disposed, clear the node and quit + if (consumer.disposed) { + consumer.node = null; + return; } - // emit the cached item - downstream.onNext(node.values[offset]); - - // move the node offset forward - offset++; - // move the total consumed item count forward - index++; + // first see if the source has terminated, read order matters! + boolean sourceDone = done; + // and if the number of items is the same as this consumer has received + boolean empty = size == index; + + // if the source is done and we have all items so far, terminate the consumer + if (sourceDone && empty) { + // release the node object to avoid leaks through retained consumers + consumer.node = null; + // if error is not null then the source failed + Throwable ex = error; + if (ex != null) { + downstream.onError(ex); + } else { + downstream.onComplete(); + } + return; + } - // retry for the next item/terminal event if any - continue; - } + // there are still items not sent to the consumer + if (!empty) { + // if the offset in the current node has reached the node capacity + if (offset == capacity) { + // switch to the subsequent node + node = node.next; + // reset the in-node offset + offset = 0; + } + + // emit the cached item + downstream.onNext(node.values[offset]); + + // move the node offset forward + offset++; + // move the total consumed item count forward + index++; + + // retry for the next item/terminal event if any + continue; + } - // commit the changed references back - consumer.index = index; - consumer.offset = offset; - consumer.node = node; - // release the changes and see if there were more replay request in the meantime - missed = consumer.addAndGet(-missed); - if (missed == 0) { - break; + // commit the changed references back + consumer.index = index; + consumer.offset = offset; + consumer.node = node; + // release the changes and see if there were more replay request in the meantime + missed = consumer.addAndGet(-missed); + if (missed == 0) { + break; + } } } - } - @Override - public void onSubscribe(Disposable d) { - // we can't do much with the upstream disposable - } - - @Override - public void onNext(T t) { - int tailOffset = this.tailOffset; - // if the current tail node is full, create a fresh node - if (tailOffset == capacityHint) { - Node n = new Node<>(tailOffset); - n.values[0] = t; - this.tailOffset = 1; - tail.next = n; - tail = n; - } else { - tail.values[tailOffset] = t; - this.tailOffset = tailOffset + 1; + @Override + public void onSubscribe(Disposable d) { + // we can't do much with the upstream disposable } - size++; - for (CacheDisposable consumer : observers.get()) { - replay(consumer); + + @Override + public void onNext(T t) { + int tailOffset = this.tailOffset; + // if the current tail node is full, create a fresh node + if (tailOffset == capacityHint) { + Node n = new Node<>(tailOffset); + n.values[0] = t; + this.tailOffset = 1; + tail.next = n; + tail = n; + } else { + tail.values[tailOffset] = t; + this.tailOffset = tailOffset + 1; + } + size++; + for (CacheDisposable consumer : get()) { + replay(consumer); + } } - } - @SuppressWarnings("unchecked") - @Override - public void onError(Throwable t) { - error = t; - done = true; - for (CacheDisposable consumer : observers.getAndSet(TERMINATED)) { - replay(consumer); + @SuppressWarnings("unchecked") + @Override + public void onError(Throwable t) { + error = t; + done = true; + // No additional events will arrive, so now we can clear the 'tail' reference + tail = null; + for (CacheDisposable consumer : getAndSet(TERMINATED)) { + replay(consumer); + } } - } - @SuppressWarnings("unchecked") - @Override - public void onComplete() { - done = true; - for (CacheDisposable consumer : observers.getAndSet(TERMINATED)) { - replay(consumer); + @SuppressWarnings("unchecked") + @Override + public void onComplete() { + done = true; + // No additional events will arrive, so now we can clear the 'tail' reference + tail = null; + for (CacheDisposable consumer : getAndSet(TERMINATED)) { + replay(consumer); + } } } @@ -338,7 +357,7 @@ static final class CacheDisposable extends AtomicInteger final Observer downstream; - final ObservableCache parent; + final Multicaster parent; Node node; @@ -353,11 +372,12 @@ static final class CacheDisposable extends AtomicInteger * the parent cache object. * @param downstream the actual consumer * @param parent the parent that holds onto the cached items + * @param head the first node in the linked list */ - CacheDisposable(Observer downstream, ObservableCache parent) { + CacheDisposable(Observer downstream, Multicaster parent, Node head) { this.downstream = downstream; this.parent = parent; - this.node = parent.head; + this.node = head; } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollect.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollect.java index 6bddb34aac7..6b700addd73 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollect.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollect.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectSingle.java index 82f8923de3f..88137432ac3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatest.java index 34dce804315..fded0d0ef59 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableCombineLatest extends Observable { final ObservableSource[] sources; @@ -49,13 +49,19 @@ public void subscribeActual(Observer observer) { int count = 0; if (sources == null) { sources = new ObservableSource[8]; - for (ObservableSource p : sourcesIterable) { - if (count == sources.length) { - ObservableSource[] b = new ObservableSource[count + (count >> 2)]; - System.arraycopy(sources, 0, b, 0, count); - sources = b; + try { + for (ObservableSource p : sourcesIterable) { + if (count == sources.length) { + ObservableSource[] b = new ObservableSource[count + (count >> 2)]; + System.arraycopy(sources, 0, b, 0, count); + sources = b; + } + sources[count++] = Objects.requireNonNull(p, "The Iterator returned a null ObservableSource"); } - sources[count++] = p; + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + EmptyDisposable.error(ex, observer); + return; } } else { count = sources.length; @@ -122,9 +128,7 @@ public void dispose() { if (!cancelled) { cancelled = true; cancelSources(); - if (getAndIncrement() == 0) { - clear(queue); - } + drain(); } } @@ -161,6 +165,7 @@ void drain() { for (;;) { if (cancelled) { clear(q); + errors.tryTerminateAndReport(); return; } @@ -240,7 +245,6 @@ void innerError(int index, Throwable ex) { if (latest == null) { return; } - cancelOthers = latest[index] == null; if (cancelOthers || ++complete == latest.length) { done = true; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMap.java index 9b03b9fc35c..b8f34df3d7f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.Objects; @@ -20,10 +21,11 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; import io.reactivex.rxjava3.observers.SerializedObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableConcatMap extends AbstractObservableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEager.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEager.java index 792940b5e06..5a4b1c3a472 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEager.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEager.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,11 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.observers.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableConcatMapEager extends AbstractObservableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapScheduler.java index b4cd8352b5b..1ea59c83c38 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.Objects; @@ -20,10 +21,11 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; import io.reactivex.rxjava3.observers.SerializedObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableConcatMapScheduler extends AbstractObservableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletable.java index 4ffc8f5490e..8d97074a8c4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybe.java index 19af4e56412..e198a0412a8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingle.java index b2e18601101..3d69ae83ac1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCount.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCount.java index f7ab3b012f5..366c4bb3dbe 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCount.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCount.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountSingle.java index 5796519f740..be73420542e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreate.java index 66445bc8d19..1e2e910f0f5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.concurrent.atomic.*; @@ -19,9 +20,9 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Cancellable; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableCreate extends Observable { @@ -159,7 +160,7 @@ static final class SerializedEmitter @Override public void onNext(T t) { - if (emitter.isDisposed() || done) { + if (done || emitter.isDisposed()) { return; } if (t == null) { @@ -192,7 +193,7 @@ public void onError(Throwable t) { @Override public boolean tryOnError(Throwable t) { - if (emitter.isDisposed() || done) { + if (done || emitter.isDisposed()) { return false; } if (t == null) { @@ -208,7 +209,7 @@ public boolean tryOnError(Throwable t) { @Override public void onComplete() { - if (emitter.isDisposed() || done) { + if (done || emitter.isDisposed()) { return; } done = true; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounce.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounce.java index 16f882d6c53..862227e305b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounce.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounce.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTimed.java index b0b19ef0dc1..f2db191229f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,6 +19,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; import io.reactivex.rxjava3.observers.SerializedObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -27,19 +29,20 @@ public final class ObservableDebounceTimed extends AbstractObservableWithUpst final long timeout; final TimeUnit unit; final Scheduler scheduler; + final Consumer onDropped; - public ObservableDebounceTimed(ObservableSource source, long timeout, TimeUnit unit, Scheduler scheduler) { + public ObservableDebounceTimed(ObservableSource source, long timeout, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override public void subscribeActual(Observer t) { source.subscribe(new DebounceTimedObserver<>( - new SerializedObserver<>(t), - timeout, unit, scheduler.createWorker())); + new SerializedObserver<>(t), timeout, unit, scheduler.createWorker(), onDropped)); } static final class DebounceTimedObserver @@ -48,20 +51,22 @@ static final class DebounceTimedObserver final long timeout; final TimeUnit unit; final Scheduler.Worker worker; + final Consumer onDropped; Disposable upstream; - Disposable timer; + DebounceEmitter timer; volatile long index; boolean done; - DebounceTimedObserver(Observer actual, long timeout, TimeUnit unit, Worker worker) { + DebounceTimedObserver(Observer actual, long timeout, TimeUnit unit, Worker worker, Consumer onDropped) { this.downstream = actual; this.timeout = timeout; this.unit = unit; this.worker = worker; + this.onDropped = onDropped; } @Override @@ -80,15 +85,25 @@ public void onNext(T t) { long idx = index + 1; index = idx; - Disposable d = timer; - if (d != null) { - d.dispose(); + DebounceEmitter currentEmitter = timer; + if (currentEmitter != null) { + currentEmitter.dispose(); } - DebounceEmitter de = new DebounceEmitter<>(t, idx, this); - timer = de; - d = worker.schedule(de, timeout, unit); - de.setResource(d); + if (onDropped != null && currentEmitter != null) { + try { + onDropped.accept(timer.value); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.dispose(); + downstream.onError(ex); + done = true; + } + } + + DebounceEmitter newEmitter = new DebounceEmitter<>(t, idx, this); + timer = newEmitter; + newEmitter.setResource(worker.schedule(newEmitter, timeout, unit)); } @Override @@ -113,15 +128,13 @@ public void onComplete() { } done = true; - Disposable d = timer; + DebounceEmitter d = timer; if (d != null) { d.dispose(); } - @SuppressWarnings("unchecked") - DebounceEmitter de = (DebounceEmitter)d; - if (de != null) { - de.run(); + if (d != null) { + d.run(); } downstream.onComplete(); worker.dispose(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefer.java index 15b3394af70..0b3388c84c9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelay.java index 93cbb003893..7c01c23f90a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -111,7 +111,9 @@ final class OnNext implements Runnable { @Override public void run() { - downstream.onNext(t); + if (!w.isDisposed()) { + downstream.onNext(t); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOther.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOther.java index c594c68b007..978e4d2f32c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOther.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOther.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerialize.java index 37f5fdadd81..20164519862 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetach.java index 763fcdde972..b9c6f2bade8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinct.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinct.java index cd766ef559e..ff377833a50 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinct.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinct.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChanged.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChanged.java index f18e47030d8..7604db7c8f8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChanged.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChanged.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNext.java index 91051e75626..6382e6b8221 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinally.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinally.java index 8c7ee32d09d..e6d9031f72e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinally.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinally.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Action; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; import io.reactivex.rxjava3.internal.observers.BasicIntQueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEach.java index ff884192fae..f4869d19a8a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnLifecycle.java index 835cd886b2f..f1852312466 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnLifecycle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnLifecycle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAt.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAt.java index b8d042a5321..8d8a535bcf0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAt.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAt.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtMaybe.java index 53b13120927..14bb368a23a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtSingle.java index bb006ca2dd3..c779f9eec2a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableEmpty.java index d4869b70eab..7ff9e8b955f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,11 +10,12 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; public final class ObservableEmpty extends Observable implements ScalarSupplier { public static final Observable INSTANCE = new ObservableEmpty(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableError.java index 7481373e7a6..f25af956e09 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilter.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilter.java index 51fec2cc680..ed7068f6a08 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilter.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMap.java index a169627ed30..d19b5059992 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,9 +22,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.*; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableFlatMap extends AbstractObservableWithUpstream { @@ -69,7 +68,7 @@ static final class MergeObserver extends AtomicInteger implements Disposab final AtomicThrowable errors = new AtomicThrowable(); - volatile boolean cancelled; + volatile boolean disposed; final AtomicReference[]> observers; @@ -80,7 +79,6 @@ static final class MergeObserver extends AtomicInteger implements Disposab Disposable upstream; long uniqueId; - long lastId; int lastIndex; Queue> sources; @@ -188,9 +186,6 @@ void removeInner(InnerObserver inner) { for (;;) { InnerObserver[] a = observers.get(); int n = a.length; - if (n == 0) { - return; - } int j = -1; for (int i = 0; i < n; i++) { if (a[i] == inner) { @@ -246,10 +241,7 @@ boolean tryEmitScalar(Supplier value) { queue = q; } - if (!q.offer(u)) { - onError(new IllegalStateException("Scalar queue full?!")); - return true; - } + q.offer(u); if (getAndIncrement() != 0) { return false; } @@ -301,17 +293,15 @@ public void onComplete() { @Override public void dispose() { - if (!cancelled) { - cancelled = true; - if (disposeAll()) { - errors.tryTerminateAndReport(); - } + disposed = true; + if (disposeAll()) { + errors.tryTerminateAndReport(); } } @Override public boolean isDisposed() { - return cancelled; + return disposed; } void drain() { @@ -327,6 +317,7 @@ void drainLoop() { if (checkTerminate()) { return; } + int innerCompleted = 0; SimplePlainQueue svq = queue; if (svq != null) { @@ -342,9 +333,18 @@ void drainLoop() { } child.onNext(o); + innerCompleted++; } } + if (innerCompleted != 0) { + if (maxConcurrency != Integer.MAX_VALUE) { + subscribeMore(innerCompleted); + innerCompleted = 0; + } + continue; + } + boolean d = done; svq = queue; InnerObserver[] inner = observers.get(); @@ -362,31 +362,9 @@ void drainLoop() { return; } - int innerCompleted = 0; if (n != 0) { - long startId = lastId; - int index = lastIndex; - - if (n <= index || inner[index].id != startId) { - if (n <= index) { - index = 0; - } - int j = index; - for (int i = 0; i < n; i++) { - if (inner[j].id == startId) { - break; - } - j++; - if (j == n) { - j = 0; - } - } - index = j; - lastIndex = j; - lastId = inner[j].id; - } + int j = Math.min(n - 1, lastIndex); - int j = index; sourceLoop: for (int i = 0; i < n; i++) { if (checkTerminate()) { @@ -432,9 +410,6 @@ void drainLoop() { SimpleQueue innerQueue = is.queue; if (innerDone && (innerQueue == null || innerQueue.isEmpty())) { removeInner(is); - if (checkTerminate()) { - return; - } innerCompleted++; } @@ -444,25 +419,16 @@ void drainLoop() { } } lastIndex = j; - lastId = inner[j].id; } if (innerCompleted != 0) { if (maxConcurrency != Integer.MAX_VALUE) { - while (innerCompleted-- != 0) { - ObservableSource p; - synchronized (this) { - p = sources.poll(); - if (p == null) { - wip--; - continue; - } - } - subscribeInner(p); - } + subscribeMore(innerCompleted); + innerCompleted = 0; } continue; } + missed = addAndGet(-missed); if (missed == 0) { break; @@ -470,8 +436,22 @@ void drainLoop() { } } + void subscribeMore(int innerCompleted) { + while (innerCompleted-- != 0) { + ObservableSource p; + synchronized (this) { + p = sources.poll(); + if (p == null) { + wip--; + continue; + } + } + subscribeInner(p); + } + } + boolean checkTerminate() { - if (cancelled) { + if (disposed) { return true; } Throwable e = errors.get(); @@ -485,15 +465,12 @@ boolean checkTerminate() { boolean disposeAll() { upstream.dispose(); - InnerObserver[] a = observers.get(); + InnerObserver[] a = observers.getAndSet(CANCELLED); if (a != CANCELLED) { - a = observers.getAndSet(CANCELLED); - if (a != CANCELLED) { - for (InnerObserver inner : a) { - inner.dispose(); - } - return true; + for (InnerObserver inner : a) { + inner.dispose(); } + return true; } return false; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletable.java index 729e8cf6c50..ae7c6f98ac0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -116,9 +116,7 @@ public void onError(Throwable e) { disposed = true; upstream.dispose(); set.dispose(); - if (getAndSet(0) > 0) { - errors.tryTerminateConsumer(downstream); - } + errors.tryTerminateConsumer(downstream); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableCompletable.java index 2d488ac2c5d..62ea03a54d3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -122,9 +122,7 @@ public void onError(Throwable e) { disposed = true; upstream.dispose(); set.dispose(); - if (getAndSet(0) > 0) { - errors.tryTerminateConsumer(downstream); - } + errors.tryTerminateConsumer(downstream); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybe.java index 7ac5ca6f3c9..b8d223d4ac3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Maps upstream values into MaybeSources and merges their signals into one sequence. @@ -172,16 +172,15 @@ void innerSuccess(InnerObserver inner, R value) { } SpscLinkedArrayQueue getOrCreateQueue() { - for (;;) { - SpscLinkedArrayQueue current = queue.get(); - if (current != null) { - return current; - } - current = new SpscLinkedArrayQueue<>(Observable.bufferSize()); - if (queue.compareAndSet(null, current)) { - return current; - } + SpscLinkedArrayQueue current = queue.get(); + if (current != null) { + return current; + } + current = new SpscLinkedArrayQueue<>(Observable.bufferSize()); + if (queue.compareAndSet(null, current)) { + return current; } + return queue.get(); } void innerError(InnerObserver inner, Throwable e) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingle.java index 8ed45d5f399..985e4fa2d91 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,8 +21,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Maps upstream values into SingleSources and merges their signals into one sequence. @@ -172,16 +172,15 @@ void innerSuccess(InnerObserver inner, R value) { } SpscLinkedArrayQueue getOrCreateQueue() { - for (;;) { - SpscLinkedArrayQueue current = queue.get(); - if (current != null) { - return current; - } - current = new SpscLinkedArrayQueue<>(Observable.bufferSize()); - if (queue.compareAndSet(null, current)) { - return current; - } + SpscLinkedArrayQueue current = queue.get(); + if (current != null) { + return current; + } + current = new SpscLinkedArrayQueue<>(Observable.bufferSize()); + if (queue.compareAndSet(null, current)) { + return current; } + return queue.get(); } void innerError(InnerObserver inner, Throwable e) { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterable.java index 732eb50dd3b..47dbde9a1ed 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java index cccb5b5d382..cd0970f0d06 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromArray.java index 97ebfe0d4ff..f84c1183469 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallable.java index 0285b83ff24..ab4b7aa7b89 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java index 4748e6a6257..83bf51f7e03 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromFuture.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromFuture.java index 5459429f4de..d6f21ad133e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromFuture.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromFuture.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterable.java index 187d0cecc33..d5f402d1935 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromPublisher.java index 14efd74eba3..ade1eeb8707 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java index 0dc37a8993c..eeda8e48328 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplier.java index e46cf8fe8fc..7d3cd41480f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromUnsafeSource.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromUnsafeSource.java index d34423bcd43..1f7c7bcccdc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromUnsafeSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromUnsafeSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerate.java index 2bd9a866a14..fee8dfe26ea 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupBy.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupBy.java index 8e259db47cc..e1af50378e8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupBy.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupBy.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,8 +23,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.observables.GroupedObservable; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableGroupBy extends AbstractObservableWithUpstream> { final Function keySelector; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoin.java index 3605ee5203f..4df7fc7bd84 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoin.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.observable; @@ -26,8 +23,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.UnicastSubject; @@ -319,7 +316,7 @@ else if (mode == LEFT_CLOSE) { up.onComplete(); } } - else if (mode == RIGHT_CLOSE) { + else { LeftRightEndObserver end = (LeftRightEndObserver)val; rights.remove(end.index); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHide.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHide.java index 5b216cd44c9..8d6c7a7b60a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHide.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElements.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElements.java index ec4a07e92a9..6afab8124d6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElements.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElements.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsCompletable.java index 14b3a776845..10e4880b55a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelper.java index 5f9dce646df..89822c3e9b4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.Objects; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInterval.java index 93fee0973d3..c61645bdd97 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRange.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRange.java index 96d113663e1..68d303b6ab0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRange.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRange.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -90,8 +90,10 @@ public void run() { downstream.onNext(c); if (c == end) { + if (!isDisposed()) { + downstream.onComplete(); + } DisposableHelper.dispose(this); - downstream.onComplete(); return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoin.java index 70f62aec032..4a0f95695e3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoin.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.observable; @@ -25,8 +22,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.operators.observable.ObservableGroupJoin.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableJoin extends AbstractObservableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJust.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJust.java index d3448d0b413..af01eb09bb4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJust.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJust.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,8 +14,8 @@ package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; import io.reactivex.rxjava3.internal.operators.observable.ObservableScalarXMap.ScalarDisposable; +import io.reactivex.rxjava3.operators.ScalarSupplier; /** * Represents a constant scalar value. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastMaybe.java index 73e26a3972e..b20119d4306 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastSingle.java index 7c5433e1057..049e9341c10 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLift.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLift.java index 4aa45683ffa..67dd7a06498 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLift.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLift.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMap.java index 4361016ec6e..8f4502ba192 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotification.java index 1622b504d43..51883e75193 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotification.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotification.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterialize.java index e55430c3782..866ced7dd98 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletable.java index 1f086f7175e..e1a79180d87 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybe.java index f462075a506..4e940a74f5d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,9 +18,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Merges an Observable and a Maybe by emitting the items of the Observable and the success diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingle.java index 08940cf6452..014df98cc29 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,9 +18,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; /** * Merges an Observable and a Single by emitting the items of the Observable and the success diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableNever.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableNever.java index dd476d59932..1d237491ccd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableNever.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableNever.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOn.java index af5e78df3f3..05a0064f41a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,10 +18,11 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.observers.BasicIntQueueDisposable; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.schedulers.TrampolineScheduler; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableObserveOn extends AbstractObservableWithUpstream { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java index 6854a5ce6d0..70266c14d32 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorNext.java index 3cf18490117..9bcc3b8dd69 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturn.java index 54efdc62e5c..24c9af47005 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublish.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublish.java index 8589ee3c8a5..f2d4c8f0f4b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublish.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublish.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishSelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishSelector.java index 687bee95484..d025a5487de 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishSelector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishSelector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRange.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRange.java index 56e277dc32b..53855a46c23 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRange.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRange.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.annotations.Nullable; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLong.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLong.java index f92decb11e9..39a36e72f2c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLong.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLong.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.annotations.Nullable; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceMaybe.java index f5421a666eb..3f66614ef0a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceSeedSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceSeedSingle.java index 67347debb84..f2382f6f9d2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceSeedSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceSeedSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceWithSingle.java index 1de6cb1e6c5..22dbaa6a1d6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCount.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCount.java index a806a537c65..1a5d9f55ccf 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCount.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCount.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeat.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeat.java index 2816dac708c..b14549f65f7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeat.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeat.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatUntil.java index 51c8b9dd656..d89fd17b830 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatWhen.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatWhen.java index d3fcdf59710..87d30330bae 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatWhen.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatWhen.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplay.java index 7dabfcc72d2..0e8c122d624 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -122,6 +122,7 @@ public static ConnectableObservable create(ObservableSource source, /** * Creates a OperatorReplay instance to replay values of the given source observable. + * @param the value type * @param source the source observable * @param bufferFactory the factory to instantiate the appropriate buffer when the observable becomes active * @return the connectable observable @@ -174,7 +175,7 @@ public void connect(Consumer connection) { // create a new subscriber-to-source ReplayBuffer buf = bufferFactory.call(); - ReplayObserver u = new ReplayObserver<>(buf); + ReplayObserver u = new ReplayObserver<>(buf, current); // try setting it as the current subscriber-to-source if (!current.compareAndSet(ps, u)) { // did not work, perhaps a new subscriber arrived @@ -240,8 +241,12 @@ static final class ReplayObserver */ final AtomicBoolean shouldConnect; - ReplayObserver(ReplayBuffer buffer) { + /** The current connection. */ + final AtomicReference> current; + + ReplayObserver(ReplayBuffer buffer, AtomicReference> current) { this.buffer = buffer; + this.current = current; this.observers = new AtomicReference<>(EMPTY); this.shouldConnect = new AtomicBoolean(); @@ -255,9 +260,7 @@ public boolean isDisposed() { @Override public void dispose() { observers.set(TERMINATED); - // unlike OperatorPublish, we can't null out the terminated so - // late observers can still get replay - // current.compareAndSet(ReplayObserver.this, null); + current.compareAndSet(ReplayObserver.this, null); // we don't care if it fails because it means the current has // been replaced in the meantime DisposableHelper.dispose(this); @@ -451,6 +454,7 @@ public void dispose() { } /** * Convenience method to auto-cast the index object. + * @param type index to be casted to * @return the index Object or null */ @SuppressWarnings("unchecked") @@ -846,7 +850,7 @@ void truncate() { int e = 0; for (;;) { - if (next != null && size > 1) { // never truncate the very last item just added + if (size > 1) { // never truncate the very last item just added if (size > limit) { e++; size--; @@ -881,7 +885,7 @@ void truncateFinal() { int e = 0; for (;;) { - if (next != null && size > 1) { + if (size > 1) { Timed v = (Timed)next.value; if (v.time() <= timeLimit) { e++; @@ -1004,7 +1008,7 @@ public void subscribe(Observer child) { // create a new subscriber to source ReplayBuffer buf = bufferFactory.call(); - ReplayObserver u = new ReplayObserver<>(buf); + ReplayObserver u = new ReplayObserver<>(buf, curr); // let's try setting it as the current subscriber-to-source if (!curr.compareAndSet(null, u)) { // didn't work, maybe someone else did it or the current subscriber @@ -1069,29 +1073,4 @@ protected void subscribeActual(Observer child) { co.connect(new DisposeConsumer<>(srw)); } } - - static final class Replay extends ConnectableObservable { - private final ConnectableObservable co; - private final Observable observable; - - Replay(ConnectableObservable co, Observable observable) { - this.co = co; - this.observable = observable; - } - - @Override - public void connect(Consumer connection) { - co.connect(connection); - } - - @Override - public void reset() { - co.reset(); - } - - @Override - protected void subscribeActual(Observer observer) { - observable.subscribe(observer); - } - } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryBiPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryBiPredicate.java index 56de8606be9..1340a5ad9fa 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryBiPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryBiPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryPredicate.java index 9c4d5c748ab..5c40dc6d977 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWhen.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWhen.java index 2a3f0b6b074..bae50456e4d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWhen.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWhen.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTimed.java index 3f516e8cca1..f264b8e76d4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,6 +18,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; import io.reactivex.rxjava3.observers.SerializedObserver; @@ -25,24 +27,30 @@ public final class ObservableSampleTimed extends AbstractObservableWithUpstre final long period; final TimeUnit unit; final Scheduler scheduler; - + final Consumer onDropped; final boolean emitLast; - public ObservableSampleTimed(ObservableSource source, long period, TimeUnit unit, Scheduler scheduler, boolean emitLast) { + public ObservableSampleTimed(ObservableSource source, + long period, + TimeUnit unit, + Scheduler scheduler, + boolean emitLast, + Consumer onDropped) { super(source); this.period = period; this.unit = unit; this.scheduler = scheduler; this.emitLast = emitLast; + this.onDropped = onDropped; } @Override public void subscribeActual(Observer t) { SerializedObserver serial = new SerializedObserver<>(t); if (emitLast) { - source.subscribe(new SampleTimedEmitLast<>(serial, period, unit, scheduler)); + source.subscribe(new SampleTimedEmitLast<>(serial, period, unit, scheduler, onDropped)); } else { - source.subscribe(new SampleTimedNoLast<>(serial, period, unit, scheduler)); + source.subscribe(new SampleTimedNoLast<>(serial, period, unit, scheduler, onDropped)); } } @@ -54,16 +62,18 @@ abstract static class SampleTimedObserver extends AtomicReference implemen final long period; final TimeUnit unit; final Scheduler scheduler; + final Consumer onDropped; final AtomicReference timer = new AtomicReference<>(); Disposable upstream; - SampleTimedObserver(Observer actual, long period, TimeUnit unit, Scheduler scheduler) { + SampleTimedObserver(Observer actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { this.downstream = actual; this.period = period; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override @@ -79,7 +89,17 @@ public void onSubscribe(Disposable d) { @Override public void onNext(T t) { - lazySet(t); + T oldValue = getAndSet(t); + if (oldValue != null && onDropped != null) { + try { + onDropped.accept(oldValue); + } catch (Throwable throwable) { + Exceptions.throwIfFatal(throwable); + cancelTimer(); + upstream.dispose(); + downstream.onError(throwable); + } + } } @Override @@ -123,8 +143,8 @@ static final class SampleTimedNoLast extends SampleTimedObserver { private static final long serialVersionUID = -7139995637533111443L; - SampleTimedNoLast(Observer actual, long period, TimeUnit unit, Scheduler scheduler) { - super(actual, period, unit, scheduler); + SampleTimedNoLast(Observer actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { + super(actual, period, unit, scheduler, onDropped); } @Override @@ -144,8 +164,8 @@ static final class SampleTimedEmitLast extends SampleTimedObserver { final AtomicInteger wip; - SampleTimedEmitLast(Observer actual, long period, TimeUnit unit, Scheduler scheduler) { - super(actual, period, unit, scheduler); + SampleTimedEmitLast(Observer actual, long period, TimeUnit unit, Scheduler scheduler, Consumer onDropped) { + super(actual, period, unit, scheduler, onDropped); this.wip = new AtomicInteger(1); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleWithObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleWithObservable.java index cae3259d12e..53b9aec31f4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleWithObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleWithObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMap.java index c62c23c0c5b..7ce5bb82f03 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; -import io.reactivex.rxjava3.internal.fuseable.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueDisposable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScan.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScan.java index bd0ba2b12ae..59a74661cc6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScan.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScan.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanSeed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanSeed.java index 89eb4046f0b..f0e197db7ea 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanSeed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanSeed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqual.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqual.java index 11eb6946968..e79f992243c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqual.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqual.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.BiPredicate; import io.reactivex.rxjava3.internal.disposables.ArrayCompositeDisposable; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableSequenceEqual extends Observable { final ObservableSource first; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualSingle.java index 9169cb64656..9b51815ce0e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ import io.reactivex.rxjava3.functions.BiPredicate; import io.reactivex.rxjava3.internal.disposables.ArrayCompositeDisposable; import io.reactivex.rxjava3.internal.fuseable.FuseToObservable; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableSequenceEqualSingle extends Single implements FuseToObservable { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerialized.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerialized.java index 98f757e6f72..c57d0d9a24e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerialized.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerialized.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleMaybe.java index 83a8569f059..b4068e834d5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleSingle.java index de4729f5e53..dd8032a400e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkip.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkip.java index e0000dc7a5f..0fe5787c1be 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkip.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkip.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLast.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLast.java index 3e45e38a795..68fabb3ac7d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLast.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLast.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimed.java index f70620b5c03..7cc6f34f24a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableSkipLastTimed extends AbstractObservableWithUpstream { final long time; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntil.java index 457158200dd..87535fabf22 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhile.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhile.java index d6dad232b58..1614b0b472b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhile.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhile.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOn.java index 8eac3ae04ed..5eaeaa50356 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmpty.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmpty.java index b697afc1c9b..6aa1d84ecfb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmpty.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmpty.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchMap.java index e533834541e..3e0558aacf1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,9 +21,10 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.AtomicThrowable; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableSwitchMap extends AbstractObservableWithUpstream { @@ -169,12 +170,9 @@ public boolean isDisposed() { @SuppressWarnings("unchecked") void disposeInner() { - SwitchMapInnerObserver a = active.get(); - if (a != CANCELLED) { - a = active.getAndSet((SwitchMapInnerObserver)CANCELLED); - if (a != CANCELLED && a != null) { - a.cancel(); - } + SwitchMapInnerObserver a = active.getAndSet((SwitchMapInnerObserver)CANCELLED); + if (a != null) { + a.cancel(); } } @@ -226,25 +224,6 @@ void drain() { SimpleQueue q = inner.queue; if (q != null) { - if (inner.done) { - boolean empty = q.isEmpty(); - if (delayErrors) { - if (empty) { - active.compareAndSet(inner, null); - continue; - } - } else { - Throwable ex = errors.get(); - if (ex != null) { - errors.tryTerminateConsumer(a); - return; - } - if (empty) { - active.compareAndSet(inner, null); - continue; - } - } - } boolean retry = false; @@ -370,9 +349,10 @@ public void onSubscribe(Disposable d) { @Override public void onNext(R t) { - if (index == parent.unique) { + SimpleQueue q = queue; + if (index == parent.unique && q != null) { if (t != null) { - queue.offer(t); + q.offer(t); } parent.drain(); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTake.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTake.java index 63f37db46e4..8cc73b1b565 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTake.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTake.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLast.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLast.java index bfa2ee0bdda..b0b04c141d2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLast.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLast.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -77,9 +77,7 @@ public void onComplete() { } T v = poll(); if (v == null) { - if (!cancelled) { - a.onComplete(); - } + a.onComplete(); return; } a.onNext(v); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOne.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOne.java index f2766db765f..cb243dd3bdf 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOne.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOne.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimed.java index be6f83db79e..33066f374b8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableTakeLastTimed extends AbstractObservableWithUpstream { final long count; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntil.java index f1d5d00a0d0..c32f3a6f654 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicate.java index 1727a24fb48..5183a6026e5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhile.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhile.java index 5c251c969e8..1b56e6cf34d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhile.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhile.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTimed.java index 041ce808405..6bf3b9f119c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,28 +19,36 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; import io.reactivex.rxjava3.observers.SerializedObserver; -import io.reactivex.rxjava3.plugins.RxJavaPlugins; public final class ObservableThrottleFirstTimed extends AbstractObservableWithUpstream { final long timeout; final TimeUnit unit; final Scheduler scheduler; - - public ObservableThrottleFirstTimed(ObservableSource source, - long timeout, TimeUnit unit, Scheduler scheduler) { + final Consumer onDropped; + + public ObservableThrottleFirstTimed( + ObservableSource source, + long timeout, + TimeUnit unit, + Scheduler scheduler, + Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; + this.onDropped = onDropped; } @Override public void subscribeActual(Observer t) { source.subscribe(new DebounceTimedObserver<>( new SerializedObserver<>(t), - timeout, unit, scheduler.createWorker())); + timeout, unit, scheduler.createWorker(), + onDropped)); } static final class DebounceTimedObserver @@ -52,18 +60,21 @@ static final class DebounceTimedObserver final long timeout; final TimeUnit unit; final Scheduler.Worker worker; - + final Consumer onDropped; Disposable upstream; - volatile boolean gate; - boolean done; - - DebounceTimedObserver(Observer actual, long timeout, TimeUnit unit, Worker worker) { + DebounceTimedObserver( + Observer actual, + long timeout, + TimeUnit unit, + Worker worker, + Consumer onDropped) { this.downstream = actual; this.timeout = timeout; this.unit = unit; this.worker = worker; + this.onDropped = onDropped; } @Override @@ -76,7 +87,7 @@ public void onSubscribe(Disposable d) { @Override public void onNext(T t) { - if (!gate && !done) { + if (!gate) { gate = true; downstream.onNext(t); @@ -86,6 +97,15 @@ public void onNext(T t) { d.dispose(); } DisposableHelper.replace(this, worker.schedule(this, timeout, unit)); + } else if (onDropped != null) { + try { + onDropped.accept(t); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.dispose(); + downstream.onError(ex); + worker.dispose(); + } } } @@ -96,22 +116,14 @@ public void run() { @Override public void onError(Throwable t) { - if (done) { - RxJavaPlugins.onError(t); - } else { - done = true; - downstream.onError(t); - worker.dispose(); - } + downstream.onError(t); + worker.dispose(); } @Override public void onComplete() { - if (!done) { - done = true; - downstream.onComplete(); - worker.dispose(); - } + downstream.onComplete(); + worker.dispose(); } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatest.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatest.java index 253f5d35013..caf14d3a5e1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatest.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Emits the next or latest item when the given time elapses. @@ -41,19 +44,24 @@ public final class ObservableThrottleLatest extends AbstractObservableWithUps final boolean emitLast; + final Consumer onDropped; + public ObservableThrottleLatest(Observable source, - long timeout, TimeUnit unit, Scheduler scheduler, - boolean emitLast) { + long timeout, TimeUnit unit, + Scheduler scheduler, + boolean emitLast, + Consumer onDropped) { super(source); this.timeout = timeout; this.unit = unit; this.scheduler = scheduler; this.emitLast = emitLast; + this.onDropped = onDropped; } @Override protected void subscribeActual(Observer observer) { - source.subscribe(new ThrottleLatestObserver<>(observer, timeout, unit, scheduler.createWorker(), emitLast)); + source.subscribe(new ThrottleLatestObserver<>(observer, timeout, unit, scheduler.createWorker(), emitLast, onDropped)); } static final class ThrottleLatestObserver @@ -74,6 +82,8 @@ static final class ThrottleLatestObserver final AtomicReference latest; + final Consumer onDropped; + Disposable upstream; volatile boolean done; @@ -86,14 +96,17 @@ static final class ThrottleLatestObserver boolean timerRunning; ThrottleLatestObserver(Observer downstream, - long timeout, TimeUnit unit, Scheduler.Worker worker, - boolean emitLast) { + long timeout, TimeUnit unit, + Scheduler.Worker worker, + boolean emitLast, + Consumer onDropped) { this.downstream = downstream; this.timeout = timeout; this.unit = unit; this.worker = worker; this.emitLast = emitLast; this.latest = new AtomicReference<>(); + this.onDropped = onDropped; } @Override @@ -106,7 +119,17 @@ public void onSubscribe(Disposable d) { @Override public void onNext(T t) { - latest.set(t); + T old = latest.getAndSet(t); + if (onDropped != null && old != null) { + try { + onDropped.accept(old); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + upstream.dispose(); + error = ex; + done = true; + } + } drain(); } @@ -129,6 +152,22 @@ public void dispose() { upstream.dispose(); worker.dispose(); if (getAndIncrement() == 0) { + clear(); + } + } + + void clear() { + if (onDropped != null) { + T v = latest.getAndSet(null); + if (v != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } else { latest.lazySet(null); } } @@ -158,14 +197,27 @@ void drain() { for (;;) { if (cancelled) { - latest.lazySet(null); + clear(); return; } boolean d = done; + Throwable error = this.error; if (d && error != null) { - latest.lazySet(null); + if (onDropped != null) { + T v = latest.getAndSet(null); + if (v != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + error = new CompositeException(error, ex); + } + } + } else { + latest.lazySet(null); + } downstream.onError(error); worker.dispose(); return; @@ -175,9 +227,22 @@ void drain() { boolean empty = v == null; if (d) { - v = latest.getAndSet(null); - if (!empty && emitLast) { - downstream.onNext(v); + if (!empty) { + v = latest.getAndSet(null); + if (emitLast) { + downstream.onNext(v); + } else { + if (onDropped != null) { + try { + onDropped.accept(v); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(ex); + worker.dispose(); + return; + } + } + } } downstream.onComplete(); worker.dispose(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeInterval.java index 7dd47ec03bb..4a4e6a787f1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeout.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeout.java index dfef0e74e6d..1922251d54a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeout.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeout.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTimed.java index 29b17729305..d0f56951432 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimer.java index 778388f39b3..3c9500996e6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToList.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToList.java index 6a3c5322f21..e75986c77cb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToList.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToList.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Supplier; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.util.ExceptionHelper; public final class ObservableToList> @@ -28,12 +27,6 @@ public final class ObservableToList> final Supplier collectionSupplier; - @SuppressWarnings({ "unchecked", "rawtypes" }) - public ObservableToList(ObservableSource source, final int defaultCapacityHint) { - super(source); - this.collectionSupplier = (Supplier)Functions.createArrayList(defaultCapacityHint); - } - public ObservableToList(ObservableSource source, Supplier collectionSupplier) { super(source); this.collectionSupplier = collectionSupplier; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListSingle.java index 0ac41b12d61..de4db3ecf1b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOn.java index 2c5f748477d..d06d64f34c5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsing.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsing.java index dec3da5ebe6..1ffdef32d6e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsing.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsing.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -115,11 +115,9 @@ public void onError(Throwable t) { } } - upstream.dispose(); downstream.onError(t); } else { downstream.onError(t); - upstream.dispose(); disposeResource(); } } @@ -137,11 +135,9 @@ public void onComplete() { } } - upstream.dispose(); downstream.onComplete(); } else { downstream.onComplete(); - upstream.dispose(); disposeResource(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindow.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindow.java index 3ada9cd93c9..c742ad6288e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindow.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindow.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -51,18 +51,20 @@ static final class WindowExactObserver final long count; final int capacityHint; + final AtomicBoolean cancelled; + long size; Disposable upstream; UnicastSubject window; - volatile boolean cancelled; - WindowExactObserver(Observer> actual, long count, int capacityHint) { this.downstream = actual; this.count = count; this.capacityHint = capacityHint; + this.cancelled = new AtomicBoolean(); + this.lazySet(1); } @Override @@ -78,7 +80,9 @@ public void onSubscribe(Disposable d) { public void onNext(T t) { UnicastSubject w = window; ObservableWindowSubscribeIntercept intercept = null; - if (w == null && !cancelled) { + if (w == null && !cancelled.get()) { + getAndIncrement(); + w = UnicastSubject.create(capacityHint, this); window = w; intercept = new ObservableWindowSubscribeIntercept<>(w); @@ -92,15 +96,12 @@ public void onNext(T t) { size = 0; window = null; w.onComplete(); - if (cancelled) { - upstream.dispose(); - } } if (intercept != null && intercept.tryAbandon()) { + window = null; w.onComplete(); w = null; - window = null; } } } @@ -127,23 +128,25 @@ public void onComplete() { @Override public void dispose() { - cancelled = true; + if (cancelled.compareAndSet(false, true)) { + run(); + } } @Override public boolean isDisposed() { - return cancelled; + return cancelled.get(); } @Override public void run() { - if (cancelled) { + if (decrementAndGet() == 0) { upstream.dispose(); } } } - static final class WindowSkipObserver extends AtomicBoolean + static final class WindowSkipObserver extends AtomicInteger implements Observer, Disposable, Runnable { private static final long serialVersionUID = 3366976432059579510L; @@ -153,23 +156,23 @@ static final class WindowSkipObserver extends AtomicBoolean final int capacityHint; final ArrayDeque> windows; - long index; + final AtomicBoolean cancelled; - volatile boolean cancelled; + long index; /** Counts how many elements were emitted to the very first window in windows. */ long firstEmission; Disposable upstream; - final AtomicInteger wip = new AtomicInteger(); - WindowSkipObserver(Observer> actual, long count, long skip, int capacityHint) { this.downstream = actual; this.count = count; this.skip = skip; this.capacityHint = capacityHint; this.windows = new ArrayDeque<>(); + this.cancelled = new AtomicBoolean(); + this.lazySet(1); } @Override @@ -191,8 +194,8 @@ public void onNext(T t) { ObservableWindowSubscribeIntercept intercept = null; - if (i % s == 0 && !cancelled) { - wip.getAndIncrement(); + if (i % s == 0 && !cancelled.get()) { + getAndIncrement(); UnicastSubject w = UnicastSubject.create(capacityHint, this); intercept = new ObservableWindowSubscribeIntercept<>(w); ws.offer(w); @@ -207,8 +210,7 @@ public void onNext(T t) { if (c >= count) { ws.poll().onComplete(); - if (ws.isEmpty() && cancelled) { - this.upstream.dispose(); + if (ws.isEmpty() && cancelled.get()) { return; } firstEmission = c - s; @@ -243,20 +245,20 @@ public void onComplete() { @Override public void dispose() { - cancelled = true; + if (cancelled.compareAndSet(false, true)) { + run(); + } } @Override public boolean isDisposed() { - return cancelled; + return cancelled.get(); } @Override public void run() { - if (wip.decrementAndGet() == 0) { - if (cancelled) { - upstream.dispose(); - } + if (decrementAndGet() == 0) { + upstream.dispose(); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundary.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundary.java index 503a5cbd295..a1ecb8e8690 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundary.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundary.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundarySelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundarySelector.java index 367ddf2d02f..cec435839e1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundarySelector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowBoundarySelector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,9 +23,9 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.UnicastSubject; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowSubscribeIntercept.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowSubscribeIntercept.java index da6f96f2a3e..4cc879662d4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowSubscribeIntercept.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowSubscribeIntercept.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -43,4 +43,4 @@ protected void subscribeActual(Observer s) { boolean tryAbandon() { return !once.get() && once.compareAndSet(false, true); } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowTimed.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowTimed.java index 5c295f46089..2cc96a61a93 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowTimed.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowTimed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,8 +23,8 @@ import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; +import io.reactivex.rxjava3.operators.SimplePlainQueue; import io.reactivex.rxjava3.subjects.UnicastSubject; public final class ObservableWindowTimed extends AbstractObservableWithUpstream> { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFrom.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFrom.java index b7e283c5156..95b21187a71 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFrom.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFrom.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromMany.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromMany.java index c9f2a6b57af..f8327b82846 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromMany.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromMany.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.Arrays; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZip.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZip.java index ace2d748e50..e1626b48656 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZip.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZip.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,7 +22,7 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.disposables.*; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; public final class ObservableZip extends Observable { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterable.java index d775c585157..7c8f5e6d0e5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -112,7 +112,7 @@ public void onNext(T t) { u = Objects.requireNonNull(iterator.next(), "The iterator returned a null value"); } catch (Throwable e) { Exceptions.throwIfFatal(e); - error(e); + fail(e); return; } @@ -121,7 +121,7 @@ public void onNext(T t) { v = Objects.requireNonNull(zipper.apply(t, u), "The zipper function returned a null value"); } catch (Throwable e) { Exceptions.throwIfFatal(e); - error(e); + fail(e); return; } @@ -133,7 +133,7 @@ public void onNext(T t) { b = iterator.hasNext(); } catch (Throwable e) { Exceptions.throwIfFatal(e); - error(e); + fail(e); return; } @@ -144,7 +144,7 @@ public void onNext(T t) { } } - void error(Throwable e) { + void fail(Throwable e) { done = true; upstream.dispose(); downstream.onError(e); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObserverResourceWrapper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObserverResourceWrapper.java index 4245417ce78..a3c797fee63 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObserverResourceWrapper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObserverResourceWrapper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelCollect.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelCollect.java index 29f9d916749..60e36beed44 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelCollect.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelCollect.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -47,6 +47,8 @@ public ParallelCollect(ParallelFlowable source, @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelConcatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelConcatMap.java index 1ff745ecba9..ebdcf0bdf3b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelConcatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelConcatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,6 +19,7 @@ import io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatMap; import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; import java.util.Objects; @@ -55,6 +56,8 @@ public int parallelism() { @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelDoOnNextTry.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelDoOnNextTry.java index 6b3f69ff978..b8ff3885355 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelDoOnNextTry.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelDoOnNextTry.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -48,6 +48,8 @@ public ParallelDoOnNextTry(ParallelFlowable source, Consumer onNex @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilter.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilter.java index 14f414dce3f..28987a6fc9c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilter.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Predicate; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -40,6 +40,8 @@ public ParallelFilter(ParallelFlowable source, Predicate predicate @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilterTry.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilterTry.java index bfd22ec5a85..563937e1a63 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilterTry.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFilterTry.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -46,6 +46,8 @@ public ParallelFilterTry(ParallelFlowable source, Predicate predic @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMap.java index 1e0c9f5738d..227521143a2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,6 +18,7 @@ import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap; import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Flattens the generated Publishers on each rail. @@ -57,6 +58,8 @@ public int parallelism() { @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMapIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMapIterable.java index 1bb127233f2..9e6c45a9ca5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMapIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFlatMapIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,6 +18,7 @@ import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.operators.flowable.FlowableFlattenIterable; import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Flattens the generated {@link Iterable}s on each rail. @@ -50,6 +51,8 @@ public int parallelism() { @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromArray.java index cb40caaad59..d2512ccd7f1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,6 +16,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Wraps multiple Publishers into a ParallelFlowable which runs them @@ -37,6 +38,8 @@ public int parallelism() { @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromPublisher.java index 0d4fb9a4c55..eb57bccea5d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelFromPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,11 +19,13 @@ import io.reactivex.rxjava3.core.FlowableSubscriber; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * Dispatches the values from upstream in a round robin fashion to subscribers which are @@ -51,6 +53,8 @@ public int parallelism() { @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } @@ -150,10 +154,6 @@ void setupSubscribers() { final int m = subs.length; for (int i = 0; i < m; i++) { - if (cancelled) { - return; - } - subscriberCount.lazySet(i + 1); subs[i].onSubscribe(new RailSubscription(i, m)); @@ -204,7 +204,7 @@ public void onNext(T t) { if (sourceMode == QueueSubscription.NONE) { if (!queue.offer(t)) { upstream.cancel(); - onError(new MissingBackpressureException("Queue is full?")); + onError(new QueueOverflowException()); return; } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelJoin.java index 4545b133f5b..2852fda8c7f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelJoin.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,11 +18,12 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.MissingBackpressureException; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; +import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -152,7 +153,7 @@ public void onNext(JoinInnerSubscriber inner, T value) { if (!q.offer(value)) { cancelAll(); - Throwable mbe = new MissingBackpressureException("Queue full?!"); + Throwable mbe = new QueueOverflowException(); if (errors.compareAndSet(null, mbe)) { downstream.onError(mbe); } else { @@ -169,7 +170,7 @@ public void onNext(JoinInnerSubscriber inner, T value) { if (!q.offer(value)) { cancelAll(); - onError(new MissingBackpressureException("Queue full?!")); + onError(new QueueOverflowException()); return; } @@ -298,18 +299,13 @@ void drainLoop() { } } - if (e != 0 && r != Long.MAX_VALUE) { - requested.addAndGet(-e); + if (e != 0) { + BackpressureHelper.produced(requested, e); } - int w = get(); - if (w == missed) { - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } @@ -337,7 +333,7 @@ void onNext(JoinInnerSubscriber inner, T value) { if (!q.offer(value)) { inner.cancel(); - errors.tryAddThrowableOrReport(new MissingBackpressureException("Queue full?!")); + errors.tryAddThrowableOrReport(new QueueOverflowException()); done.decrementAndGet(); drainLoop(); return; @@ -350,10 +346,9 @@ void onNext(JoinInnerSubscriber inner, T value) { SimplePlainQueue q = inner.getQueue(); if (!q.offer(value)) { - if (inner.cancel()) { - errors.tryAddThrowableOrReport(new MissingBackpressureException("Queue full?!")); - done.decrementAndGet(); - } + inner.cancel(); + errors.tryAddThrowableOrReport(new QueueOverflowException()); + done.decrementAndGet(); } if (getAndIncrement() != 0) { @@ -464,18 +459,13 @@ void drainLoop() { } } - if (e != 0 && r != Long.MAX_VALUE) { - requested.addAndGet(-e); + if (e != 0) { + BackpressureHelper.produced(requested, e); } - int w = get(); - if (w == missed) { - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMap.java index c9418878536..81d70a01d9e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,8 +18,8 @@ import io.reactivex.rxjava3.core.FlowableSubscriber; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -44,6 +44,8 @@ public ParallelMap(ParallelFlowable source, Function @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMapTry.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMapTry.java index 30250f2e602..cac64f37114 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMapTry.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelMapTry.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.parallel.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -49,6 +49,8 @@ public ParallelMapTry(ParallelFlowable source, Function[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelPeek.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelPeek.java index 206a2dd4721..42f65567ca0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelPeek.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelPeek.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -66,6 +66,8 @@ public ParallelPeek(ParallelFlowable source, @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduce.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduce.java index 53fa2b38992..b955ca711ae 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduce.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduce.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -46,6 +46,8 @@ public ParallelReduce(ParallelFlowable source, Supplier initialS @Override public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduceFull.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduceFull.java index a47bc5b8987..2e24b9e2562 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduceFull.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelReduceFull.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelRunOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelRunOn.java index ceb2a7665a2..22f822db34a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelRunOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelRunOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,13 +19,13 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; -import io.reactivex.rxjava3.exceptions.MissingBackpressureException; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; +import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.schedulers.SchedulerMultiWorkerSupport; import io.reactivex.rxjava3.internal.schedulers.SchedulerMultiWorkerSupport.WorkerCallback; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -49,7 +49,9 @@ public ParallelRunOn(ParallelFlowable parent, } @Override - public void subscribe(final Subscriber[] subscribers) { + public void subscribe(Subscriber[] subscribers) { + subscribers = RxJavaPlugins.onSubscribe(this, subscribers); + if (!validate(subscribers)) { return; } @@ -146,7 +148,7 @@ public final void onNext(T t) { } if (!queue.offer(t)) { upstream.cancel(); - onError(new MissingBackpressureException("Queue is full?!")); + onError(new QueueOverflowException()); return; } schedule(); @@ -430,19 +432,14 @@ public void run() { } } - if (e != 0L && r != Long.MAX_VALUE) { - requested.addAndGet(-e); + if (e != 0L) { + BackpressureHelper.produced(requested, e); } - int w = get(); - if (w == missed) { - consumed = c; - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + consumed = c; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelSortedJoin.java b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelSortedJoin.java index 7994abf6976..fb20bb65b90 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelSortedJoin.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/parallel/ParallelSortedJoin.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -215,48 +215,41 @@ void drain() { e++; } - if (e == r) { - if (cancelled) { - Arrays.fill(lists, null); - return; - } + if (cancelled) { + Arrays.fill(lists, null); + return; + } - Throwable ex = error.get(); - if (ex != null) { - cancelAll(); - Arrays.fill(lists, null); - a.onError(ex); - return; - } + Throwable ex = error.get(); + if (ex != null) { + cancelAll(); + Arrays.fill(lists, null); + a.onError(ex); + return; + } - boolean empty = true; + boolean empty = true; - for (int i = 0; i < n; i++) { - if (indexes[i] != lists[i].size()) { - empty = false; - break; - } + for (int i = 0; i < n; i++) { + if (indexes[i] != lists[i].size()) { + empty = false; + break; } + } - if (empty) { - Arrays.fill(lists, null); - a.onComplete(); - return; - } + if (empty) { + Arrays.fill(lists, null); + a.onComplete(); + return; } - if (e != 0 && r != Long.MAX_VALUE) { - requested.addAndGet(-e); + if (e != 0) { + BackpressureHelper.produced(requested, e); } - int w = get(); - if (w == missed) { - missed = addAndGet(-missed); - if (missed == 0) { - break; - } - } else { - missed = w; + missed = addAndGet(-missed); + if (missed == 0) { + break; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleAmb.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleAmb.java index 7fd1dba29f0..24ff7eabed4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleAmb.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleAmb.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCache.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCache.java index a8cb63f0eda..7f0848e4c1a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCache.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCache.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleContains.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleContains.java index aaa249a6e8f..2497fb2047a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleContains.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleContains.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCreate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCreate.java index 8c5331c87bd..c0f6c4b1d0b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCreate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleCreate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDefer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDefer.java index 24a35fbdee2..ddf2b2c3479 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDefer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDefer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelay.java index 12da3821fcb..1a92d389fad 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelay.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithCompletable.java index c3f74584595..164a5029928 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithObservable.java index a0eb8ab860a..58ed261e714 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -56,7 +56,7 @@ static final class OtherSubscriber @Override public void onSubscribe(Disposable d) { - if (DisposableHelper.set(this, d)) { + if (DisposableHelper.setOnce(this, d)) { downstream.onSubscribe(this); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithPublisher.java index 1d8a601a024..12eeb7fd13d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithSingle.java index d8e11665c89..1f2ffb21dde 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayWithSingle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerialize.java index 6d072f4ceaf..e573560e76c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDetach.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDetach.java index 72e1f3def34..2a9acc8a193 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDetach.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDetach.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccess.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccess.java index d7ab5e4c79b..51b73f0216b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccess.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccess.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminate.java index eca7ebff151..651c9ee60d7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinally.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinally.java index 0ba60a6493a..a64060cc977 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinally.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinally.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnDispose.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnDispose.java index 262f4f7d433..8c9fd1cb1b3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnDispose.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnDispose.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnError.java index 87061fdafe7..dd24ac210c9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnEvent.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnEvent.java index 9aa9fccd8ad..de53462380d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnEvent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnEvent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java index 288e8970cda..2d4e15f27c5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.single; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSubscribe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSubscribe.java index 24a24caac93..567f95404b4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSubscribe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSubscribe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSuccess.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSuccess.java index 2efec6acdd7..855dc7e3884 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSuccess.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnSuccess.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminate.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminate.java index 1bb0ca2decb..d6f5dea7fa3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminate.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminate.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleEquals.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleEquals.java index 0a839ab7470..d11f938a2ee 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleEquals.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleEquals.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -74,20 +74,13 @@ public void onSuccess(T value) { @Override public void onError(Throwable e) { - for (;;) { - int state = count.get(); - if (state >= 2) { - RxJavaPlugins.onError(e); - return; - } - if (count.compareAndSet(state, 2)) { - set.dispose(); - downstream.onError(e); - return; - } + int state = count.getAndSet(-1); + if (state == 0 || state == 1) { + set.dispose(); + downstream.onError(e); + } else { + RxJavaPlugins.onError(e); } } - } - } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleError.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleError.java index 89b9bc3baaa..f016d2c9a97 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleError.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleError.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMap.java index d622f83faee..ff38538b095 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java index d1051f3357e..7f6f58de845 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletable.java index d914799640d..a06241c56c9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowable.java index 9e05a25ef89..6d697265888 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -154,7 +154,7 @@ void drain() { long e = 0L; if (r == Long.MAX_VALUE) { - slowPath(a, iterator); + fastPath(a, iterator); return; } @@ -213,7 +213,7 @@ void drain() { } } - void slowPath(Subscriber a, Iterator iterator) { + void fastPath(Subscriber a, Iterator iterator) { for (;;) { if (cancelled) { return; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservable.java index add137d7cb5..c07131da8c7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybe.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybe.java index d810f8f5c3d..c58e6aeeae9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybe.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybe.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java index 1ba9796b7ce..bb592a74a9e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java index c89913791d9..59a067832fe 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ * A Flowable that emits items based on applying a specified function to the item emitted by the * source Single, where that function returns a Publisher. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallable.java index a78dde3e36d..d1a6b73384b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisher.java index e18394eb1a5..860e47f9041 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisher.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplier.java index e6fd32603f3..83e2dc47804 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromUnsafeSource.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromUnsafeSource.java index 328ab873b6c..e09e38c8335 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromUnsafeSource.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFromUnsafeSource.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleHide.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleHide.java index 34f5dc4aed7..01a4e36d6e2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleHide.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleHide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java index 47f8bf1e880..5df3dae35df 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,7 +14,6 @@ package io.reactivex.rxjava3.internal.operators.single; import java.util.*; -import java.util.concurrent.Callable; import org.reactivestreams.Publisher; @@ -31,14 +30,9 @@ private SingleInternalHelper() { throw new IllegalStateException("No instances!"); } - enum NoSuchElementCallable implements Supplier, Callable { + enum NoSuchElementSupplier implements Supplier { INSTANCE; - @Override - public NoSuchElementException call() { - return new NoSuchElementException(); - } - @Override public NoSuchElementException get() { return new NoSuchElementException(); @@ -46,7 +40,7 @@ public NoSuchElementException get() { } public static Supplier emptyThrower() { - return NoSuchElementCallable.INSTANCE; + return NoSuchElementSupplier.INSTANCE; } @SuppressWarnings("rawtypes") diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleJust.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleJust.java index 4fd2387f960..ceb94b93a14 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleJust.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleJust.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleLift.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleLift.java index 8382b2f1b82..5b127e58cb4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleLift.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleLift.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMap.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMap.java index 534b41495c5..3fb20516ce0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMap.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMap.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterialize.java index 1ffbfe073a2..c09d28ffd17 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterialize.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterialize.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleNever.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleNever.java index ea76fac50de..0feefe196d9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleNever.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleNever.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOn.java index 168a88ee8ec..e513e16fa26 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java index 7be9bd817c9..bd083cddb18 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorReturn.java index 1a606d27500..d1f8b66fd91 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorReturn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleResumeNext.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleResumeNext.java index 070b2447474..554a2a254b6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleResumeNext.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleResumeNext.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOn.java index 3347fc19894..56cf684e9f4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntil.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntil.java index 50e8b897636..fb5d0989f66 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntil.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java index 2eac3bbc3ae..f6d65f7c148 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeout.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeout.java index f529d02446a..cc5b9237277 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeout.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeout.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -113,11 +113,7 @@ public void onError(Throwable e) { @Override public void run() { - Disposable d = get(); - if (d != DisposableHelper.DISPOSED && compareAndSet(d, DisposableHelper.DISPOSED)) { - if (d != null) { - d.dispose(); - } + if (DisposableHelper.dispose(this)) { SingleSource other = this.other; if (other == null) { downstream.onError(new TimeoutException(timeoutMessage(timeout, unit))); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimer.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimer.java index 5188f3a2c91..07748952c85 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowable.java index 890f6b05692..e692dea5b96 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.single; import org.reactivestreams.Subscriber; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservable.java index 810adaea3f6..45863177401 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.single; import io.reactivex.rxjava3.core.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOn.java index 9a78d61bb70..4b18599c84d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUsing.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUsing.java index 57f9daf263c..55ab6c31ff0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUsing.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleUsing.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArray.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArray.java index 9130a2bf356..b53d2f21844 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArray.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArray.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -74,7 +74,7 @@ static final class ZipCoordinator extends AtomicInteger implements Disposa final ZipSingleObserver[] observers; - final Object[] values; + Object[] values; @SuppressWarnings("unchecked") ZipCoordinator(SingleObserver observer, int n, Function zipper) { @@ -100,11 +100,16 @@ public void dispose() { for (ZipSingleObserver d : observers) { d.dispose(); } + + values = null; } } void innerSuccess(T value, int index) { - values[index] = value; + Object[] values = this.values; + if (values != null) { + values[index] = value; + } if (decrementAndGet() == 0) { R v; @@ -112,10 +117,12 @@ void innerSuccess(T value, int index) { v = Objects.requireNonNull(zipper.apply(values), "The zipper returned a null value"); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); + this.values = null; downstream.onError(ex); return; } + this.values = null; downstream.onSuccess(v); } } @@ -134,6 +141,7 @@ void disposeExcept(int index) { void innerError(Throwable ex, int index) { if (getAndSet(0) > 0) { disposeExcept(index); + values = null; downstream.onError(ex); } else { RxJavaPlugins.onError(ex); diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterable.java index ad393987be8..935550ab479 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/queue/MpscLinkedQueue.java b/src/main/java/io/reactivex/rxjava3/internal/queue/MpscLinkedQueue.java index 31fe6eca9b1..e8d19c633e3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/queue/MpscLinkedQueue.java +++ b/src/main/java/io/reactivex/rxjava3/internal/queue/MpscLinkedQueue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; +import io.reactivex.rxjava3.operators.SimplePlainQueue; /** * A multi-producer single consumer unbounded queue. @@ -91,6 +91,8 @@ public T poll() { // we have to null out the value because we are going to hang on to the node final T nextValue = nextNode.getAndNullValue(); spConsumerNode(nextNode); + // unlink previous consumer to help gc + currConsumerNode.soNext(null); return nextValue; } else if (currConsumerNode != lvProducerNode()) { @@ -101,6 +103,8 @@ else if (currConsumerNode != lvProducerNode()) { // we have to null out the value because we are going to hang on to the node final T nextValue = nextNode.getAndNullValue(); spConsumerNode(nextNode); + // unlink previous consumer to help gc + currConsumerNode.soNext(null); return nextValue; } return null; diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTask.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTask.java index a1c4bc2ce17..556fcd23c7b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTask.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTask.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -35,14 +32,17 @@ abstract class AbstractDirectTask protected final Runnable runnable; + protected final boolean interruptOnCancel; + protected Thread runner; protected static final FutureTask FINISHED = new FutureTask<>(Functions.EMPTY_RUNNABLE, null); protected static final FutureTask DISPOSED = new FutureTask<>(Functions.EMPTY_RUNNABLE, null); - AbstractDirectTask(Runnable runnable) { + AbstractDirectTask(Runnable runnable, boolean interruptOnCancel) { this.runnable = runnable; + this.interruptOnCancel = interruptOnCancel; } @Override @@ -51,7 +51,7 @@ public final void dispose() { if (f != FINISHED && f != DISPOSED) { if (compareAndSet(f, DISPOSED)) { if (f != null) { - f.cancel(runner != Thread.currentThread()); + cancelFuture(f); } } } @@ -70,7 +70,7 @@ public final void setFuture(Future future) { break; } if (f == DISPOSED) { - future.cancel(runner != Thread.currentThread()); + cancelFuture(future); break; } if (compareAndSet(f, future)) { @@ -79,8 +79,36 @@ public final void setFuture(Future future) { } } + private void cancelFuture(Future future) { + if (runner == Thread.currentThread()) { + future.cancel(false); + } else { + future.cancel(interruptOnCancel); + } + } + @Override public Runnable getWrappedRunnable() { return runnable; } + + @Override + public String toString() { + String status; + Future f = get(); + if (f == FINISHED) { + status = "Finished"; + } else if (f == DISPOSED) { + status = "Disposed"; + } else { + Thread r = runner; + if (r != null) { + status = "Running on " + runner; + } else { + status = "Waiting"; + } + } + + return getClass().getSimpleName() + "[" + status + "]"; + } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ComputationScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ComputationScheduler.java index e0bf388772d..f6845e660e7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ComputationScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ComputationScheduler.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.schedulers; import java.util.concurrent.*; @@ -175,15 +173,9 @@ public void start() { @Override public void shutdown() { - for (;;) { - FixedSchedulerPool curr = pool.get(); - if (curr == NONE) { - return; - } - if (pool.compareAndSet(curr, NONE)) { - curr.shutdown(); - return; - } + FixedSchedulerPool curr = pool.getAndSet(NONE); + if (curr != NONE) { + curr.shutdown(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancel.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancel.java index 370fb5d8a2f..72ac8ef5251 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancel.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancel.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ExecutorScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ExecutorScheduler.java index a9547e64e1b..fa0bcab7f86 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ExecutorScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ExecutorScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -38,7 +38,9 @@ public final class ExecutorScheduler extends Scheduler { @NonNull final Executor executor; - static final Scheduler HELPER = Schedulers.single(); + static final class SingleHolder { + static final Scheduler HELPER = Schedulers.single(); + } public ExecutorScheduler(@NonNull Executor executor, boolean interruptibleWorker, boolean fair) { this.executor = executor; @@ -58,7 +60,7 @@ public Disposable scheduleDirect(@NonNull Runnable run) { Runnable decoratedRun = RxJavaPlugins.onSchedule(run); try { if (executor instanceof ExecutorService) { - ScheduledDirectTask task = new ScheduledDirectTask(decoratedRun); + ScheduledDirectTask task = new ScheduledDirectTask(decoratedRun, interruptibleWorker); Future f = ((ExecutorService)executor).submit(task); task.setFuture(f); return task; @@ -85,7 +87,7 @@ public Disposable scheduleDirect(@NonNull Runnable run, final long delay, final final Runnable decoratedRun = RxJavaPlugins.onSchedule(run); if (executor instanceof ScheduledExecutorService) { try { - ScheduledDirectTask task = new ScheduledDirectTask(decoratedRun); + ScheduledDirectTask task = new ScheduledDirectTask(decoratedRun, interruptibleWorker); Future f = ((ScheduledExecutorService)executor).schedule(task, delay, unit); task.setFuture(f); return task; @@ -97,7 +99,7 @@ public Disposable scheduleDirect(@NonNull Runnable run, final long delay, final final DelayedRunnable dr = new DelayedRunnable(decoratedRun); - Disposable delayed = HELPER.scheduleDirect(new DelayedDispose(dr), delay, unit); + Disposable delayed = SingleHolder.HELPER.scheduleDirect(new DelayedDispose(dr), delay, unit); dr.timed.replace(delayed); @@ -110,7 +112,7 @@ public Disposable schedulePeriodicallyDirect(@NonNull Runnable run, long initial if (executor instanceof ScheduledExecutorService) { Runnable decoratedRun = RxJavaPlugins.onSchedule(run); try { - ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun); + ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun, interruptibleWorker); Future f = ((ScheduledExecutorService)executor).scheduleAtFixedRate(task, initialDelay, period, unit); task.setFuture(f); return task; @@ -202,7 +204,7 @@ public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit final Runnable decoratedRun = RxJavaPlugins.onSchedule(run); - ScheduledRunnable sr = new ScheduledRunnable(new SequentialDispose(mar, decoratedRun), tasks); + ScheduledRunnable sr = new ScheduledRunnable(new SequentialDispose(mar, decoratedRun), tasks, interruptibleWorker); tasks.add(sr); if (executor instanceof ScheduledExecutorService) { @@ -215,7 +217,7 @@ public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit return EmptyDisposable.INSTANCE; } } else { - final Disposable d = HELPER.scheduleDirect(sr, delay, unit); + final Disposable d = SingleHolder.HELPER.scheduleDirect(sr, delay, unit); sr.setFuture(new DisposeOnCancel(d)); } @@ -257,9 +259,7 @@ void runFair() { } Runnable run = q.poll(); - if (run != null) { - run.run(); - } + run.run(); // never null because of offer + increment happens first if (disposed) { q.clear(); @@ -322,6 +322,10 @@ public void run() { } try { actual.run(); + } catch (Throwable ex) { + // Exceptions.throwIfFatal(ex); nowhere to go + RxJavaPlugins.onError(ex); + throw ex; } finally { lazySet(true); } @@ -388,7 +392,13 @@ public void run() { thread = Thread.currentThread(); if (compareAndSet(READY, RUNNING)) { try { - run.run(); + try { + run.run(); + } catch (Throwable ex) { + // Exceptions.throwIfFatal(ex); nowhere to go + RxJavaPlugins.onError(ex); + throw ex; + } } finally { thread = null; if (compareAndSet(RUNNING, FINISHED)) { @@ -465,11 +475,17 @@ public void run() { Runnable r = get(); if (r != null) { try { - r.run(); - } finally { - lazySet(null); - timed.lazySet(DisposableHelper.DISPOSED); - direct.lazySet(DisposableHelper.DISPOSED); + try { + r.run(); + } finally { + lazySet(null); + timed.lazySet(DisposableHelper.DISPOSED); + direct.lazySet(DisposableHelper.DISPOSED); + } + } catch (Throwable ex) { + // Exceptions.throwIfFatal(ex); nowhere to go + RxJavaPlugins.onError(ex); + throw ex; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinScheduler.java index 21fbbead832..e2430e74cbc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTask.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTask.java index a855b44683c..1fd37f5d933 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTask.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTask.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -20,7 +17,6 @@ import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -54,12 +50,13 @@ public Void call() { runner = Thread.currentThread(); try { task.run(); - setRest(executor.submit(this)); runner = null; + setRest(executor.submit(this)); } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); + // Exceptions.throwIfFatal(ex); nowhere to go runner = null; RxJavaPlugins.onError(ex); + throw ex; } return null; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/IoScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/IoScheduler.java index 3a4bac58b25..cfe95206856 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/IoScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/IoScheduler.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -48,6 +45,10 @@ public final class IoScheduler extends Scheduler { /** The name of the system property for setting the thread priority for this Scheduler. */ private static final String KEY_IO_PRIORITY = "rx3.io-priority"; + /** The name of the system property for setting the release behaviour for this Scheduler. */ + private static final String KEY_SCHEDULED_RELEASE = "rx3.io-scheduled-release"; + static boolean USE_SCHEDULED_RELEASE; + static final CachedWorkerPool NONE; static { @@ -63,6 +64,8 @@ public final class IoScheduler extends Scheduler { EVICTOR_THREAD_FACTORY = new RxThreadFactory(EVICTOR_THREAD_NAME_PREFIX, priority); + USE_SCHEDULED_RELEASE = Boolean.getBoolean(KEY_SCHEDULED_RELEASE); + NONE = new CachedWorkerPool(0, null, WORKER_THREAD_FACTORY); NONE.shutdown(); } @@ -93,7 +96,7 @@ static final class CachedWorkerPool implements Runnable { @Override public void run() { - evictExpiredWorkers(); + evictExpiredWorkers(expiringWorkerQueue, allWorkers); } ThreadWorker get() { @@ -120,7 +123,7 @@ void release(ThreadWorker threadWorker) { expiringWorkerQueue.offer(threadWorker); } - void evictExpiredWorkers() { + static void evictExpiredWorkers(ConcurrentLinkedQueue expiringWorkerQueue, CompositeDisposable allWorkers) { if (!expiringWorkerQueue.isEmpty()) { long currentTimestamp = now(); @@ -138,7 +141,7 @@ void evictExpiredWorkers() { } } - long now() { + static long now() { return System.nanoTime(); } @@ -178,15 +181,9 @@ public void start() { @Override public void shutdown() { - for (;;) { - CachedWorkerPool curr = pool.get(); - if (curr == NONE) { - return; - } - if (pool.compareAndSet(curr, NONE)) { - curr.shutdown(); - return; - } + CachedWorkerPool curr = pool.getAndSet(NONE); + if (curr != NONE) { + curr.shutdown(); } } @@ -200,7 +197,7 @@ public int size() { return pool.get().allWorkers.size(); } - static final class EventLoopWorker extends Scheduler.Worker { + static final class EventLoopWorker extends Scheduler.Worker implements Runnable { private final CompositeDisposable tasks; private final CachedWorkerPool pool; private final ThreadWorker threadWorker; @@ -218,11 +215,20 @@ public void dispose() { if (once.compareAndSet(false, true)) { tasks.dispose(); - // releasing the pool should be the last action - pool.release(threadWorker); + if (USE_SCHEDULED_RELEASE) { + threadWorker.scheduleActual(this, 0, TimeUnit.NANOSECONDS, null); + } else { + // releasing the pool should be the last action + pool.release(threadWorker); + } } } + @Override + public void run() { + pool.release(threadWorker); + } + @Override public boolean isDisposed() { return once.get(); @@ -241,7 +247,8 @@ public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull Ti } static final class ThreadWorker extends NewThreadWorker { - private long expirationTime; + + long expirationTime; ThreadWorker(ThreadFactory threadFactory) { super(threadFactory); diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadScheduler.java index 1cd48ce1e04..1c29efddc54 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadScheduler.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadWorker.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadWorker.java index d811c8e7823..764241e76e3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadWorker.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NewThreadWorker.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ * worker but doesn't perform task-tracking operations. * */ -public class NewThreadWorker extends Scheduler.Worker implements Disposable { +public class NewThreadWorker extends Scheduler.Worker { private final ScheduledExecutorService executor; volatile boolean disposed; @@ -59,7 +59,7 @@ public Disposable schedule(@NonNull final Runnable action, long delayTime, @NonN * @return the ScheduledRunnable instance */ public Disposable scheduleDirect(final Runnable run, long delayTime, TimeUnit unit) { - ScheduledDirectTask task = new ScheduledDirectTask(RxJavaPlugins.onSchedule(run)); + ScheduledDirectTask task = new ScheduledDirectTask(RxJavaPlugins.onSchedule(run), true); try { Future f; if (delayTime <= 0L) { @@ -104,7 +104,7 @@ public Disposable schedulePeriodicallyDirect(Runnable run, long initialDelay, lo return periodicWrapper; } - ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun); + ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun, true); try { Future f = executor.scheduleAtFixedRate(task, initialDelay, period, unit); task.setFuture(f); @@ -116,10 +116,8 @@ public Disposable schedulePeriodicallyDirect(Runnable run, long initialDelay, lo } /** - * Wraps the given runnable into a ScheduledRunnable and schedules it + * Wraps and returns the given runnable into a ScheduledRunnable and schedules it * on the underlying ScheduledExecutorService. - *

If the schedule has been rejected, the ScheduledRunnable.wasScheduled will return - * false. * @param run the runnable instance * @param delayTime the time to delay the execution * @param unit the time unit diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NonBlockingThread.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NonBlockingThread.java index f800f1ac4e8..ff6dd5c7063 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/NonBlockingThread.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/NonBlockingThread.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactory.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactory.java index 5bd0614b894..9b3a7968c3e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactory.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactory.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTask.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTask.java index ac30532e687..1862035dde4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTask.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTask.java @@ -1,22 +1,18 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; -import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -28,8 +24,8 @@ public final class ScheduledDirectPeriodicTask extends AbstractDirectTask implem private static final long serialVersionUID = 1811839108042568751L; - public ScheduledDirectPeriodicTask(Runnable runnable) { - super(runnable); + public ScheduledDirectPeriodicTask(Runnable runnable, boolean interruptOnCancel) { + super(runnable, interruptOnCancel); } @Override @@ -39,10 +35,11 @@ public void run() { runnable.run(); runner = null; } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); + // Exceptions.throwIfFatal(ex); nowhere to go + dispose(); runner = null; - lazySet(FINISHED); RxJavaPlugins.onError(ex); + throw ex; } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectTask.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectTask.java index d48ccf8ab61..6ca89929710 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectTask.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectTask.java @@ -1,23 +1,22 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; import java.util.concurrent.Callable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + /** * A Callable to be submitted to an ExecutorService that runs a Runnable * action and manages completion/cancellation. @@ -27,18 +26,24 @@ public final class ScheduledDirectTask extends AbstractDirectTask implements Cal private static final long serialVersionUID = 1811839108042568751L; - public ScheduledDirectTask(Runnable runnable) { - super(runnable); + public ScheduledDirectTask(Runnable runnable, boolean interruptOnCancel) { + super(runnable, interruptOnCancel); } @Override public Void call() { runner = Thread.currentThread(); try { - runnable.run(); - } finally { - lazySet(FINISHED); - runner = null; + try { + runnable.run(); + } finally { + lazySet(FINISHED); + runner = null; + } + } catch (Throwable ex) { + // Exceptions.throwIfFatal(e); nowhere to go + RxJavaPlugins.onError(ex); + throw ex; } return null; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnable.java index 45072a2abdc..2a1baa641a2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,6 +24,7 @@ public final class ScheduledRunnable extends AtomicReferenceArray private static final long serialVersionUID = -6120223772001106981L; final Runnable actual; + final boolean interruptOnCancel; /** Indicates that the parent tracking this task has been notified about its completion. */ static final Object PARENT_DISPOSED = new Object(); @@ -41,12 +42,26 @@ public final class ScheduledRunnable extends AtomicReferenceArray /** * Creates a ScheduledRunnable by wrapping the given action and setting * up the optional parent. + * The underlying future will be interrupted if the task is disposed asynchronously. * @param actual the runnable to wrap, not-null (not verified) * @param parent the parent tracking container or null if none */ public ScheduledRunnable(Runnable actual, DisposableContainer parent) { + this(actual, parent, true); + } + + /** + * Creates a ScheduledRunnable by wrapping the given action and setting + * up the optional parent. + * @param actual the runnable to wrap, not-null (not verified) + * @param parent the parent tracking container or null if none + * @param interruptOnCancel if true, the underlying future will be interrupted when disposing + * this task from a different thread than it is running on. + */ + public ScheduledRunnable(Runnable actual, DisposableContainer parent, boolean interruptOnCancel) { super(3); this.actual = actual; + this.interruptOnCancel = interruptOnCancel; this.lazySet(0, parent); } @@ -66,9 +81,9 @@ public void run() { } catch (Throwable e) { // Exceptions.throwIfFatal(e); nowhere to go RxJavaPlugins.onError(e); + throw e; } } finally { - lazySet(THREAD_INDEX, null); Object o = get(PARENT_INDEX); if (o != PARENT_DISPOSED && compareAndSet(PARENT_INDEX, o, DONE) && o != null) { ((DisposableContainer)o).delete(this); @@ -80,6 +95,7 @@ public void run() { break; } } + lazySet(THREAD_INDEX, null); } } @@ -94,7 +110,7 @@ public void setFuture(Future f) { return; } if (o == ASYNC_DISPOSED) { - f.cancel(true); + f.cancel(interruptOnCancel); return; } if (compareAndSet(FUTURE_INDEX, o, f)) { @@ -113,7 +129,7 @@ public void dispose() { boolean async = get(THREAD_INDEX) != Thread.currentThread(); if (compareAndSet(FUTURE_INDEX, o, async ? ASYNC_DISPOSED : SYNC_DISPOSED)) { if (o != null) { - ((Future)o).cancel(async); + ((Future)o).cancel(async && interruptOnCancel); } break; } @@ -136,4 +152,26 @@ public boolean isDisposed() { Object o = get(PARENT_INDEX); return o == PARENT_DISPOSED || o == DONE; } + + @Override + public String toString() { + String state; + Object o = get(FUTURE_INDEX); + if (o == DONE) { + state = "Finished"; + } else if (o == SYNC_DISPOSED) { + state = "Disposed(Sync)"; + } else if (o == ASYNC_DISPOSED) { + state = "Disposed(Async)"; + } else { + o = get(THREAD_INDEX); + if (o == null) { + state = "Waiting"; + } else { + state = "Running on " + o; + } + } + + return getClass().getSimpleName() + "[" + state + "]"; + } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupport.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupport.java index d42fa32cfb7..b1e186adc91 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupport.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupport.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactory.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactory.java index 333d4ded9e1..44a824a168d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactory.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactory.java @@ -1,24 +1,19 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; -import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.exceptions.Exceptions; import io.reactivex.rxjava3.functions.Function; @@ -34,86 +29,11 @@ private SchedulerPoolFactory() { static final String PURGE_ENABLED_KEY = "rx3.purge-enabled"; - /** - * Indicates the periodic purging of the ScheduledExecutorService is enabled. - */ public static final boolean PURGE_ENABLED; - static final String PURGE_PERIOD_SECONDS_KEY = "rx3.purge-period-seconds"; - - /** - * Indicates the purge period of the ScheduledExecutorServices created by create(). - */ - public static final int PURGE_PERIOD_SECONDS; - - static final AtomicReference PURGE_THREAD = - new AtomicReference<>(); - - // Upcast to the Map interface here to avoid 8.x compatibility issues. - // See http://stackoverflow.com/a/32955708/61158 - static final Map POOLS = - new ConcurrentHashMap<>(); - - /** - * Starts the purge thread if not already started. - */ - public static void start() { - tryStart(PURGE_ENABLED); - } - - static void tryStart(boolean purgeEnabled) { - if (purgeEnabled) { - for (;;) { - ScheduledExecutorService curr = PURGE_THREAD.get(); - if (curr != null) { - return; - } - ScheduledExecutorService next = Executors.newScheduledThreadPool(1, new RxThreadFactory("RxSchedulerPurge")); - if (PURGE_THREAD.compareAndSet(curr, next)) { - - next.scheduleAtFixedRate(new ScheduledTask(), PURGE_PERIOD_SECONDS, PURGE_PERIOD_SECONDS, TimeUnit.SECONDS); - - return; - } else { - next.shutdownNow(); - } - } - } - } - - /** - * Stops the purge thread. - */ - public static void shutdown() { - ScheduledExecutorService exec = PURGE_THREAD.getAndSet(null); - if (exec != null) { - exec.shutdownNow(); - } - POOLS.clear(); - } - static { SystemPropertyAccessor propertyAccessor = new SystemPropertyAccessor(); PURGE_ENABLED = getBooleanProperty(true, PURGE_ENABLED_KEY, true, true, propertyAccessor); - PURGE_PERIOD_SECONDS = getIntProperty(PURGE_ENABLED, PURGE_PERIOD_SECONDS_KEY, 1, 1, propertyAccessor); - - start(); - } - - static int getIntProperty(boolean enabled, String key, int defaultNotFound, int defaultNotEnabled, Function propertyAccessor) { - if (enabled) { - try { - String value = propertyAccessor.apply(key); - if (value == null) { - return defaultNotFound; - } - return Integer.parseInt(value); - } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); - return defaultNotFound; - } - } - return defaultNotEnabled; } static boolean getBooleanProperty(boolean enabled, String key, boolean defaultNotFound, boolean defaultNotEnabled, Function propertyAccessor) { @@ -145,28 +65,8 @@ public String apply(String t) { * @return the ScheduledExecutorService */ public static ScheduledExecutorService create(ThreadFactory factory) { - final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory); - tryPutIntoPool(PURGE_ENABLED, exec); + final ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1, factory); + exec.setRemoveOnCancelPolicy(PURGE_ENABLED); return exec; } - - static void tryPutIntoPool(boolean purgeEnabled, ScheduledExecutorService exec) { - if (purgeEnabled && exec instanceof ScheduledThreadPoolExecutor) { - ScheduledThreadPoolExecutor e = (ScheduledThreadPoolExecutor) exec; - POOLS.put(e, exec); - } - } - - static final class ScheduledTask implements Runnable { - @Override - public void run() { - for (ScheduledThreadPoolExecutor e : new ArrayList<>(POOLS.keySet())) { - if (e.isShutdown()) { - POOLS.remove(e); - } else { - e.purge(); - } - } - } - } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhen.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhen.java index ddff75388b9..814c971f1c6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhen.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhen.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.schedulers; import java.util.concurrent.TimeUnit; @@ -53,11 +51,13 @@ * thread pool: * *
+ * {@code
  * Scheduler limitScheduler = Schedulers.computation().when(workers -> {
  *  // use merge max concurrent to limit the number of concurrent
  *  // callbacks two at a time
  *  return Completable.merge(Observable.merge(workers), 2);
  * });
+ * }
  * 
*

* This is a slightly different way to limit the concurrency but it has some @@ -71,19 +71,22 @@ * to the second. * *

+ * {@code
  * Scheduler limitScheduler = Schedulers.computation().when(workers -> {
  *  // use merge max concurrent to limit the number of concurrent
  *  // Observables two at a time
  *  return Completable.merge(Observable.merge(workers, 2));
  * });
+ * }
  * 
* - * Slowing down the rate to no more than than 1 a second. This suffers from the + * Slowing down the rate to no more than 1 a second. This suffers from the * same problem as the one above I could find an {@link Observable} operator * that limits the rate without dropping the values (aka leaky bucket * algorithm). * *
+ * {@code
  * Scheduler slowScheduler = Schedulers.computation().when(workers -> {
  *  // use concatenate to make each worker happen one at a time.
  *  return Completable.concat(workers.map(actions -> {
@@ -91,6 +94,7 @@
  *      return Completable.merge(actions.delaySubscription(1, TimeUnit.SECONDS));
  *  }));
  * });
+ * }
  * 
*

History 2.0.1 - experimental * @since 2.1 @@ -187,21 +191,7 @@ public boolean isDisposed() { @Override public void dispose() { - Disposable oldState; - // no matter what the current state is the new state is going to be - Disposable newState = DISPOSED; - do { - oldState = get(); - if (oldState == DISPOSED) { - // the action has already been unsubscribed - return; - } - } while (!compareAndSet(oldState, newState)); - - if (oldState != SUBSCRIBED) { - // the action was scheduled. stop it. - oldState.dispose(); - } + getAndSet(DISPOSED).dispose(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SingleScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SingleScheduler.java index 13c7430f942..98d3b04626a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/SingleScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/SingleScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.schedulers; import java.util.concurrent.*; @@ -90,12 +91,9 @@ public void start() { @Override public void shutdown() { - ScheduledExecutorService current = executor.get(); + ScheduledExecutorService current = executor.getAndSet(SHUTDOWN); if (current != SHUTDOWN) { - current = executor.getAndSet(SHUTDOWN); - if (current != SHUTDOWN) { - current.shutdownNow(); - } + current.shutdownNow(); } } @@ -108,7 +106,7 @@ public Worker createWorker() { @NonNull @Override public Disposable scheduleDirect(@NonNull Runnable run, long delay, TimeUnit unit) { - ScheduledDirectTask task = new ScheduledDirectTask(RxJavaPlugins.onSchedule(run)); + ScheduledDirectTask task = new ScheduledDirectTask(RxJavaPlugins.onSchedule(run), true); try { Future f; if (delay <= 0L) { @@ -148,7 +146,7 @@ public Disposable schedulePeriodicallyDirect(@NonNull Runnable run, long initial return periodicWrapper; } - ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun); + ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun, true); try { Future f = executor.get().scheduleAtFixedRate(task, initialDelay, period, unit); task.setFuture(f); diff --git a/src/main/java/io/reactivex/rxjava3/internal/schedulers/TrampolineScheduler.java b/src/main/java/io/reactivex/rxjava3/internal/schedulers/TrampolineScheduler.java index 5ddd8677837..04496482b06 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/schedulers/TrampolineScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/internal/schedulers/TrampolineScheduler.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -65,7 +62,7 @@ public Disposable scheduleDirect(@NonNull Runnable run, long delay, TimeUnit uni return EmptyDisposable.INSTANCE; } - static final class TrampolineWorker extends Scheduler.Worker implements Disposable { + static final class TrampolineWorker extends Scheduler.Worker { final PriorityBlockingQueue queue = new PriorityBlockingQueue<>(); private final AtomicInteger wip = new AtomicInteger(); diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriber.java index ae1e72c3f85..645a3171f2b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,8 +16,9 @@ import org.reactivestreams.Subscription; import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriber.java index b0944cacec3..162a9dbe552 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.core.FlowableSubscriber; import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingBaseSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingBaseSubscriber.java index cf93064c6a0..68fa0df3eb0 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingBaseSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingBaseSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.subscribers; import java.util.concurrent.CountDownLatch; diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingFirstSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingFirstSubscriber.java index 228023b3d9e..1226eca8451 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingFirstSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingFirstSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingLastSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingLastSubscriber.java index 18891937707..05be9d79fa3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingLastSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingLastSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriber.java index 9ddba51e3c8..4617833fc48 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriber.java index 7ea697a3aba..a55f4ae4fae 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -136,4 +136,4 @@ public void cancel() { public boolean hasCustomOnError() { return onError != Functions.ON_ERROR_MISSING; } -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriber.java index 5fca99286af..11123962f27 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/DisposableAutoReleaseSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/DisposableAutoReleaseSubscriber.java new file mode 100644 index 00000000000..3b9d2d99b3d --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/DisposableAutoReleaseSubscriber.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.subscribers; + +import java.util.concurrent.atomic.AtomicReference; + +import org.reactivestreams.Subscription; + +import io.reactivex.rxjava3.core.FlowableSubscriber; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps lambda callbacks and when the upstream terminates or this subscriber gets disposed, + * removes itself from a {@link io.reactivex.rxjava3.disposables.CompositeDisposable}. + *

History: 0.18.0 @ RxJavaExtensions + * @param the element type consumed + * @since 3.1.0 + */ +public final class DisposableAutoReleaseSubscriber +extends AtomicReference +implements FlowableSubscriber, Disposable, LambdaConsumerIntrospection { + + private static final long serialVersionUID = 8924480688481408726L; + + final AtomicReference composite; + + final Consumer onNext; + + final Consumer onError; + + final Action onComplete; + + public DisposableAutoReleaseSubscriber( + DisposableContainer composite, + Consumer onNext, + Consumer onError, + Action onComplete + ) { + this.onNext = onNext; + this.onError = onError; + this.onComplete = onComplete; + this.composite = new AtomicReference<>(composite); + } + + @Override + public void onNext(T t) { + if (get() != SubscriptionHelper.CANCELLED) { + try { + onNext.accept(t); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + get().cancel(); + onError(e); + } + } + } + + @Override + public void onError(Throwable t) { + if (get() != SubscriptionHelper.CANCELLED) { + lazySet(SubscriptionHelper.CANCELLED); + try { + onError.accept(t); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(new CompositeException(t, e)); + } + } else { + RxJavaPlugins.onError(t); + } + removeSelf(); + } + + @Override + public void onComplete() { + if (get() != SubscriptionHelper.CANCELLED) { + lazySet(SubscriptionHelper.CANCELLED); + try { + onComplete.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(e); + } + } + removeSelf(); + } + + @Override + public void dispose() { + SubscriptionHelper.cancel(this); + removeSelf(); + } + + void removeSelf() { + DisposableContainer c = composite.getAndSet(null); + if (c != null) { + c.delete(this); + } + } + + @Override + public boolean isDisposed() { + return SubscriptionHelper.CANCELLED == get(); + } + + @Override + public void onSubscribe(Subscription s) { + if (SubscriptionHelper.setOnce(this, s)) { + s.request(Long.MAX_VALUE); + } + } + + @Override + public boolean hasCustomOnError() { + return onError != Functions.ON_ERROR_MISSING; + } + +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/ForEachWhileSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/ForEachWhileSubscriber.java index 34d00eef9d7..cb5ff01a13c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/ForEachWhileSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/ForEachWhileSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriber.java index 59edd4f80d4..145195e2cc4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,9 +19,9 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; -import io.reactivex.rxjava3.annotations.NonNull; import org.reactivestreams.Subscription; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.FlowableSubscriber; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BlockingHelper; @@ -128,18 +128,16 @@ public void onNext(T t) { @Override public void onError(Throwable t) { - for (;;) { + if (error == null) { Subscription a = upstream.get(); - if (a == this || a == SubscriptionHelper.CANCELLED) { - RxJavaPlugins.onError(t); - return; - } - error = t; - if (upstream.compareAndSet(a, this)) { + if (a != this && a != SubscriptionHelper.CANCELLED + && upstream.compareAndSet(a, this)) { + error = t; countDown(); return; } } + RxJavaPlugins.onError(t); } @Override @@ -148,15 +146,12 @@ public void onComplete() { onError(new NoSuchElementException("The source is empty")); return; } - for (;;) { - Subscription a = upstream.get(); - if (a == this || a == SubscriptionHelper.CANCELLED) { - return; - } - if (upstream.compareAndSet(a, this)) { - countDown(); - return; - } + Subscription a = upstream.get(); + if (a == this || a == SubscriptionHelper.CANCELLED) { + return; + } + if (upstream.compareAndSet(a, this)) { + countDown(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriber.java index c53138e3d72..f946ec7deb5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,9 +18,10 @@ import org.reactivestreams.Subscription; import io.reactivex.rxjava3.core.FlowableSubscriber; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.QueueDrainHelper; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; /** * Subscriber that can fuse with the upstream and calls a support interface @@ -115,18 +116,6 @@ public void request(long n) { } } - public void requestOne() { - if (fusionMode != QueueSubscription.SYNC) { - long p = produced + 1; - if (p == limit) { - produced = 0L; - get().request(p); - } else { - produced = p; - } - } - } - @Override public void cancel() { SubscriptionHelper.cancel(this); diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberSupport.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberSupport.java index e7deb5c4115..3844c5b981a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberSupport.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberSupport.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriber.java index daa76fdfbf5..f137237e975 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriber.java index c66505a0711..8fb7f552953 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,9 +20,9 @@ import io.reactivex.rxjava3.core.FlowableSubscriber; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.MissingBackpressureException; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.SimplePlainQueue; /** * Abstract base class for subscribers that hold another subscriber, a queue @@ -84,7 +84,7 @@ protected final void fastPathEmitMax(U value, boolean delayError, Disposable dis } } else { dispose.dispose(); - s.onError(new MissingBackpressureException("Could not emit buffer due to lack of requests")); + s.onError(MissingBackpressureException.createDefault()); return; } } else { @@ -118,7 +118,7 @@ protected final void fastPathOrderedEmitMax(U value, boolean delayError, Disposa } else { cancelled = true; dispose.dispose(); - s.onError(new MissingBackpressureException("Could not emit buffer due to lack of requests")); + s.onError(MissingBackpressureException.createDefault()); return; } } else { diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriber.java index ab9f9ba7999..ceec9f6b90a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriber.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriber.java index f3511260444..265acd60a57 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapper.java b/src/main/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapper.java index 4c9b6b49306..df85e953247 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscription.java index 628891a7e6f..ce4b2b5ac82 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscription.java index 62973e7440c..d33d05c8d1b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicIntQueueSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicIntQueueSubscription.java index 862fb51b4b7..46b420354b8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicIntQueueSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicIntQueueSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,14 +15,15 @@ import java.util.concurrent.atomic.AtomicInteger; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * Base class extending AtomicInteger (wip or request accounting) and QueueSubscription (fusion). * * @param the value type */ -public abstract class BasicIntQueueSubscription extends AtomicInteger implements QueueSubscription { +public abstract class BasicIntQueueSubscription<@NonNull T> extends AtomicInteger implements QueueSubscription { private static final long serialVersionUID = -6671519529404341862L; diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicQueueSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicQueueSubscription.java index 54d33f26cb8..684bdf4e80f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicQueueSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BasicQueueSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.AtomicLong; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * Base class extending AtomicLong (wip or request accounting) and QueueSubscription (fusion). diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BooleanSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BooleanSubscription.java index 117b09b60ce..2d7f01ef057 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BooleanSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/BooleanSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.subscriptions; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscription.java index b50b4e13f9c..544fac8b58a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,7 @@ import org.reactivestreams.Subscriber; -import io.reactivex.rxjava3.annotations.Nullable; +import io.reactivex.rxjava3.annotations.*; /** * A subscription that signals a single value eventually. @@ -33,7 +33,7 @@ * Where exclusively set means any other bits are 0 when that bit is set. * @param the value type */ -public class DeferredScalarSubscription extends BasicIntQueueSubscription { +public class DeferredScalarSubscription<@NonNull T> extends BasicIntQueueSubscription { private static final long serialVersionUID = -2151279923272604993L; @@ -115,7 +115,7 @@ public final void complete(T v) { lazySet(FUSED_READY); Subscriber a = downstream; - a.onNext(v); + a.onNext(null); if (get() != CANCELLED) { a.onComplete(); } diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/EmptySubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/EmptySubscription.java index 2da5f529a12..6b2c033d5ec 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/EmptySubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/EmptySubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,7 +16,7 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * An empty subscription that does nothing other than validates the request amount. diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscription.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscription.java index e854c11f921..ef1e35e7530 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,7 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * A Subscription that holds a constant value and emits it only when requested. diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiter.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiter.java index 44c5fe5845f..7d964224ebb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiter.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -12,18 +12,6 @@ */ package io.reactivex.rxjava3.internal.subscriptions; -/** - * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the specific language governing permissions and limitations under the License. - */ import java.util.Objects; import java.util.concurrent.atomic.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelper.java b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelper.java index 8cfc3f5a7c7..922ac9c3c9c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/AppendOnlyLinkedArrayList.java b/src/main/java/io/reactivex/rxjava3/internal/util/AppendOnlyLinkedArrayList.java index a2a78e7b7e7..3c17b880096 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/AppendOnlyLinkedArrayList.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/AppendOnlyLinkedArrayList.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ArrayListSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/util/ArrayListSupplier.java index 7338c990404..6379cfcab84 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ArrayListSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ArrayListSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/AtomicThrowable.java b/src/main/java/io/reactivex/rxjava3/internal/util/AtomicThrowable.java index 222008e216a..3ef92cb77a3 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/AtomicThrowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/AtomicThrowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/BackpressureHelper.java b/src/main/java/io/reactivex/rxjava3/internal/util/BackpressureHelper.java index 4ccfe678454..73b15382c89 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/BackpressureHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/BackpressureHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.util.concurrent.atomic.AtomicLong; diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/BlockingHelper.java b/src/main/java/io/reactivex/rxjava3/internal/util/BlockingHelper.java index 57d9f863b31..84acadee6fb 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/BlockingHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/BlockingHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/BlockingIgnoringReceiver.java b/src/main/java/io/reactivex/rxjava3/internal/util/BlockingIgnoringReceiver.java index f0d90e4708a..8d4c1fb76e4 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/BlockingIgnoringReceiver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/BlockingIgnoringReceiver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ConnectConsumer.java b/src/main/java/io/reactivex/rxjava3/internal/util/ConnectConsumer.java index 63fd12dc991..5d5246719db 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ConnectConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ConnectConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/EmptyComponent.java b/src/main/java/io/reactivex/rxjava3/internal/util/EmptyComponent.java index 1ffc9c51d4c..47390f57cb6 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/EmptyComponent.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/EmptyComponent.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/EndConsumerHelper.java b/src/main/java/io/reactivex/rxjava3/internal/util/EndConsumerHelper.java index 01b95a0a113..0e72353800f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/EndConsumerHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/EndConsumerHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ErrorMode.java b/src/main/java/io/reactivex/rxjava3/internal/util/ErrorMode.java index e3ff3d5fdb7..02389f0b7a8 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ErrorMode.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ErrorMode.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ExceptionHelper.java b/src/main/java/io/reactivex/rxjava3/internal/util/ExceptionHelper.java index 8b9d62317a4..1ddbb8aca11 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ExceptionHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ExceptionHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/HalfSerializer.java b/src/main/java/io/reactivex/rxjava3/internal/util/HalfSerializer.java index 54f787f55ab..e1bf5596e2c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/HalfSerializer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/HalfSerializer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.util.concurrent.atomic.AtomicInteger; @@ -37,15 +38,18 @@ private HalfSerializer() { * @param value the value to emit * @param wip the serialization work-in-progress counter/indicator * @param errors the holder of Throwables + * @return true if the operation succeeded, false if there sequence completed */ - public static void onNext(Subscriber subscriber, T value, + public static boolean onNext(Subscriber subscriber, T value, AtomicInteger wip, AtomicThrowable errors) { if (wip.get() == 0 && wip.compareAndSet(0, 1)) { subscriber.onNext(value); - if (wip.decrementAndGet() != 0) { - errors.tryTerminateConsumer(subscriber); + if (wip.decrementAndGet() == 0) { + return true; } + errors.tryTerminateConsumer(subscriber); } + return false; } /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/HashMapSupplier.java b/src/main/java/io/reactivex/rxjava3/internal/util/HashMapSupplier.java index 46236ff2938..15c2884266e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/HashMapSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/HashMapSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/LinkedArrayList.java b/src/main/java/io/reactivex/rxjava3/internal/util/LinkedArrayList.java index 08d675a4afb..92ff9d30a6e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/LinkedArrayList.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/LinkedArrayList.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.util.*; diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ListAddBiConsumer.java b/src/main/java/io/reactivex/rxjava3/internal/util/ListAddBiConsumer.java index cd6c8e97509..fb643fcff30 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ListAddBiConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ListAddBiConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/MergerBiFunction.java b/src/main/java/io/reactivex/rxjava3/internal/util/MergerBiFunction.java index 64d9faff715..a736309019e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/MergerBiFunction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/MergerBiFunction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/NotificationLite.java b/src/main/java/io/reactivex/rxjava3/internal/util/NotificationLite.java index c37aa71da24..c27486d9cfd 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/NotificationLite.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/NotificationLite.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.io.Serializable; diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/ObservableQueueDrain.java b/src/main/java/io/reactivex/rxjava3/internal/util/ObservableQueueDrain.java index c0187e9cc22..6d69b375d4b 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/ObservableQueueDrain.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/ObservableQueueDrain.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/OpenHashSet.java b/src/main/java/io/reactivex/rxjava3/internal/util/OpenHashSet.java index c5bf3bb6766..9967ca831d9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/OpenHashSet.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/OpenHashSet.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/Pow2.java b/src/main/java/io/reactivex/rxjava3/internal/util/Pow2.java index dd6df01d9e2..fd30ee04fb9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/Pow2.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/Pow2.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,6 +15,7 @@ * Original License: https://github.com/JCTools/JCTools/blob/master/LICENSE * Original location: https://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/util/Pow2.java */ + package io.reactivex.rxjava3.internal.util; public final class Pow2 { diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrain.java b/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrain.java index 4a84e5e6ed5..481cbe0012e 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrain.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrain.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrainHelper.java b/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrainHelper.java index 9808e2fe0d6..fa0c500892f 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrainHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/QueueDrainHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.util.Queue; @@ -21,8 +22,7 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.BooleanSupplier; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.*; +import io.reactivex.rxjava3.operators.*; /** * Utility class to help with the queue-drain serialization idiom. @@ -78,7 +78,7 @@ public static void drainMaxLoop(SimplePlainQueue q, Subscriber the value type * @param n the current request amount * @param actual the target Subscriber to send events to * @param queue the queue to drain if in the post-complete state diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/SorterFunction.java b/src/main/java/io/reactivex/rxjava3/internal/util/SorterFunction.java index a62efd154f7..b74f1bccf65 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/SorterFunction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/SorterFunction.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/SuppressAnimalSniffer.java b/src/main/java/io/reactivex/rxjava3/internal/util/SuppressAnimalSniffer.java index e57d8830369..b55fb0673b9 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/SuppressAnimalSniffer.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/SuppressAnimalSniffer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayList.java b/src/main/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayList.java index 33e1e18a562..798a05a6dca 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayList.java +++ b/src/main/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayList.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observables/ConnectableObservable.java b/src/main/java/io/reactivex/rxjava3/observables/ConnectableObservable.java index 2221ac62b0b..231d0357fea 100644 --- a/src/main/java/io/reactivex/rxjava3/observables/ConnectableObservable.java +++ b/src/main/java/io/reactivex/rxjava3/observables/ConnectableObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -32,22 +32,21 @@ * can wait for all intended {@link Observer}s to {@link Observable#subscribe} to the {@code Observable} * before the {@code Observable} begins emitting items. *

- * + * *

* When the upstream terminates, the {@code ConnectableObservable} remains in this terminated state and, - * depending on the actual underlying implementation, relays cached events to late {@link Observer}s. + * depending on the actual underlying implementation, relays cached events to late {@code Observer}s. * In order to reuse and restart this {@code ConnectableObservable}, the {@link #reset()} method has to be called. - * When called, this {@code ConnectableObservable} will appear as fresh, unconnected source to new {@link Observer}s. - * Disposing the connection will reset the {@code ConnectableFlowable} to its fresh state and there is no need to call - * {@code reset()} in this case. + * When called, this {@code ConnectableObservable} will appear as fresh, unconnected source to new {@code Observer}s. + * Disposing the connection will reset the {@code ConnectableObservable} to its fresh state and there is no need to call + * {@link #reset()} in this case. *

* Note that although {@link #connect()} and {@link #reset()} are safe to call from multiple threads, it is recommended * a dedicated thread or business logic manages the connection or resetting of a {@code ConnectableObservable} so that * there is no unwanted signal loss due to early {@code connect()} or {@code reset()} calls while {@code Observer}s are * still being subscribed to to this {@code ConnectableObservable} to receive signals from the get go. * - * @see RxJava Wiki: - * Connectable Observable Operators + * @see RxJava Wiki: Connectable Observable Operators * @param * the type of items emitted by the {@code ConnectableObservable} */ @@ -71,7 +70,7 @@ public abstract class ConnectableObservable extends Observable { public abstract void connect(@NonNull Consumer connection); /** - * Resets this ConnectableObservable into its fresh state if it has terminated + * Resets this {@code ConnectableObservable} into its fresh state if it has terminated * or has been disposed. *

* Calling this method on a fresh or active {@code ConnectableObservable} has no effect. @@ -94,7 +93,7 @@ public abstract class ConnectableObservable extends Observable { *

The behavior is determined by the implementor of this abstract class.
* * - * @return the subscription representing the connection + * @return the {@link Disposable} representing the connection * @see ReactiveX documentation: Connect */ @NonNull @@ -106,13 +105,13 @@ public final Disposable connect() { } /** - * Returns an {@code Observable} that stays connected to this {@code ConnectableObservable} as long as there + * Returns an {@link Observable} that stays connected to this {@code ConnectableObservable} as long as there * is at least one subscription to this {@code ConnectableObservable}. *
*
Scheduler:
*
This {@code refCount} overload does not operate on any particular {@link Scheduler}.
*
- * @return an {@link Observable} + * @return a new {@code Observable} instance * @see ReactiveX documentation: RefCount * @see #refCount(int) * @see #refCount(long, TimeUnit) @@ -127,35 +126,36 @@ public Observable refCount() { /** * Connects to the upstream {@code ConnectableObservable} if the number of subscribed - * observers reaches the specified count and disconnect if all subscribers have unsubscribed. + * observers reaches the specified count and disconnect if all {@link Observer}s have unsubscribed. *
*
Scheduler:
*
This {@code refCount} overload does not operate on any particular {@link Scheduler}.
*
*

History: 2.1.14 - experimental - * @param subscriberCount the number of subscribers required to connect to the upstream - * @return the new Observable instance + * @param observerCount the number of {@code Observer}s required to connect to the upstream + * @return the new {@link Observable} instance + * @throws IllegalArgumentException if {@code observerCount} is non-positive * @since 2.2 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable refCount(int subscriberCount) { - return refCount(subscriberCount, 0, TimeUnit.NANOSECONDS, Schedulers.trampoline()); + public final Observable refCount(int observerCount) { + return refCount(observerCount, 0, TimeUnit.NANOSECONDS, Schedulers.trampoline()); } /** * Connects to the upstream {@code ConnectableObservable} if the number of subscribed * observers reaches 1 and disconnect after the specified - * timeout if all subscribers have unsubscribed. + * timeout if all {@link Observer}s have unsubscribed. *

*
Scheduler:
*
This {@code refCount} overload operates on the {@code computation} {@link Scheduler}.
*
*

History: 2.1.14 - experimental - * @param timeout the time to wait before disconnecting after all subscribers unsubscribed + * @param timeout the time to wait before disconnecting after all {@code Observer}s unsubscribed * @param unit the time unit of the timeout - * @return the new Observable instance + * @return the new {@link Observable} instance * @throws NullPointerException if {@code unit} is {@code null} * @see #refCount(long, TimeUnit, Scheduler) * @since 2.2 @@ -170,16 +170,16 @@ public final Observable refCount(long timeout, @NonNull TimeUnit unit) { /** * Connects to the upstream {@code ConnectableObservable} if the number of subscribed * observers reaches 1 and disconnect after the specified - * timeout if all subscribers have unsubscribed. + * timeout if all {@link Observer}s have unsubscribed. *

*
Scheduler:
*
This {@code refCount} overload operates on the specified {@link Scheduler}.
*
*

History: 2.1.14 - experimental - * @param timeout the time to wait before disconnecting after all subscribers unsubscribed + * @param timeout the time to wait before disconnecting after all {@code Observer}s unsubscribed * @param unit the time unit of the timeout * @param scheduler the target scheduler to wait on before disconnecting - * @return the new Observable instance + * @return the new {@link Observable} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} * @since 2.2 */ @@ -193,66 +193,67 @@ public final Observable refCount(long timeout, @NonNull TimeUnit unit, @NonNu /** * Connects to the upstream {@code ConnectableObservable} if the number of subscribed * observers reaches the specified count and disconnect after the specified - * timeout if all subscribers have unsubscribed. + * timeout if all {@link Observer}s have unsubscribed. *

*
Scheduler:
*
This {@code refCount} overload operates on the {@code computation} {@link Scheduler}.
*
*

History: 2.1.14 - experimental - * @param subscriberCount the number of subscribers required to connect to the upstream - * @param timeout the time to wait before disconnecting after all subscribers unsubscribed + * @param observerCount the number of {@code Observer}s required to connect to the upstream + * @param timeout the time to wait before disconnecting after all {@code Observer}s unsubscribed * @param unit the time unit of the timeout - * @return the new Observable instance + * @return the new {@link Observable} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @throws IllegalArgumentException if {@code observerCount} is non-positive * @see #refCount(int, long, TimeUnit, Scheduler) * @since 2.2 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable refCount(int subscriberCount, long timeout, @NonNull TimeUnit unit) { - return refCount(subscriberCount, timeout, unit, Schedulers.computation()); + public final Observable refCount(int observerCount, long timeout, @NonNull TimeUnit unit) { + return refCount(observerCount, timeout, unit, Schedulers.computation()); } /** * Connects to the upstream {@code ConnectableObservable} if the number of subscribed * observers reaches the specified count and disconnect after the specified - * timeout if all subscribers have unsubscribed. + * timeout if all {@link Observer}s have unsubscribed. *

*
Scheduler:
*
This {@code refCount} overload operates on the specified {@link Scheduler}.
*
*

History: 2.1.14 - experimental - * @param subscriberCount the number of subscribers required to connect to the upstream - * @param timeout the time to wait before disconnecting after all subscribers unsubscribed + * @param observerCount the number of {@code Observer}s required to connect to the upstream + * @param timeout the time to wait before disconnecting after all {@code Observer}s unsubscribed * @param unit the time unit of the timeout * @param scheduler the target scheduler to wait on before disconnecting - * @return the new Observable instance + * @return the new {@link Observable} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} - * @throws IllegalArgumentException if {@code subscriberCount} is non-positive + * @throws IllegalArgumentException if {@code observerCount} is non-positive * @since 2.2 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable refCount(int subscriberCount, long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - ObjectHelper.verifyPositive(subscriberCount, "subscriberCount"); + public final Observable refCount(int observerCount, long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + ObjectHelper.verifyPositive(observerCount, "observerCount"); Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableRefCount<>(this, subscriberCount, timeout, unit, scheduler)); + return RxJavaPlugins.onAssembly(new ObservableRefCount<>(this, observerCount, timeout, unit, scheduler)); } /** - * Returns an Observable that automatically connects (at most once) to this ConnectableObservable - * when the first Observer subscribes. + * Returns an {@link Observable} that automatically connects (at most once) to this {@code ConnectableObservable} + * when the first {@link Observer} subscribes. *

* *

* The connection happens after the first subscription and happens at most once - * during the lifetime of the returned Observable. If this ConnectableObservable - * terminates, the connection is never renewed, no matter how Observers come + * during the lifetime of the returned {@code Observable}. If this {@code ConnectableObservable} + * terminates, the connection is never renewed, no matter how {@code Observer}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active - * connection when all {@code Observer}s have disposed their {@code Disposable}s. + * connection when all {@code Observer}s have disposed their {@link Disposable}s. *

* This overload does not allow disconnecting the connection established via * {@link #connect(Consumer)}. Use the {@link #autoConnect(int, Consumer)} overload @@ -262,8 +263,8 @@ public final Observable refCount(int subscriberCount, long timeout, @NonNull *

{@code autoConnect} overload does not operate on any particular {@link Scheduler}.
* * - * @return an Observable that automatically connects to this ConnectableObservable - * when the first Observer subscribes + * @return a new {@code Observable} instance that automatically connects to this {@code ConnectableObservable} + * when the first {@code Observer} subscribes */ @NonNull @CheckReturnValue @@ -273,16 +274,16 @@ public Observable autoConnect() { } /** - * Returns an Observable that automatically connects (at most once) to this ConnectableObservable - * when the specified number of Observers subscribe to it. + * Returns an {@link Observable} that automatically connects (at most once) to this {@code ConnectableObservable} + * when the specified number of {@link Observer}s subscribe to it. *

* *

* The connection happens after the given number of subscriptions and happens at most once - * during the lifetime of the returned Observable. If this ConnectableObservable - * terminates, the connection is never renewed, no matter how Observers come + * during the lifetime of the returned {@code Observable}. If this {@code ConnectableObservable} + * terminates, the connection is never renewed, no matter how {@code Observer}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active - * connection when all {@code Observer}s have disposed their {@code Disposable}s. + * connection when all {@code Observer}s have disposed their {@link Disposable}s. *

* This overload does not allow disconnecting the connection established via * {@link #connect(Consumer)}. Use the {@link #autoConnect(int, Consumer)} overload @@ -292,29 +293,29 @@ public Observable autoConnect() { *

{@code autoConnect} overload does not operate on any particular {@link Scheduler}.
* * - * @param numberOfSubscribers the number of subscribers to await before calling connect - * on the ConnectableObservable. A non-positive value indicates + * @param numberOfObservers the number of subscribers to await before calling connect + * on the {@code ConnectableObservable}. A non-positive value indicates * an immediate connection. - * @return an Observable that automatically connects to this ConnectableObservable - * when the specified number of Subscribers subscribe to it + * @return a new {@code Observable} instance that automatically connects to this {@code ConnectableObservable} + * when the specified number of {@code Observer}s subscribe to it */ @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) - public Observable autoConnect(int numberOfSubscribers) { - return autoConnect(numberOfSubscribers, Functions.emptyConsumer()); + public Observable autoConnect(int numberOfObservers) { + return autoConnect(numberOfObservers, Functions.emptyConsumer()); } /** - * Returns an Observable that automatically connects (at most once) to this ConnectableObservable - * when the specified number of Subscribers subscribe to it and calls the - * specified callback with the Subscription associated with the established connection. + * Returns an {@link Observable} that automatically connects (at most once) to this {@code ConnectableObservable} + * when the specified number of {@link Observer}s subscribe to it and calls the + * specified callback with the {@link Disposable} associated with the established connection. *

* *

* The connection happens after the given number of subscriptions and happens at most once - * during the lifetime of the returned Observable. If this ConnectableObservable - * terminates, the connection is never renewed, no matter how Observers come + * during the lifetime of the returned {@code Observable}. If this {@code ConnectableObservable} + * terminates, the connection is never renewed, no matter how {@code Observer}s come * and go. Use {@link #refCount()} to renew a connection or dispose an active * connection when all {@code Observer}s have disposed their {@code Disposable}s. *

@@ -322,25 +323,25 @@ public Observable autoConnect(int numberOfSubscribers) { *
{@code autoConnect} overload does not operate on any particular {@link Scheduler}.
*
* - * @param numberOfSubscribers the number of subscribers to await before calling connect - * on the ConnectableObservable. A non-positive value indicates + * @param numberOfObservers the number of subscribers to await before calling connect + * on the {@code ConnectableObservable}. A non-positive value indicates * an immediate connection. - * @param connection the callback Consumer that will receive the Subscription representing the + * @param connection the callback {@link Consumer} that will receive the {@code Disposable} representing the * established connection - * @return an Observable that automatically connects to this ConnectableObservable - * when the specified number of Subscribers subscribe to it and calls the - * specified callback with the Subscription associated with the established connection + * @return a new {@code Observable} instance that automatically connects to this {@code ConnectableObservable} + * when the specified number of {@code Observer}s subscribe to it and calls the + * specified callback with the {@code Disposable} associated with the established connection * @throws NullPointerException if {@code connection} is {@code null} */ @NonNull @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) - public Observable autoConnect(int numberOfSubscribers, @NonNull Consumer connection) { + public Observable autoConnect(int numberOfObservers, @NonNull Consumer connection) { Objects.requireNonNull(connection, "connection is null"); - if (numberOfSubscribers <= 0) { + if (numberOfObservers <= 0) { this.connect(connection); return RxJavaPlugins.onAssembly(this); } - return RxJavaPlugins.onAssembly(new ObservableAutoConnect<>(this, numberOfSubscribers, connection)); + return RxJavaPlugins.onAssembly(new ObservableAutoConnect<>(this, numberOfObservers, connection)); } } diff --git a/src/main/java/io/reactivex/rxjava3/observables/GroupedObservable.java b/src/main/java/io/reactivex/rxjava3/observables/GroupedObservable.java index 489ee1d716c..baa35ce48dc 100644 --- a/src/main/java/io/reactivex/rxjava3/observables/GroupedObservable.java +++ b/src/main/java/io/reactivex/rxjava3/observables/GroupedObservable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observables; import io.reactivex.rxjava3.annotations.Nullable; diff --git a/src/main/java/io/reactivex/rxjava3/observables/package-info.java b/src/main/java/io/reactivex/rxjava3/observables/package-info.java index 7fb2fc14544..93c6ad0c406 100644 --- a/src/main/java/io/reactivex/rxjava3/observables/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/observables/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/observers/BaseTestConsumer.java b/src/main/java/io/reactivex/rxjava3/observers/BaseTestConsumer.java index 458325c280f..6b3a72fadbc 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/BaseTestConsumer.java +++ b/src/main/java/io/reactivex/rxjava3/observers/BaseTestConsumer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -54,6 +54,9 @@ public abstract class BaseTestConsumer> { */ protected boolean timeout; + /** + * Constructs a {@code BaseTestConsumer} with {@code CountDownLatch} set to 1. + */ public BaseTestConsumer() { this.values = new VolatileSizeArrayList<>(); this.errors = new VolatileSizeArrayList<>(); @@ -228,7 +231,7 @@ public final U assertNoErrors() { */ @NonNull public final U assertError(@NonNull Throwable error) { - return assertError(Functions.equalsWith(error)); + return assertError(Functions.equalsWith(error), true); } /** @@ -240,7 +243,7 @@ public final U assertError(@NonNull Throwable error) { @SuppressWarnings({ "unchecked", "rawtypes" }) @NonNull public final U assertError(@NonNull Class errorClass) { - return (U)assertError((Predicate)Functions.isInstanceOf(errorClass)); + return (U)assertError((Predicate)Functions.isInstanceOf(errorClass), true); } /** @@ -251,9 +254,14 @@ public final U assertError(@NonNull Class errorClass) { * and should return {@code true} for expected errors. * @return this */ - @SuppressWarnings("unchecked") @NonNull public final U assertError(@NonNull Predicate errorPredicate) { + return assertError(errorPredicate, false); + } + + @SuppressWarnings("unchecked") + @NonNull + private U assertError(@NonNull Predicate errorPredicate, boolean exact) { int s = errors.size(); if (s == 0) { throw fail("No errors"); @@ -274,10 +282,16 @@ public final U assertError(@NonNull Predicate errorPredicate) { if (found) { if (s != 1) { - throw fail("Error present but other errors as well"); + if (exact) { + throw fail("Error present but other errors as well"); + } + throw fail("One error passed the predicate but other errors are present as well"); } } else { - throw fail("Error not present"); + if (exact) { + throw fail("Error not present"); + } + throw fail("No error(s) passed the predicate"); } return (U)this; } @@ -293,11 +307,11 @@ public final U assertError(@NonNull Predicate errorPredicate) { public final U assertValue(@NonNull T value) { int s = values.size(); if (s != 1) { - throw fail("expected: " + valueAndClass(value) + " but was: " + values); + throw fail("\nexpected: " + valueAndClass(value) + "\ngot: " + values); } T v = values.get(0); if (!Objects.equals(value, v)) { - throw fail("expected: " + valueAndClass(value) + " but was: " + valueAndClass(v)); + throw fail("\nexpected: " + valueAndClass(value) + "\ngot: " + valueAndClass(v)); } return (U)this; } @@ -316,7 +330,7 @@ public final U assertValue(@NonNull Predicate valuePredicate) { assertValueAt(0, valuePredicate); if (values.size() > 1) { - throw fail("Value present but other values as well"); + throw fail("The first value passed the predicate but this consumer received more than one value"); } return (U)this; @@ -339,13 +353,14 @@ public final U assertValueAt(int index, @NonNull T value) { throw fail("No values"); } - if (index >= s) { - throw fail("Invalid index: " + index); + if (index < 0 || index >= s) { + throw fail("Index " + index + " is out of range [0, " + s + ")"); } T v = values.get(index); if (!Objects.equals(value, v)) { - throw fail("expected: " + valueAndClass(value) + " but was: " + valueAndClass(v)); + throw fail("\nexpected: " + valueAndClass(value) + "\ngot: " + valueAndClass(v) + + "; Value at position " + index + " differ"); } return (U)this; } @@ -367,14 +382,15 @@ public final U assertValueAt(int index, @NonNull Predicate valuePredicate) { throw fail("No values"); } - if (index >= values.size()) { - throw fail("Invalid index: " + index); + if (index < 0 || index >= s) { + throw fail("Index " + index + " is out of range [0, " + s + ")"); } boolean found = false; + T v = values.get(index); try { - if (valuePredicate.test(values.get(index))) { + if (valuePredicate.test(v)) { found = true; } } catch (Throwable ex) { @@ -382,7 +398,7 @@ public final U assertValueAt(int index, @NonNull Predicate valuePredicate) { } if (!found) { - throw fail("Value not present"); + throw fail("Value " + valueAndClass(v) + " at position " + index + " did not pass the predicate"); } return (U)this; } @@ -410,7 +426,7 @@ public static String valueAndClass(@Nullable Object o) { public final U assertValueCount(int count) { int s = values.size(); if (s != count) { - throw fail("Value counts differ; expected: " + count + " but was: " + s); + throw fail("\nexpected: " + count + "\ngot: " + s + "; Value counts differ"); } return (U)this; } @@ -435,14 +451,15 @@ public final U assertNoValues() { public final U assertValues(@NonNull T... values) { int s = this.values.size(); if (s != values.length) { - throw fail("Value count differs; expected: " + values.length + " " + Arrays.toString(values) - + " but was: " + s + " " + this.values); + throw fail("\nexpected: " + values.length + " " + Arrays.toString(values) + + "\ngot: " + s + " " + this.values + "; Value count differs"); } for (int i = 0; i < s; i++) { T v = this.values.get(i); T u = values[i]; if (!Objects.equals(u, v)) { - throw fail("Values at position " + i + " differ; expected: " + valueAndClass(u) + " but was: " + valueAndClass(v)); + throw fail("\nexpected: " + valueAndClass(u) + "\ngot: " + valueAndClass(v) + + "; Value at position " + i + " differ"); } } return (U)this; @@ -489,7 +506,8 @@ public final U assertValueSequence(@NonNull Iterable sequence) { T v = actualIterator.next(); if (!Objects.equals(u, v)) { - throw fail("Values at position " + i + " differ; expected: " + valueAndClass(u) + " but was: " + valueAndClass(v)); + throw fail("\nexpected: " + valueAndClass(u) + "\ngot: " + valueAndClass(v) + + "; Value at position " + i + " differ"); } i++; } diff --git a/src/main/java/io/reactivex/rxjava3/observers/DefaultObserver.java b/src/main/java/io/reactivex/rxjava3/observers/DefaultObserver.java index 42cd69e79cd..29d1f16d007 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/DefaultObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/DefaultObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/DisposableCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/observers/DisposableCompletableObserver.java index 940654b622f..20bf6d59d59 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/DisposableCompletableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/DisposableCompletableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/DisposableMaybeObserver.java b/src/main/java/io/reactivex/rxjava3/observers/DisposableMaybeObserver.java index 092994e8180..6ea1d26e977 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/DisposableMaybeObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/DisposableMaybeObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/DisposableObserver.java b/src/main/java/io/reactivex/rxjava3/observers/DisposableObserver.java index ff2eba7758c..d4e6d5f5d8a 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/DisposableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/DisposableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/DisposableSingleObserver.java b/src/main/java/io/reactivex/rxjava3/observers/DisposableSingleObserver.java index 56e5c543b72..9126332b218 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/DisposableSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/DisposableSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/LambdaConsumerIntrospection.java b/src/main/java/io/reactivex/rxjava3/observers/LambdaConsumerIntrospection.java index e3f5c46cfe1..293847979ec 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/LambdaConsumerIntrospection.java +++ b/src/main/java/io/reactivex/rxjava3/observers/LambdaConsumerIntrospection.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/ResourceCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/observers/ResourceCompletableObserver.java index df05fe01692..339692d7560 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/ResourceCompletableObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/ResourceCompletableObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/ResourceMaybeObserver.java b/src/main/java/io/reactivex/rxjava3/observers/ResourceMaybeObserver.java index 22345e60ced..e9df1c3edcf 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/ResourceMaybeObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/ResourceMaybeObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/ResourceObserver.java b/src/main/java/io/reactivex/rxjava3/observers/ResourceObserver.java index f0810f4c5e7..0238dd5a176 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/ResourceObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/ResourceObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/ResourceSingleObserver.java b/src/main/java/io/reactivex/rxjava3/observers/ResourceSingleObserver.java index efebfaa85c4..b1b90495241 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/ResourceSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/ResourceSingleObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/observers/SafeObserver.java b/src/main/java/io/reactivex/rxjava3/observers/SafeObserver.java index c3935e79dc9..4a72e5b80e1 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/SafeObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/SafeObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observers; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/observers/SerializedObserver.java b/src/main/java/io/reactivex/rxjava3/observers/SerializedObserver.java index e0d32fbd7ae..062a3b6abf7 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/SerializedObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/SerializedObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observers; import io.reactivex.rxjava3.annotations.NonNull; diff --git a/src/main/java/io/reactivex/rxjava3/observers/TestObserver.java b/src/main/java/io/reactivex/rxjava3/observers/TestObserver.java index 44b129fdab4..8142747ec1f 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/TestObserver.java +++ b/src/main/java/io/reactivex/rxjava3/observers/TestObserver.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observers; import java.util.concurrent.atomic.AtomicReference; diff --git a/src/main/java/io/reactivex/rxjava3/observers/package-info.java b/src/main/java/io/reactivex/rxjava3/observers/package-info.java index dbf39cbef2b..09f56f3eb03 100644 --- a/src/main/java/io/reactivex/rxjava3/observers/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/observers/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** @@ -23,7 +20,8 @@ *

* Available observer variants *
- * + *
+ * * * * diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/ConditionalSubscriber.java b/src/main/java/io/reactivex/rxjava3/operators/ConditionalSubscriber.java similarity index 85% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/ConditionalSubscriber.java rename to src/main/java/io/reactivex/rxjava3/operators/ConditionalSubscriber.java index 9db35aed028..0880d125447 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/ConditionalSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/operators/ConditionalSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -11,20 +11,20 @@ * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.FlowableSubscriber; /** - * A Subscriber with an additional {@link #tryOnNext(Object)} method that - * tells the caller the specified value has been accepted or - * not. + * A {@link FlowableSubscriber} with an additional {@link #tryOnNext(Object)} method that + * tells the caller the specified value has been accepted or not. * *

This allows certain queue-drain or source-drain operators * to avoid requesting 1 on behalf of a dropped value. * * @param the value type + * @since 3.1.1 */ public interface ConditionalSubscriber<@NonNull T> extends FlowableSubscriber { /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueDisposable.java b/src/main/java/io/reactivex/rxjava3/operators/QueueDisposable.java similarity index 69% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueDisposable.java rename to src/main/java/io/reactivex/rxjava3/operators/QueueDisposable.java index 74124d918c9..97096064d90 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueDisposable.java +++ b/src/main/java/io/reactivex/rxjava3/operators/QueueDisposable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,16 +10,15 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; -import java.util.Queue; +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.disposables.Disposable; /** - * An interface extending Queue and Disposable and allows negotiating - * the fusion mode between subsequent operators of the {@code Observable} base reactive type. + * An interface extending {@link SimpleQueue} and {@link Disposable} and allows negotiating + * the fusion mode between subsequent operators of the {@link io.reactivex.rxjava3.core.Observable Observable} base reactive type. *

* The negotiation happens in subscription time when the upstream * calls the {@code onSubscribe} with an instance of this interface. The @@ -27,30 +26,32 @@ * with the appropriate mode before calling {@code request()}. *

* In synchronous fusion, all upstream values are either already available or is generated - * when {@link #poll()} is called synchronously. When the {@link #poll()} returns null, + * when {@link #poll()} is called synchronously. When the {@link #poll()} returns {@code null}, * that is the indication if a terminated stream. In this mode, the upstream won't call the onXXX methods. *

* In asynchronous fusion, upstream values may become available to {@link #poll()} eventually. - * Upstream signals onError() and onComplete() as usual but onNext may not actually contain - * the upstream value but have {@code null} instead. Downstream should treat such onNext as indication - * that {@link #poll()} can be called. + * Upstream signals {@code onError()} and {@code onComplete()} as usual, however, + * {@code onNext} will be called with {@code null} instead of the actual value. + * Downstream should treat such onNext as indication that {@link #poll()} can be called. *

- * The general rules for consuming the {@link Queue} interface: + * The general rules for consuming the {@link SimpleQueue} interface: *

    - *
  • {@link #poll()} has to be called sequentially (from within a serializing drain-loop).
  • + *
  • {@link #poll()} and {@link #clear()} has to be called sequentially (from within a serializing drain-loop).
  • *
  • In addition, callers of {@link #poll()} should be prepared to catch exceptions.
  • *
  • Due to how computation attaches to the {@link #poll()}, {@link #poll()} may return * {@code null} even if a preceding {@link #isEmpty()} returned false.
  • *
*

* Implementations should only allow calling the following methods and the rest of the - * {@link Queue} interface methods should throw {@link UnsupportedOperationException}: + * {@link SimpleQueue} interface methods should throw {@link UnsupportedOperationException}: *

    *
  • {@link #poll()}
  • *
  • {@link #isEmpty()}
  • *
  • {@link #clear()}
  • *
* @param the value type transmitted through the queue + * @see QueueSubscription + * @since 3.1.1 */ public interface QueueDisposable<@NonNull T> extends QueueFuseable, Disposable { } diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueFuseable.java b/src/main/java/io/reactivex/rxjava3/operators/QueueFuseable.java similarity index 95% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueFuseable.java rename to src/main/java/io/reactivex/rxjava3/operators/QueueFuseable.java index 71b93a75add..d295d12f0db 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueFuseable.java +++ b/src/main/java/io/reactivex/rxjava3/operators/QueueFuseable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -11,13 +11,14 @@ * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.NonNull; /** - * Represents a SimpleQueue plus the means and constants for requesting a fusion mode. + * Represents a {@link SimpleQueue} plus the means and constants for requesting a fusion mode. * @param the value type returned by the SimpleQueue.poll() + * @since 3.1.1 */ public interface QueueFuseable<@NonNull T> extends SimpleQueue { /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueSubscription.java b/src/main/java/io/reactivex/rxjava3/operators/QueueSubscription.java similarity index 70% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueSubscription.java rename to src/main/java/io/reactivex/rxjava3/operators/QueueSubscription.java index 923589377c0..eae89229927 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/QueueSubscription.java +++ b/src/main/java/io/reactivex/rxjava3/operators/QueueSubscription.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,17 +10,16 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; -import java.util.Queue; +package io.reactivex.rxjava3.operators; import org.reactivestreams.Subscription; import io.reactivex.rxjava3.annotations.NonNull; /** - * An interface extending Queue and Subscription and allows negotiating - * the fusion mode between subsequent operators of the {@code Flowable} base reactive type. + * An interface extending {@link SimpleQueue} and {@link Subscription} and allows negotiating + * the fusion mode between subsequent operators of the {@link io.reactivex.rxjava3.core.Flowable Flowable} base reactive type. *

* The negotiation happens in subscription time when the upstream * calls the {@code onSubscribe} with an instance of this interface. The @@ -33,27 +32,30 @@ * in this mode. In this mode, the upstream won't call the onXXX methods. *

* In asynchronous fusion, upstream values may become available to {@link #poll()} eventually. - * Upstream signals onError() and onComplete() as usual but onNext may not actually contain - * the upstream value but have {@code null} instead. Downstream should treat such onNext as indication - * that {@link #poll()} can be called. In this mode, the downstream still has to call {@link #request(long)} + * Upstream signals {@code onError()} and {@code onComplete()} as usual, however, + * {@code onNext} will be called with {@code null} instead of the actual value. + * Downstream should treat such onNext as indication that {@link #poll()} can be called. + * In this mode, the downstream still has to call {@link #request(long)} * to indicate it is prepared to receive more values. *

- * The general rules for consuming the {@link Queue} interface: + * The general rules for consuming the {@link SimpleQueue} interface: *

    - *
  • {@link #poll()} has to be called sequentially (from within a serializing drain-loop).
  • + *
  • {@link #poll()} and {@link #clear()} has to be called sequentially (from within a serializing drain-loop).
  • *
  • In addition, callers of {@link #poll()} should be prepared to catch exceptions.
  • *
  • Due to how computation attaches to the {@link #poll()}, {@link #poll()} may return * {@code null} even if a preceding {@link #isEmpty()} returned false.
  • *
*

* Implementations should only allow calling the following methods and the rest of the - * {@link Queue} interface methods should throw {@link UnsupportedOperationException}: + * {@link SimpleQueue} interface methods should throw {@link UnsupportedOperationException}: *

    *
  • {@link #poll()}
  • *
  • {@link #isEmpty()}
  • *
  • {@link #clear()}
  • *
* @param the value type transmitted through the queue + * @see QueueDisposable + * @since 3.1.1 */ public interface QueueSubscription<@NonNull T> extends QueueFuseable, Subscription { } diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/ScalarSupplier.java b/src/main/java/io/reactivex/rxjava3/operators/ScalarSupplier.java similarity index 96% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/ScalarSupplier.java rename to src/main/java/io/reactivex/rxjava3/operators/ScalarSupplier.java index eda6086f87a..9b79c5c1020 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/ScalarSupplier.java +++ b/src/main/java/io/reactivex/rxjava3/operators/ScalarSupplier.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,7 +10,8 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; + +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.functions.Supplier; @@ -29,6 +30,7 @@ * single-element sources uniformly. *

* @param the scalar value type held by the implementing reactive type + * @since 3.1.1 */ @FunctionalInterface public interface ScalarSupplier<@NonNull T> extends Supplier { diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/SimplePlainQueue.java b/src/main/java/io/reactivex/rxjava3/operators/SimplePlainQueue.java similarity index 83% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/SimplePlainQueue.java rename to src/main/java/io/reactivex/rxjava3/operators/SimplePlainQueue.java index c3122038c11..7e0cac21f35 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/SimplePlainQueue.java +++ b/src/main/java/io/reactivex/rxjava3/operators/SimplePlainQueue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -11,14 +11,15 @@ * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.*; /** - * Override of the SimpleQueue interface with no throws Exception on poll(). + * Override of the {@link SimpleQueue} interface with no {@code throws Throwable} on {@code poll()}. * * @param the value type to offer and poll, not null + * @since 3.1.1 */ public interface SimplePlainQueue<@NonNull T> extends SimpleQueue { diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/SimpleQueue.java b/src/main/java/io/reactivex/rxjava3/operators/SimpleQueue.java similarity index 85% rename from src/main/java/io/reactivex/rxjava3/internal/fuseable/SimpleQueue.java rename to src/main/java/io/reactivex/rxjava3/operators/SimpleQueue.java index 49d893031b4..a10b7f9a43c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/fuseable/SimpleQueue.java +++ b/src/main/java/io/reactivex/rxjava3/operators/SimpleQueue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -11,19 +11,24 @@ * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.fuseable; +package io.reactivex.rxjava3.operators; import io.reactivex.rxjava3.annotations.*; /** - * A minimalist queue interface without the method bloat of java.util.Collection and java.util.Queue. + * A simplified interface for offering, polling and clearing a queue. + *

+ * This interface does not define most of the {@link java.util.Collection} + * or {@link java.util.Queue} methods as the intended usage of {@code SimpleQueue} + * does not require support for iteration or introspection. * * @param the value type to offer and poll, not null + * @since 3.1.1 */ public interface SimpleQueue<@NonNull T> { /** - * Atomically enqueue a single. + * Atomically enqueue a single value. * @param value the value to enqueue, not null * @return true if successful, false if the value was not enqueued * likely due to reaching the queue capacity) diff --git a/src/main/java/io/reactivex/rxjava3/internal/queue/SpscArrayQueue.java b/src/main/java/io/reactivex/rxjava3/operators/SpscArrayQueue.java similarity index 93% rename from src/main/java/io/reactivex/rxjava3/internal/queue/SpscArrayQueue.java rename to src/main/java/io/reactivex/rxjava3/operators/SpscArrayQueue.java index c86a109f81c..1e4c2d4f110 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/queue/SpscArrayQueue.java +++ b/src/main/java/io/reactivex/rxjava3/operators/SpscArrayQueue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,12 +16,11 @@ * https://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/queues/atomic */ -package io.reactivex.rxjava3.internal.queue; +package io.reactivex.rxjava3.operators; import java.util.concurrent.atomic.*; import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.util.Pow2; /** @@ -37,6 +36,7 @@ * This implementation is wait free. * * @param the element type of the queue + * @since 3.1.1 */ public final class SpscArrayQueue extends AtomicReferenceArray implements SimplePlainQueue { private static final long serialVersionUID = -1296597691183856449L; @@ -47,6 +47,12 @@ public final class SpscArrayQueue extends AtomicReferenceArray implements final AtomicLong consumerIndex; final int lookAheadStep; + /** + * Constructs an array-backed queue with the given capacity rounded + * up to the next power of 2 size. + * @param capacity the maximum number of elements the queue would hold, + * rounded up to the next power of 2 + */ public SpscArrayQueue(int capacity) { super(Pow2.roundToPowerOfTwo(capacity)); this.mask = length() - 1; diff --git a/src/main/java/io/reactivex/rxjava3/internal/queue/SpscLinkedArrayQueue.java b/src/main/java/io/reactivex/rxjava3/operators/SpscLinkedArrayQueue.java similarity index 95% rename from src/main/java/io/reactivex/rxjava3/internal/queue/SpscLinkedArrayQueue.java rename to src/main/java/io/reactivex/rxjava3/operators/SpscLinkedArrayQueue.java index 2bd61dcc154..97fac2253ab 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/queue/SpscLinkedArrayQueue.java +++ b/src/main/java/io/reactivex/rxjava3/operators/SpscLinkedArrayQueue.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,18 +16,18 @@ * https://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/queues/atomic */ -package io.reactivex.rxjava3.internal.queue; +package io.reactivex.rxjava3.operators; import java.util.concurrent.atomic.*; import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.internal.fuseable.SimplePlainQueue; import io.reactivex.rxjava3.internal.util.Pow2; /** * A single-producer single-consumer array-backed queue which can allocate new arrays in case the consumer is slower * than the producer. * @param the contained value type + * @since 3.1.1 */ public final class SpscLinkedArrayQueue implements SimplePlainQueue { static final int MAX_LOOK_AHEAD_STEP = Integer.getInteger("jctools.spsc.max.lookahead.step", 4096); @@ -45,6 +45,11 @@ public final class SpscLinkedArrayQueue implements SimplePlainQueue { private static final Object HAS_NEXT = new Object(); + /** + * Constructs a linked array-based queue instance with the given + * island size rounded up to the next power of 2. + * @param bufferSize the maximum number of elements per island + */ public SpscLinkedArrayQueue(final int bufferSize) { int p2capacity = Pow2.roundToPowerOfTwo(Math.max(8, bufferSize)); int mask = p2capacity - 1; @@ -160,7 +165,13 @@ private T newBufferPoll(AtomicReferenceArray nextBuffer, final long inde return n; } + /** + * Returns the next element in this queue without removing it or {@code null} + * if this queue is empty + * @return the next element or {@code null} + */ @SuppressWarnings("unchecked") + @Nullable public T peek() { final AtomicReferenceArray buffer = consumerBuffer; final long index = lpConsumerIndex(); @@ -186,6 +197,10 @@ public void clear() { while (poll() != null || !isEmpty()) { } // NOPMD } + /** + * Returns the number of elements in the queue. + * @return the number of elements in the queue + */ public int size() { /* * It is possible for a thread to be interrupted or reschedule between the read of the producer and diff --git a/src/main/java/io/reactivex/rxjava3/operators/package-info.java b/src/main/java/io/reactivex/rxjava3/operators/package-info.java new file mode 100644 index 00000000000..93e1ca05be7 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/operators/package-info.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/** + * Classes and interfaces for writing advanced operators within and outside RxJava. + */ + +package io.reactivex.rxjava3.operators; \ No newline at end of file diff --git a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFailureHandling.java b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFailureHandling.java index 9e78d698e89..ce0496651e5 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFailureHandling.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFailureHandling.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java index 58152e2400b..8d5414d27cf 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -59,7 +59,7 @@ public abstract class ParallelFlowable<@NonNull T> { */ @BackpressureSupport(BackpressureKind.SPECIAL) @SchedulerSupport(SchedulerSupport.NONE) - public abstract void subscribe(@NonNull Subscriber<@NonNull ? super T>[] subscribers); + public abstract void subscribe(@NonNull Subscriber[] subscribers); /** * Returns the number of expected parallel {@link Subscriber}s. @@ -110,7 +110,7 @@ protected final boolean validate(@NonNull Subscriber<@NonNull ?>[] subscribers) @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static <@NonNull T> ParallelFlowable from(@NonNull Publisher<@NonNull ? extends T> source) { + public static <@NonNull T> ParallelFlowable from(@NonNull Publisher source) { return from(source, Runtime.getRuntime().availableProcessors(), Flowable.bufferSize()); } @@ -135,7 +135,7 @@ protected final boolean validate(@NonNull Subscriber<@NonNull ?>[] subscribers) @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static <@NonNull T> ParallelFlowable from(@NonNull Publisher<@NonNull ? extends T> source, int parallelism) { + public static <@NonNull T> ParallelFlowable from(@NonNull Publisher source, int parallelism) { return from(source, parallelism, Flowable.bufferSize()); } @@ -164,7 +164,7 @@ protected final boolean validate(@NonNull Subscriber<@NonNull ?>[] subscribers) @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) - public static <@NonNull T> ParallelFlowable from(@NonNull Publisher<@NonNull ? extends T> source, + public static <@NonNull T> ParallelFlowable from(@NonNull Publisher source, int parallelism, int prefetch) { Objects.requireNonNull(source, "source is null"); ObjectHelper.verifyPositive(parallelism, "parallelism"); @@ -193,7 +193,7 @@ protected final boolean validate(@NonNull Subscriber<@NonNull ?>[] subscribers) @NonNull @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.PASS_THROUGH) - public final ParallelFlowable map(@NonNull Function mapper) { + public final <@NonNull R> ParallelFlowable map(@NonNull Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ParallelMap<>(this, mapper)); } @@ -223,7 +223,7 @@ public final ParallelFlowable map(@NonNull Function ParallelFlowable map(@NonNull Function mapper, @NonNull ParallelFailureHandling errorHandler) { + public final <@NonNull R> ParallelFlowable map(@NonNull Function mapper, @NonNull ParallelFailureHandling errorHandler) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(errorHandler, "errorHandler is null"); return RxJavaPlugins.onAssembly(new ParallelMapTry<>(this, mapper, errorHandler)); @@ -255,7 +255,7 @@ public final ParallelFlowable map(@NonNull Function ParallelFlowable map(@NonNull Function mapper, @NonNull BiFunction errorHandler) { + public final <@NonNull R> ParallelFlowable map(@NonNull Function mapper, @NonNull BiFunction errorHandler) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(errorHandler, "errorHandler is null"); return RxJavaPlugins.onAssembly(new ParallelMapTry<>(this, mapper, errorHandler)); @@ -473,7 +473,7 @@ public final Flowable reduce(@NonNull BiFunction reducer) { @NonNull @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable reduce(@NonNull Supplier initialSupplier, @NonNull BiFunction reducer) { + public final <@NonNull R> ParallelFlowable reduce(@NonNull Supplier initialSupplier, @NonNull BiFunction reducer) { Objects.requireNonNull(initialSupplier, "initialSupplier is null"); Objects.requireNonNull(reducer, "reducer is null"); return RxJavaPlugins.onAssembly(new ParallelReduce<>(this, initialSupplier, reducer)); @@ -1044,7 +1044,7 @@ public final ParallelFlowable doOnCancel(@NonNull Action onCancel) { @NonNull @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable collect(@NonNull Supplier collectionSupplier, @NonNull BiConsumer collector) { + public final <@NonNull C> ParallelFlowable collect(@NonNull Supplier collectionSupplier, @NonNull BiConsumer collector) { Objects.requireNonNull(collectionSupplier, "collectionSupplier is null"); Objects.requireNonNull(collector, "collector is null"); return RxJavaPlugins.onAssembly(new ParallelCollect<>(this, collectionSupplier, collector)); @@ -1126,7 +1126,7 @@ public final ParallelFlowable collect(@NonNull Supplier coll @NonNull @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable compose(@NonNull ParallelTransformer composer) { + public final <@NonNull U> ParallelFlowable compose(@NonNull ParallelTransformer composer) { return RxJavaPlugins.onAssembly(Objects.requireNonNull(composer, "composer is null").apply(this)); } @@ -1154,7 +1154,7 @@ public final ParallelFlowable compose(@NonNull ParallelTransformer @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable flatMap(@NonNull Function> mapper) { + public final <@NonNull R> ParallelFlowable flatMap(@NonNull Function> mapper) { return flatMap(mapper, false, Flowable.bufferSize(), Flowable.bufferSize()); } @@ -1184,8 +1184,8 @@ public final ParallelFlowable flatMap(@NonNull Function ParallelFlowable flatMap( - @NonNull Function> mapper, boolean delayError) { + public final <@NonNull R> ParallelFlowable flatMap( + @NonNull Function> mapper, boolean delayError) { return flatMap(mapper, delayError, Flowable.bufferSize(), Flowable.bufferSize()); } @@ -1218,8 +1218,8 @@ public final ParallelFlowable flatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable flatMap( - @NonNull Function> mapper, boolean delayError, int maxConcurrency) { + public final <@NonNull R> ParallelFlowable flatMap( + @NonNull Function> mapper, boolean delayError, int maxConcurrency) { return flatMap(mapper, delayError, maxConcurrency, Flowable.bufferSize()); } @@ -1252,8 +1252,8 @@ public final ParallelFlowable flatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable flatMap( - @NonNull Function> mapper, + public final <@NonNull R> ParallelFlowable flatMap( + @NonNull Function> mapper, boolean delayError, int maxConcurrency, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); @@ -1284,8 +1284,8 @@ public final ParallelFlowable flatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable concatMap( - @NonNull Function> mapper) { + public final <@NonNull R> ParallelFlowable concatMap( + @NonNull Function> mapper) { return concatMap(mapper, 2); } @@ -1315,8 +1315,8 @@ public final ParallelFlowable concatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable concatMap( - @NonNull Function> mapper, + public final <@NonNull R> ParallelFlowable concatMap( + @NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1348,8 +1348,8 @@ public final ParallelFlowable concatMap( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable concatMapDelayError( - @NonNull Function> mapper, + public final <@NonNull R> ParallelFlowable concatMapDelayError( + @NonNull Function> mapper, boolean tillTheEnd) { return concatMapDelayError(mapper, 2, tillTheEnd); } @@ -1381,8 +1381,8 @@ public final ParallelFlowable concatMapDelayError( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final ParallelFlowable concatMapDelayError( - @NonNull Function> mapper, + public final <@NonNull R> ParallelFlowable concatMapDelayError( + @NonNull Function> mapper, int prefetch, boolean tillTheEnd) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); @@ -1419,7 +1419,7 @@ public final ParallelFlowable concatMapDelayError( @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final ParallelFlowable flatMapIterable(@NonNull Function> mapper) { + public final <@NonNull U> ParallelFlowable flatMapIterable(@NonNull Function> mapper) { return flatMapIterable(mapper, Flowable.bufferSize()); } @@ -1455,7 +1455,7 @@ public final ParallelFlowable flatMapIterable(@NonNull Function ParallelFlowable flatMapIterable(@NonNull Function> mapper, int bufferSize) { + public final <@NonNull U> ParallelFlowable flatMapIterable(@NonNull Function> mapper, int bufferSize) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ParallelFlatMapIterable<>(this, mapper, bufferSize)); @@ -1486,7 +1486,7 @@ public final ParallelFlowable flatMapIterable(@NonNull Function ParallelFlowable mapOptional(@NonNull Function> mapper) { + public final <@NonNull R> ParallelFlowable mapOptional(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ParallelMapOptional<>(this, mapper)); } @@ -1516,7 +1516,7 @@ public final ParallelFlowable mapOptional(@NonNull Function ParallelFlowable mapOptional(@NonNull Function> mapper, @NonNull ParallelFailureHandling errorHandler) { + public final <@NonNull R> ParallelFlowable mapOptional(@NonNull Function> mapper, @NonNull ParallelFailureHandling errorHandler) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(errorHandler, "errorHandler is null"); return RxJavaPlugins.onAssembly(new ParallelMapTryOptional<>(this, mapper, errorHandler)); @@ -1548,7 +1548,7 @@ public final ParallelFlowable mapOptional(@NonNull Function ParallelFlowable mapOptional(@NonNull Function> mapper, @NonNull BiFunction errorHandler) { + public final <@NonNull R> ParallelFlowable mapOptional(@NonNull Function> mapper, @NonNull BiFunction errorHandler) { Objects.requireNonNull(mapper, "mapper is null"); Objects.requireNonNull(errorHandler, "errorHandler is null"); return RxJavaPlugins.onAssembly(new ParallelMapTryOptional<>(this, mapper, errorHandler)); @@ -1604,7 +1604,7 @@ public final ParallelFlowable mapOptional(@NonNull Function ParallelFlowable flatMapStream(@NonNull Function> mapper) { + public final <@NonNull R> ParallelFlowable flatMapStream(@NonNull Function> mapper) { return flatMapStream(mapper, Flowable.bufferSize()); } @@ -1658,7 +1658,7 @@ public final ParallelFlowable mapOptional(@NonNull Function ParallelFlowable flatMapStream(@NonNull Function> mapper, int prefetch) { + public final <@NonNull R> ParallelFlowable flatMapStream(@NonNull Function> mapper, int prefetch) { Objects.requireNonNull(mapper, "mapper is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); return RxJavaPlugins.onAssembly(new ParallelFlatMapStream<>(this, mapper, prefetch)); @@ -1688,7 +1688,7 @@ public final ParallelFlowable mapOptional(@NonNull Function Flowable collect(@NonNull Collector collector) { + public final <@NonNull A, @NonNull R> Flowable collect(@NonNull Collector collector) { Objects.requireNonNull(collector, "collector is null"); return RxJavaPlugins.onAssembly(new ParallelCollector<>(this, collector)); } diff --git a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowableConverter.java b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowableConverter.java index 7033261e65a..47510faf37b 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowableConverter.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowableConverter.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/parallel/ParallelTransformer.java b/src/main/java/io/reactivex/rxjava3/parallel/ParallelTransformer.java index a10a73ead46..f35f71567c1 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/ParallelTransformer.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/ParallelTransformer.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -32,4 +32,4 @@ public interface ParallelTransformer<@NonNull Upstream, @NonNull Downstream> { */ @NonNull ParallelFlowable apply(@NonNull ParallelFlowable upstream); -} \ No newline at end of file +} diff --git a/src/main/java/io/reactivex/rxjava3/parallel/package-info.java b/src/main/java/io/reactivex/rxjava3/parallel/package-info.java index 7c9cc785ad4..09605021f07 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/package-info.java @@ -1,21 +1,18 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** * Contains the base type {@link io.reactivex.rxjava3.parallel.ParallelFlowable}, * a sub-DSL for working with {@link io.reactivex.rxjava3.core.Flowable} sequences in parallel. */ -package io.reactivex.rxjava3.parallel; \ No newline at end of file +package io.reactivex.rxjava3.parallel; diff --git a/src/main/java/io/reactivex/rxjava3/plugins/RxJavaPlugins.java b/src/main/java/io/reactivex/rxjava3/plugins/RxJavaPlugins.java index 408eae8d360..2949253b31c 100644 --- a/src/main/java/io/reactivex/rxjava3/plugins/RxJavaPlugins.java +++ b/src/main/java/io/reactivex/rxjava3/plugins/RxJavaPlugins.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,11 +10,12 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.plugins; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Objects; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.*; import org.reactivestreams.Subscriber; @@ -95,22 +96,26 @@ public final class RxJavaPlugins { @SuppressWarnings("rawtypes") @Nullable - static volatile BiFunction onFlowableSubscribe; + static volatile BiFunction onFlowableSubscribe; @SuppressWarnings("rawtypes") @Nullable - static volatile BiFunction onMaybeSubscribe; + static volatile BiFunction onMaybeSubscribe; @SuppressWarnings("rawtypes") @Nullable - static volatile BiFunction onObservableSubscribe; + static volatile BiFunction onObservableSubscribe; @SuppressWarnings("rawtypes") @Nullable - static volatile BiFunction onSingleSubscribe; + static volatile BiFunction onSingleSubscribe; + + @Nullable + static volatile BiFunction onCompletableSubscribe; + @SuppressWarnings("rawtypes") @Nullable - static volatile BiFunction onCompletableSubscribe; + static volatile BiFunction onParallelSubscribe; @Nullable static volatile BooleanSupplier onBeforeBlocking; @@ -397,10 +402,13 @@ static boolean isBug(Throwable error) { return true; } // the sender didn't honor the request amount - // it's either due to an operator bug or concurrent onNext if (error instanceof MissingBackpressureException) { return true; } + // it's either due to an operator bug or concurrent onNext + if (error instanceof QueueOverflowException) { + return true; + } // general protocol violations // it's either due to an operator bug or concurrent onNext if (error instanceof IllegalStateException) { @@ -525,6 +533,7 @@ public static void reset() { setOnMaybeSubscribe(null); setOnParallelAssembly(null); + setOnParallelSubscribe(null); setFailOnNonBlockingScheduler(false); setOnBeforeBlocking(null); @@ -661,7 +670,7 @@ public static void setSingleSchedulerHandler(@Nullable Function getOnCompletableSubscribe() { + public static BiFunction getOnCompletableSubscribe() { return onCompletableSubscribe; } @@ -691,7 +700,7 @@ public static void setSingleSchedulerHandler(@Nullable Function getOnFlowableSubscribe() { + public static BiFunction getOnFlowableSubscribe() { return onFlowableSubscribe; } @@ -701,7 +710,7 @@ public static void setSingleSchedulerHandler(@Nullable Function getOnMaybeSubscribe() { + public static BiFunction getOnMaybeSubscribe() { return onMaybeSubscribe; } @@ -731,7 +740,7 @@ public static void setSingleSchedulerHandler(@Nullable Function getOnSingleSubscribe() { + public static BiFunction getOnSingleSubscribe() { return onSingleSubscribe; } @@ -761,7 +770,7 @@ public static void setSingleSchedulerHandler(@Nullable Function getOnObservableSubscribe() { + public static BiFunction getOnObservableSubscribe() { return onObservableSubscribe; } @@ -781,7 +790,7 @@ public static void setOnCompletableAssembly(@Nullable Function onCompletableSubscribe) { + @Nullable BiFunction onCompletableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } @@ -829,7 +838,7 @@ public static void setOnConnectableFlowableAssembly(@Nullable Function onFlowableSubscribe) { + public static void setOnFlowableSubscribe(@Nullable BiFunction onFlowableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } @@ -841,7 +850,7 @@ public static void setOnFlowableSubscribe(@Nullable BiFunction onMaybeSubscribe) { + public static void setOnMaybeSubscribe(@Nullable BiFunction onMaybeSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } @@ -878,7 +887,7 @@ public static void setOnConnectableObservableAssembly(@Nullable Function onObservableSubscribe) { + @Nullable BiFunction onObservableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } @@ -902,7 +911,7 @@ public static void setOnSingleAssembly(@Nullable Function onSingleSubscribe) { + public static void setOnSingleSubscribe(@Nullable BiFunction onSingleSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } @@ -918,8 +927,8 @@ public static void setOnSingleSubscribe(@Nullable BiFunction Subscriber<@NonNull ? super T> onSubscribe(@NonNull Flowable source, @NonNull Subscriber<@NonNull ? super T> subscriber) { - BiFunction f = onFlowableSubscribe; + public static <@NonNull T> Subscriber onSubscribe(@NonNull Flowable source, @NonNull Subscriber subscriber) { + BiFunction f = onFlowableSubscribe; if (f != null) { return apply(f, source, subscriber); } @@ -935,8 +944,8 @@ public static void setOnSingleSubscribe(@Nullable BiFunction Observer onSubscribe(@NonNull Observable source, @NonNull Observer observer) { - BiFunction f = onObservableSubscribe; + public static <@NonNull T> Observer onSubscribe(@NonNull Observable source, @NonNull Observer observer) { + BiFunction f = onObservableSubscribe; if (f != null) { return apply(f, source, observer); } @@ -952,8 +961,8 @@ public static Observer onSubscribe(@NonNull Observable source, */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static SingleObserver onSubscribe(@NonNull Single source, @NonNull SingleObserver observer) { - BiFunction f = onSingleSubscribe; + public static <@NonNull T> SingleObserver onSubscribe(@NonNull Single source, @NonNull SingleObserver observer) { + BiFunction f = onSingleSubscribe; if (f != null) { return apply(f, source, observer); } @@ -968,7 +977,7 @@ public static SingleObserver onSubscribe(@NonNull Single sourc */ @NonNull public static CompletableObserver onSubscribe(@NonNull Completable source, @NonNull CompletableObserver observer) { - BiFunction f = onCompletableSubscribe; + BiFunction f = onCompletableSubscribe; if (f != null) { return apply(f, source, observer); } @@ -984,14 +993,31 @@ public static CompletableObserver onSubscribe(@NonNull Completable source, @NonN */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static MaybeObserver onSubscribe(@NonNull Maybe source, @NonNull MaybeObserver observer) { - BiFunction f = onMaybeSubscribe; + public static <@NonNull T> MaybeObserver onSubscribe(@NonNull Maybe source, @NonNull MaybeObserver observer) { + BiFunction f = onMaybeSubscribe; if (f != null) { return apply(f, source, observer); } return observer; } + /** + * Calls the associated hook function. + * @param the value type + * @param source the hook's input value + * @param subscribers the array of subscribers + * @return the value returned by the hook + */ + @SuppressWarnings({ "rawtypes" }) + @NonNull + public static <@NonNull T> Subscriber[] onSubscribe(@NonNull ParallelFlowable source, @NonNull Subscriber[] subscribers) { + BiFunction f = onParallelSubscribe; + if (f != null) { + return apply(f, source, subscribers); + } + return subscribers; + } + /** * Calls the associated hook function. * @param the value type @@ -1000,7 +1026,7 @@ public static MaybeObserver onSubscribe(@NonNull Maybe source, */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static Maybe onAssembly(@NonNull Maybe source) { + public static <@NonNull T> Maybe onAssembly(@NonNull Maybe source) { Function f = onMaybeAssembly; if (f != null) { return apply(f, source); @@ -1016,7 +1042,7 @@ public static Maybe onAssembly(@NonNull Maybe source) { */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static Flowable onAssembly(@NonNull Flowable source) { + public static <@NonNull T> Flowable onAssembly(@NonNull Flowable source) { Function f = onFlowableAssembly; if (f != null) { return apply(f, source); @@ -1032,7 +1058,7 @@ public static Flowable onAssembly(@NonNull Flowable source) { */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static ConnectableFlowable onAssembly(@NonNull ConnectableFlowable source) { + public static <@NonNull T> ConnectableFlowable onAssembly(@NonNull ConnectableFlowable source) { Function f = onConnectableFlowableAssembly; if (f != null) { return apply(f, source); @@ -1048,7 +1074,7 @@ public static ConnectableFlowable onAssembly(@NonNull ConnectableFlowable */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static Observable onAssembly(@NonNull Observable source) { + public static <@NonNull T> Observable onAssembly(@NonNull Observable source) { Function f = onObservableAssembly; if (f != null) { return apply(f, source); @@ -1064,7 +1090,7 @@ public static Observable onAssembly(@NonNull Observable source) { */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static ConnectableObservable onAssembly(@NonNull ConnectableObservable source) { + public static <@NonNull T> ConnectableObservable onAssembly(@NonNull ConnectableObservable source) { Function f = onConnectableObservableAssembly; if (f != null) { return apply(f, source); @@ -1080,7 +1106,7 @@ public static ConnectableObservable onAssembly(@NonNull ConnectableObserv */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull - public static Single onAssembly(@NonNull Single source) { + public static <@NonNull T> Single onAssembly(@NonNull Single source) { Function f = onSingleAssembly; if (f != null) { return apply(f, source); @@ -1128,6 +1154,32 @@ public static void setOnParallelAssembly(@Nullable FunctionHistory: 3.0.11 - experimental + * @param handler the hook function to set, null allowed + * @since 3.1.0 + */ + @SuppressWarnings("rawtypes") + public static void setOnParallelSubscribe(@Nullable BiFunction handler) { + if (lockdown) { + throw new IllegalStateException("Plugins can't be changed anymore"); + } + onParallelSubscribe = handler; + } + + /** + * Returns the current hook function. + *

History: 3.0.11 - experimental + * @return the hook function, may be null + * @since 3.1.0 + */ + @SuppressWarnings("rawtypes") + @Nullable + public static BiFunction getOnParallelSubscribe() { + return onParallelSubscribe; + } + /** * Calls the associated hook function. *

History: 2.0.6 - experimental; 2.1 - beta @@ -1138,7 +1190,7 @@ public static void setOnParallelAssembly(@Nullable Function ParallelFlowable onAssembly(@NonNull ParallelFlowable source) { + public static <@NonNull T> ParallelFlowable onAssembly(@NonNull ParallelFlowable source) { Function f = onParallelAssembly; if (f != null) { return apply(f, source); @@ -1253,6 +1305,26 @@ public static Scheduler createSingleScheduler(@NonNull ThreadFactory threadFacto return new SingleScheduler(Objects.requireNonNull(threadFactory, "threadFactory is null")); } + /** + * Create an instance of a {@link Scheduler} by wrapping an existing {@link Executor}. + *

+ * This method allows creating an {@code Executor}-backed {@code Scheduler} before the {@link Schedulers} class + * would initialize the standard {@code Scheduler}s. + * + * @param executor the {@code Executor} to wrap and turn into a {@code Scheduler}. + * @param interruptibleWorker if {@code true}, the tasks submitted to the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} will + * be interrupted when the task is disposed. + * @param fair if {@code true}, tasks submitted to the {@code Scheduler} or {@code Worker} will be executed by the underlying {@code Executor} one after the other, still + * in a FIFO and non-overlapping manner, but allows interleaving with other tasks submitted to the underlying {@code Executor}. + * If {@code false}, the underlying FIFO scheme will execute as many tasks as it can before giving up the underlying {@code Executor} thread. + * @return the new {@code Scheduler} wrapping the {@code Executor} + * @since 3.1.0 + */ + @NonNull + public static Scheduler createExecutorScheduler(@NonNull Executor executor, boolean interruptibleWorker, boolean fair) { + return new ExecutorScheduler(executor, interruptibleWorker, fair); + } + /** * Wraps the call to the function in try-catch and propagates thrown * checked exceptions as RuntimeException. @@ -1263,7 +1335,7 @@ public static Scheduler createSingleScheduler(@NonNull ThreadFactory threadFacto * @return the result of the function call */ @NonNull - static R apply(@NonNull Function f, @NonNull T t) { + static <@NonNull T, @NonNull R> R apply(@NonNull Function f, @NonNull T t) { try { return f.apply(t); } catch (Throwable ex) { @@ -1283,7 +1355,7 @@ static R apply(@NonNull Function f, @NonNull T t) { * @return the result of the function call */ @NonNull - static R apply(@NonNull BiFunction f, @NonNull T t, @NonNull U u) { + static <@NonNull T, @NonNull U, @NonNull R> R apply(@NonNull BiFunction f, @NonNull T t, @NonNull U u) { try { return f.apply(t, u); } catch (Throwable ex) { diff --git a/src/main/java/io/reactivex/rxjava3/plugins/package-info.java b/src/main/java/io/reactivex/rxjava3/plugins/package-info.java index a3105506a4f..49390584dff 100644 --- a/src/main/java/io/reactivex/rxjava3/plugins/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/plugins/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/processors/AsyncProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/AsyncProcessor.java index 8037c67ffef..b20c8b23aed 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/AsyncProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/AsyncProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.processors; import java.util.concurrent.atomic.AtomicReference; @@ -113,7 +114,7 @@ * * @param the value type */ -public final class AsyncProcessor extends FlowableProcessor { +public final class AsyncProcessor<@NonNull T> extends FlowableProcessor { @SuppressWarnings("rawtypes") static final AsyncSubscription[] EMPTY = new AsyncSubscription[0]; @@ -228,7 +229,7 @@ public Throwable getThrowable() { } @Override - protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) { + protected void subscribeActual(@NonNull Subscriber s) { AsyncSubscription as = new AsyncSubscription<>(s, this); s.onSubscribe(as); if (add(as)) { @@ -336,12 +337,12 @@ public T getValue() { return subscribers.get() == TERMINATED ? value : null; } - static final class AsyncSubscription extends DeferredScalarSubscription { + static final class AsyncSubscription<@NonNull T> extends DeferredScalarSubscription { private static final long serialVersionUID = 5629876084736248016L; final AsyncProcessor parent; - AsyncSubscription(Subscriber<@NonNull ? super T> actual, AsyncProcessor parent) { + AsyncSubscription(Subscriber actual, AsyncProcessor parent) { super(actual); this.parent = parent; } diff --git a/src/main/java/io/reactivex/rxjava3/processors/BehaviorProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/BehaviorProcessor.java index de5d744f3fa..2e5117ca560 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/BehaviorProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/BehaviorProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -160,7 +160,7 @@ * @param * the type of item expected to be observed and emitted by the Processor */ -public final class BehaviorProcessor extends FlowableProcessor { +public final class BehaviorProcessor<@NonNull T> extends FlowableProcessor { final AtomicReference[]> subscribers; static final Object[] EMPTY_ARRAY = new Object[0]; @@ -239,7 +239,7 @@ public static BehaviorProcessor create() { } @Override - protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) { + protected void subscribeActual(@NonNull Subscriber s) { BehaviorSubscription bs = new BehaviorSubscription<>(s, this); s.onSubscribe(bs); if (add(bs)) { @@ -306,17 +306,14 @@ public void onComplete() { } /** - * Tries to emit the item to all currently subscribed Subscribers if all of them - * has requested some value, returns false otherwise. - *

- * This method should be called in a sequential manner just like the onXXX methods - * of the PublishProcessor. + * Tries to emit the item to all currently subscribed {@link Subscriber}s if all of them + * has requested some value, returns {@code false} otherwise. *

- * Calling with a null value will terminate the PublishProcessor and a NullPointerException - * is signaled to the Subscribers. + * This method should be called in a sequential manner just like the {@code onXXX} methods + * of this {@code BehaviorProcessor}. *

History: 2.0.8 - experimental - * @param t the item to emit, not null - * @return true if the item was emitted to all Subscribers + * @param t the item to emit, not {@code null} + * @return {@code true} if the item was emitted to all {@code Subscriber}s * @throws NullPointerException if {@code t} is {@code null} * @since 2.2 */ @@ -455,16 +452,9 @@ void remove(BehaviorSubscription rs) { @SuppressWarnings("unchecked") BehaviorSubscription[] terminate(Object terminalValue) { - BehaviorSubscription[] a = subscribers.get(); - if (a != TERMINATED) { - a = subscribers.getAndSet(TERMINATED); - if (a != TERMINATED) { - // either this or atomics with lots of allocation - setCurrent(terminalValue); - } - } + setCurrent(terminalValue); - return a; + return subscribers.getAndSet(TERMINATED); } void setCurrent(Object o) { @@ -479,7 +469,7 @@ static final class BehaviorSubscription<@NonNull T> extends AtomicLong implement private static final long serialVersionUID = 3293175281126227086L; - final Subscriber<@NonNull ? super T> downstream; + final Subscriber downstream; final BehaviorProcessor state; boolean next; @@ -492,7 +482,7 @@ static final class BehaviorSubscription<@NonNull T> extends AtomicLong implement long index; - BehaviorSubscription(Subscriber<@NonNull ? super T> actual, BehaviorProcessor state) { + BehaviorSubscription(Subscriber actual, BehaviorProcessor state) { this.downstream = actual; this.state = state; } @@ -600,7 +590,7 @@ public boolean test(Object o) { return false; } cancel(); - downstream.onError(new MissingBackpressureException("Could not deliver value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); return true; } diff --git a/src/main/java/io/reactivex/rxjava3/processors/FlowableProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/FlowableProcessor.java index 86622298f69..2bfbb33bd0c 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/FlowableProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/FlowableProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/processors/MulticastProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/MulticastProcessor.java index 7ef61d79595..14a7a55ee2a 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/MulticastProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/MulticastProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,10 +20,9 @@ import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.functions.ObjectHelper; -import io.reactivex.rxjava3.internal.fuseable.*; -import io.reactivex.rxjava3.internal.queue.*; import io.reactivex.rxjava3.internal.subscriptions.*; -import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -130,7 +129,7 @@ */ @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) -public final class MulticastProcessor extends FlowableProcessor { +public final class MulticastProcessor<@NonNull T> extends FlowableProcessor { final AtomicInteger wip; @@ -138,8 +137,6 @@ public final class MulticastProcessor extends FlowableProcessor { final AtomicReference[]> subscribers; - final AtomicBoolean once; - final int bufferSize; final int limit; @@ -233,7 +230,6 @@ public static MulticastProcessor create(int bufferSize, boolean refCount) this.subscribers = new AtomicReference<>(EMPTY); this.upstream = new AtomicReference<>(); this.refcount = refCount; - this.once = new AtomicBoolean(); } /** @@ -292,14 +288,14 @@ public void onSubscribe(@NonNull Subscription s) { @Override public void onNext(@NonNull T t) { - if (once.get()) { + if (done) { return; } if (fusionMode == QueueSubscription.NONE) { ExceptionHelper.nullCheck(t, "onNext called with a null value."); if (!queue.offer(t)) { SubscriptionHelper.cancel(upstream); - onError(new MissingBackpressureException()); + onError(MissingBackpressureException.createDefault()); return; } } @@ -317,7 +313,7 @@ public void onNext(@NonNull T t) { @CheckReturnValue public boolean offer(@NonNull T t) { ExceptionHelper.nullCheck(t, "offer called with a null value."); - if (once.get()) { + if (done) { return false; } if (fusionMode == QueueSubscription.NONE) { @@ -333,21 +329,19 @@ public boolean offer(@NonNull T t) { @Override public void onError(@NonNull Throwable t) { ExceptionHelper.nullCheck(t, "onError called with a null Throwable."); - if (once.compareAndSet(false, true)) { + if (!done) { error = t; done = true; drain(); - } else { - RxJavaPlugins.onError(t); + return; } + RxJavaPlugins.onError(t); } @Override public void onComplete() { - if (once.compareAndSet(false, true)) { - done = true; - drain(); - } + done = true; + drain(); } @Override @@ -359,23 +353,23 @@ public boolean hasSubscribers() { @Override @CheckReturnValue public boolean hasThrowable() { - return once.get() && error != null; + return done && error != null; } @Override @CheckReturnValue public boolean hasComplete() { - return once.get() && error == null; + return done && error == null; } @Override @CheckReturnValue public Throwable getThrowable() { - return once.get() ? error : null; + return done ? error : null; } @Override - protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) { + protected void subscribeActual(@NonNull Subscriber s) { MulticastSubscription ms = new MulticastSubscription<>(s, this); s.onSubscribe(ms); if (add(ms)) { @@ -385,7 +379,7 @@ protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) { drain(); } } else { - if (once.get() || !refcount) { + if (done) { Throwable ex = error; if (ex != null) { s.onError(ex); @@ -438,7 +432,7 @@ void remove(MulticastSubscription inner) { if (refcount) { if (subscribers.compareAndSet(a, TERMINATED)) { SubscriptionHelper.cancel(upstream); - once.set(true); + done = true; break; } } else { @@ -589,17 +583,17 @@ void drain() { } } - static final class MulticastSubscription extends AtomicLong implements Subscription { + static final class MulticastSubscription<@NonNull T> extends AtomicLong implements Subscription { private static final long serialVersionUID = -363282618957264509L; - final Subscriber<@NonNull ? super T> downstream; + final Subscriber downstream; final MulticastProcessor parent; long emitted; - MulticastSubscription(Subscriber<@NonNull ? super T> actual, MulticastProcessor parent) { + MulticastSubscription(Subscriber actual, MulticastProcessor parent) { this.downstream = actual; this.parent = parent; } @@ -607,19 +601,9 @@ static final class MulticastSubscription extends AtomicLong implements Subscr @Override public void request(long n) { if (SubscriptionHelper.validate(n)) { - for (;;) { - long r = get(); - if (r == Long.MIN_VALUE || r == Long.MAX_VALUE) { - break; - } - long u = r + n; - if (u < 0L) { - u = Long.MAX_VALUE; - } - if (compareAndSet(r, u)) { - parent.drain(); - break; - } + long r = BackpressureHelper.addCancel(this, n); + if (r != Long.MIN_VALUE && r != Long.MAX_VALUE) { + parent.drain(); } } } diff --git a/src/main/java/io/reactivex/rxjava3/processors/PublishProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/PublishProcessor.java index b507a2225bf..73507844d20 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/PublishProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/PublishProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.processors; import java.util.concurrent.atomic.*; @@ -106,7 +107,7 @@ * @param the value type multicasted to Subscribers. * @see MulticastProcessor */ -public final class PublishProcessor extends FlowableProcessor { +public final class PublishProcessor<@NonNull T> extends FlowableProcessor { /** The terminated indicator for the subscribers array. */ @SuppressWarnings("rawtypes") static final PublishSubscription[] TERMINATED = new PublishSubscription[0]; @@ -141,7 +142,7 @@ public static PublishProcessor create() { } @Override - protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> t) { + protected void subscribeActual(@NonNull Subscriber t) { PublishSubscription ps = new PublishSubscription<>(t, this); t.onSubscribe(ps); if (add(ps)) { @@ -270,17 +271,14 @@ public void onComplete() { } /** - * Tries to emit the item to all currently subscribed Subscribers if all of them - * has requested some value, returns false otherwise. - *

- * This method should be called in a sequential manner just like the onXXX methods - * of the PublishProcessor. + * Tries to emit the item to all currently subscribed {@link Subscriber}s if all of them + * has requested some value, returns {@code false} otherwise. *

- * Calling with a null value will terminate the PublishProcessor and a NullPointerException - * is signaled to the Subscribers. + * This method should be called in a sequential manner just like the {@code onXXX} methods + * of this {@code PublishProcessor}. *

History: 2.0.8 - experimental - * @param t the item to emit, not null - * @return true if the item was emitted to all Subscribers + * @param t the item to emit, not {@code null} + * @return {@code true} if the item was emitted to all {@code Subscriber}s * @throws NullPointerException if {@code t} is {@code null} * @since 2.2 */ @@ -340,7 +338,7 @@ static final class PublishSubscription<@NonNull T> extends AtomicLong implements private static final long serialVersionUID = 3562861878281475070L; /** The actual subscriber. */ - final Subscriber<@NonNull ? super T> downstream; + final Subscriber downstream; /** The parent processor servicing this subscriber. */ final PublishProcessor parent; @@ -349,7 +347,7 @@ static final class PublishSubscription<@NonNull T> extends AtomicLong implements * @param actual the actual subscriber * @param parent the parent PublishProcessor */ - PublishSubscription(Subscriber<@NonNull ? super T> actual, PublishProcessor parent) { + PublishSubscription(Subscriber actual, PublishProcessor parent) { this.downstream = actual; this.parent = parent; } @@ -364,7 +362,7 @@ public void onNext(T t) { BackpressureHelper.producedCancel(this, 1); } else { cancel(); - downstream.onError(new MissingBackpressureException("Could not emit value due to lack of requests")); + downstream.onError(MissingBackpressureException.createDefault()); } } diff --git a/src/main/java/io/reactivex/rxjava3/processors/ReplayProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/ReplayProcessor.java index aa3402ec137..ae6a7d3960a 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/ReplayProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/ReplayProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -141,7 +141,7 @@ * * @param the value type */ -public final class ReplayProcessor extends FlowableProcessor { +public final class ReplayProcessor<@NonNull T> extends FlowableProcessor { /** An empty array to avoid allocation in getValues(). */ private static final Object[] EMPTY_ARRAY = new Object[0]; @@ -345,7 +345,7 @@ public static ReplayProcessor createWithTimeAndSize(long maxAge, @NonNull } @Override - protected void subscribeActual(Subscriber<@NonNull ? super T> s) { + protected void subscribeActual(Subscriber s) { ReplaySubscription rs = new ReplaySubscription<>(s, this); s.onSubscribe(rs); @@ -584,7 +584,7 @@ void remove(ReplaySubscription rs) { * * @param the value type */ - interface ReplayBuffer { + interface ReplayBuffer<@NonNull T> { void next(T value); @@ -612,10 +612,10 @@ interface ReplayBuffer { void trimHead(); } - static final class ReplaySubscription extends AtomicInteger implements Subscription { + static final class ReplaySubscription<@NonNull T> extends AtomicInteger implements Subscription { private static final long serialVersionUID = 466549804534799122L; - final Subscriber<@NonNull ? super T> downstream; + final Subscriber downstream; final ReplayProcessor state; Object index; @@ -626,7 +626,7 @@ static final class ReplaySubscription extends AtomicInteger implements Subscr long emitted; - ReplaySubscription(Subscriber<@NonNull ? super T> actual, ReplayProcessor state) { + ReplaySubscription(Subscriber actual, ReplayProcessor state) { this.downstream = actual; this.state = state; this.requested = new AtomicLong(); @@ -728,7 +728,7 @@ public void replay(ReplaySubscription rs) { int missed = 1; final List b = buffer; - final Subscriber<@NonNull ? super T> a = rs.downstream; + final Subscriber a = rs.downstream; Integer indexObject = (Integer)rs.index; int index; @@ -846,7 +846,7 @@ static final class TimedNode extends AtomicReference> { } } - static final class SizeBoundReplayBuffer + static final class SizeBoundReplayBuffer<@NonNull T> implements ReplayBuffer { final int maxSize; @@ -967,7 +967,7 @@ public void replay(ReplaySubscription rs) { } int missed = 1; - final Subscriber<@NonNull ? super T> a = rs.downstream; + final Subscriber a = rs.downstream; Node index = (Node)rs.index; if (index == null) { @@ -1101,10 +1101,6 @@ void trim() { break; } TimedNode next = h.get(); - if (next == null) { - head = h; - break; - } if (next.time > limit) { head = h; @@ -1257,7 +1253,7 @@ public void replay(ReplaySubscription rs) { } int missed = 1; - final Subscriber<@NonNull ? super T> a = rs.downstream; + final Subscriber a = rs.downstream; TimedNode index = (TimedNode)rs.index; if (index == null) { diff --git a/src/main/java/io/reactivex/rxjava3/processors/SerializedProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/SerializedProcessor.java index e7740b65233..e40d935c51c 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/SerializedProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/SerializedProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/processors/UnicastProcessor.java b/src/main/java/io/reactivex/rxjava3/processors/UnicastProcessor.java index 7d7e20a0751..ad7e7f66b66 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/UnicastProcessor.java +++ b/src/main/java/io/reactivex/rxjava3/processors/UnicastProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,10 +20,10 @@ import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.internal.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** @@ -147,7 +147,7 @@ * @param the value type received and emitted by this Processor subclass * @since 2.0 */ -public final class UnicastProcessor extends FlowableProcessor { +public final class UnicastProcessor<@NonNull T> extends FlowableProcessor { final SpscLinkedArrayQueue queue; @@ -159,7 +159,7 @@ public final class UnicastProcessor extends FlowableProcessor { Throwable error; - final AtomicReference> downstream; + final AtomicReference> downstream; volatile boolean cancelled; @@ -282,7 +282,7 @@ void doTerminate() { } } - void drainRegular(Subscriber<@NonNull ? super T> a) { + void drainRegular(Subscriber a) { int missed = 1; final SpscLinkedArrayQueue q = queue; @@ -326,7 +326,7 @@ void drainRegular(Subscriber<@NonNull ? super T> a) { } } - void drainFused(Subscriber<@NonNull ? super T> a) { + void drainFused(Subscriber a) { int missed = 1; final SpscLinkedArrayQueue q = queue; @@ -374,7 +374,7 @@ void drain() { int missed = 1; - Subscriber<@NonNull ? super T> a = downstream.get(); + Subscriber a = downstream.get(); for (;;) { if (a != null) { @@ -394,7 +394,7 @@ void drain() { } } - boolean checkTerminated(boolean failFast, boolean d, boolean empty, Subscriber<@NonNull ? super T> a, SpscLinkedArrayQueue q) { + boolean checkTerminated(boolean failFast, boolean d, boolean empty, Subscriber a, SpscLinkedArrayQueue q) { if (cancelled) { q.clear(); downstream.lazySet(null); @@ -475,7 +475,7 @@ public void onComplete() { } @Override - protected void subscribeActual(Subscriber<@NonNull ? super T> s) { + protected void subscribeActual(Subscriber s) { if (!once.get() && once.compareAndSet(false, true)) { s.onSubscribe(wip); diff --git a/src/main/java/io/reactivex/rxjava3/processors/package-info.java b/src/main/java/io/reactivex/rxjava3/processors/package-info.java index be2bb7c9543..f4119c9ba8b 100644 --- a/src/main/java/io/reactivex/rxjava3/processors/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/processors/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/SchedulerRunnableIntrospection.java b/src/main/java/io/reactivex/rxjava3/schedulers/SchedulerRunnableIntrospection.java index aec31701380..97f8efcc9da 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/SchedulerRunnableIntrospection.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/SchedulerRunnableIntrospection.java @@ -1,8 +1,11 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/Schedulers.java b/src/main/java/io/reactivex/rxjava3/schedulers/Schedulers.java index 4d4c3517a59..cb256524048 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/Schedulers.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/Schedulers.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,22 +22,27 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** - * Static factory methods for returning standard Scheduler instances. + * Static factory methods for returning standard {@link Scheduler} instances. *

* The initial and runtime values of the various scheduler types can be overridden via the * {@code RxJavaPlugins.setInit(scheduler name)SchedulerHandler()} and * {@code RxJavaPlugins.set(scheduler name)SchedulerHandler()} respectively. + * Note that overriding any initial {@code Scheduler} via the {@link RxJavaPlugins} + * has to happen before the {@code Schedulers} class is accessed. *

* Supported system properties ({@code System.getProperty()}): *

    - *
  • {@code rx3.io-keep-alive-time} (long): sets the keep-alive time of the {@link #io()} Scheduler workers, default is {@link IoScheduler#KEEP_ALIVE_TIME_DEFAULT}
  • - *
  • {@code rx3.io-priority} (int): sets the thread priority of the {@link #io()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • - *
  • {@code rx3.computation-threads} (int): sets the number of threads in the {@link #computation()} Scheduler, default is the number of available CPUs
  • - *
  • {@code rx3.computation-priority} (int): sets the thread priority of the {@link #computation()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • - *
  • {@code rx3.newthread-priority} (int): sets the thread priority of the {@link #newThread()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • - *
  • {@code rx3.single-priority} (int): sets the thread priority of the {@link #single()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • - *
  • {@code rx3.purge-enabled} (boolean): enables periodic purging of all Scheduler's backing thread pools, default is false
  • - *
  • {@code rx3.purge-period-seconds} (int): specifies the periodic purge interval of all Scheduler's backing thread pools, default is 1 second
  • + *
  • {@code rx3.io-keep-alive-time} (long): sets the keep-alive time of the {@link #io()} {@code Scheduler} workers, default is {@link IoScheduler#KEEP_ALIVE_TIME_DEFAULT}
  • + *
  • {@code rx3.io-priority} (int): sets the thread priority of the {@link #io()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.io-scheduled-release} (boolean): {@code true} sets the worker release mode of the + * {@link #io()} {@code Scheduler} to scheduled, default is {@code false} for eager mode.
  • + *
  • {@code rx3.computation-threads} (int): sets the number of threads in the {@link #computation()} {@code Scheduler}, default is the number of available CPUs
  • + *
  • {@code rx3.computation-priority} (int): sets the thread priority of the {@link #computation()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.newthread-priority} (int): sets the thread priority of the {@link #newThread()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.single-priority} (int): sets the thread priority of the {@link #single()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.purge-enabled} (boolean): enables purging of all {@code Scheduler}'s backing thread pools, default is {@code true}
  • + *
  • {@code rx3.scheduler.use-nanotime} (boolean): {@code true} instructs {@code Scheduler} to use {@link System#nanoTime()} for {@link Scheduler#now(TimeUnit)}, + * instead of default {@link System#currentTimeMillis()} ({@code false})
  • *
*/ public final class Schedulers { @@ -105,32 +110,32 @@ private Schedulers() { * not disposing a worker that has timed/delayed tasks not cancelled by other means may leak resources and/or * execute those tasks "unexpectedly". *

- * If the {@link RxJavaPlugins#setFailOnNonBlockingScheduler(boolean)} is set to true, attempting to execute + * If the {@link RxJavaPlugins#setFailOnNonBlockingScheduler(boolean)} is set to {@code true}, attempting to execute * operators that block while running on this scheduler will throw an {@link IllegalStateException}. *

* You can control certain properties of this standard scheduler via system properties that have to be set - * before the {@link Schedulers} class is referenced in your code. + * before the {@code Schedulers} class is referenced in your code. *

Supported system properties ({@code System.getProperty()}): *

    - *
  • {@code rx3.computation-threads} (int): sets the number of threads in the {@code computation()} Scheduler, default is the number of available CPUs
  • - *
  • {@code rx3.computation-priority} (int): sets the thread priority of the {@code computation()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.computation-threads} (int): sets the number of threads in the {@code computation()} {@code Scheduler}, default is the number of available CPUs
  • + *
  • {@code rx3.computation-priority} (int): sets the thread priority of the {@code computation()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • *
*

* The default value of this scheduler can be overridden at initialization time via the * {@link RxJavaPlugins#setInitComputationSchedulerHandler(io.reactivex.rxjava3.functions.Function)} plugin method. * Note that due to possible initialization cycles, using any of the other scheduler-returning methods will - * result in a {@code NullPointerException}. - * Once the {@link Schedulers} class has been initialized, you can override the returned {@link Scheduler} instance + * result in a {@link NullPointerException}. + * Once the {@code Schedulers} class has been initialized, you can override the returned {@code Scheduler} instance * via the {@link RxJavaPlugins#setComputationSchedulerHandler(io.reactivex.rxjava3.functions.Function)} method. *

- * It is possible to create a fresh instance of this scheduler with a custom ThreadFactory, via the + * It is possible to create a fresh instance of this scheduler with a custom {@link ThreadFactory}, via the * {@link RxJavaPlugins#createComputationScheduler(ThreadFactory)} method. Note that such custom * instances require a manual call to {@link Scheduler#shutdown()} to allow the JVM to exit or the * (J2EE) container to unload properly. *

Operators on the base reactive classes that use this scheduler are marked with the * @{@link io.reactivex.rxjava3.annotations.SchedulerSupport SchedulerSupport}({@link io.reactivex.rxjava3.annotations.SchedulerSupport#COMPUTATION COMPUTATION}) * annotation. - * @return a {@link Scheduler} meant for computation-bound work + * @return a {@code Scheduler} meant for computation-bound work */ @NonNull public static Scheduler computation() { @@ -146,7 +151,7 @@ public static Scheduler computation() { * that will try to reuse previously started instances used by the worker * returned by {@link io.reactivex.rxjava3.core.Scheduler#createWorker()} but otherwise will start a new backing * {@link ScheduledExecutorService} instance. Note that this scheduler may create an unbounded number - * of worker threads that can result in system slowdowns or {@code OutOfMemoryError}. Therefore, for casual uses + * of worker threads that can result in system slowdowns or {@link OutOfMemoryError}. Therefore, for casual uses * or when implementing an operator, the Worker instances must be disposed via {@link io.reactivex.rxjava3.core.Scheduler.Worker#dispose()}. *

* It is not recommended to perform computational work on this scheduler. Use {@link #computation()} instead. @@ -154,28 +159,46 @@ public static Scheduler computation() { * Unhandled errors will be delivered to the scheduler Thread's {@link java.lang.Thread.UncaughtExceptionHandler}. *

* You can control certain properties of this standard scheduler via system properties that have to be set - * before the {@link Schedulers} class is referenced in your code. + * before the {@code Schedulers} class is referenced in your code. *

Supported system properties ({@code System.getProperty()}): *

    - *
  • {@code rx3.io-keep-alive-time} (long): sets the keep-alive time of the {@code io()} Scheduler workers, default is {@link IoScheduler#KEEP_ALIVE_TIME_DEFAULT}
  • - *
  • {@code rx3.io-priority} (int): sets the thread priority of the {@code io()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.io-keep-alive-time} (long): sets the keep-alive time of the {@code io()} {@code Scheduler} workers, default is {@link IoScheduler#KEEP_ALIVE_TIME_DEFAULT}
  • + *
  • {@code rx3.io-priority} (int): sets the thread priority of the {@code io()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.io-scheduled-release} (boolean): {@code true} sets the worker release mode of the + * {@code #io()} {@code Scheduler} to scheduled, default is {@code false} for eager mode.
  • *
*

* The default value of this scheduler can be overridden at initialization time via the * {@link RxJavaPlugins#setInitIoSchedulerHandler(io.reactivex.rxjava3.functions.Function)} plugin method. * Note that due to possible initialization cycles, using any of the other scheduler-returning methods will - * result in a {@code NullPointerException}. - * Once the {@link Schedulers} class has been initialized, you can override the returned {@link Scheduler} instance + * result in a {@link NullPointerException}. + * Once the {@code Schedulers} class has been initialized, you can override the returned {@code Scheduler} instance * via the {@link RxJavaPlugins#setIoSchedulerHandler(io.reactivex.rxjava3.functions.Function)} method. *

- * It is possible to create a fresh instance of this scheduler with a custom ThreadFactory, via the + * It is possible to create a fresh instance of this scheduler with a custom {@link ThreadFactory}, via the * {@link RxJavaPlugins#createIoScheduler(ThreadFactory)} method. Note that such custom * instances require a manual call to {@link Scheduler#shutdown()} to allow the JVM to exit or the * (J2EE) container to unload properly. *

Operators on the base reactive classes that use this scheduler are marked with the * @{@link io.reactivex.rxjava3.annotations.SchedulerSupport SchedulerSupport}({@link io.reactivex.rxjava3.annotations.SchedulerSupport#IO IO}) * annotation. - * @return a {@link Scheduler} meant for IO-bound work + *

+ * When the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} is disposed, + * the underlying worker can be released to the cached worker pool in two modes: + *

    + *
  • In eager mode (default), the underlying worker is returned immediately to the cached worker pool + * and can be reused much quicker by operators. The drawback is that if the currently running task doesn't + * respond to interruption in time or at all, this may lead to delays or deadlock with the reuse use of the + * underlying worker. + *
  • + *
  • In scheduled mode (enabled via the system parameter {@code rx3.io-scheduled-release} + * set to {@code true}), the underlying worker is returned to the cached worker pool only after the currently running task + * has finished. This can help prevent premature reuse of the underlying worker and likely won't lead to delays or + * deadlock with such reuses. The drawback is that the delay in release may lead to an excess amount of underlying + * workers being created. + *
  • + *
+ * @return a {@code Scheduler} meant for IO-bound work */ @NonNull public static Scheduler io() { @@ -194,7 +217,7 @@ public static Scheduler io() { * by RxJava itself but may be found in external libraries. *

* This scheduler can't be overridden via an {@link RxJavaPlugins} method. - * @return a {@link Scheduler} that queues work on the current thread + * @return a {@code Scheduler} that queues work on the current thread */ @NonNull public static Scheduler trampoline() { @@ -207,33 +230,33 @@ public static Scheduler trampoline() { * The default implementation of this scheduler creates a new, single-threaded {@link ScheduledExecutorService} for * each invocation of the {@link Scheduler#scheduleDirect(Runnable)} (plus its overloads) and {@link Scheduler#createWorker()} * methods, thus an unbounded number of worker threads may be created that can - * result in system slowdowns or {@code OutOfMemoryError}. Therefore, for casual uses or when implementing an operator, + * result in system slowdowns or {@link OutOfMemoryError}. Therefore, for casual uses or when implementing an operator, * the Worker instances must be disposed via {@link io.reactivex.rxjava3.core.Scheduler.Worker#dispose()}. *

* Unhandled errors will be delivered to the scheduler Thread's {@link java.lang.Thread.UncaughtExceptionHandler}. *

* You can control certain properties of this standard scheduler via system properties that have to be set - * before the {@link Schedulers} class is referenced in your code. + * before the {@code Schedulers} class is referenced in your code. *

Supported system properties ({@code System.getProperty()}): *

    - *
  • {@code rx3.newthread-priority} (int): sets the thread priority of the {@code newThread()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.newthread-priority} (int): sets the thread priority of the {@code newThread()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • *
*

* The default value of this scheduler can be overridden at initialization time via the * {@link RxJavaPlugins#setInitNewThreadSchedulerHandler(io.reactivex.rxjava3.functions.Function)} plugin method. * Note that due to possible initialization cycles, using any of the other scheduler-returning methods will - * result in a {@code NullPointerException}. - * Once the {@link Schedulers} class has been initialized, you can override the returned {@link Scheduler} instance + * result in a {@link NullPointerException}. + * Once the {@code Schedulers} class has been initialized, you can override the returned {@code Scheduler} instance * via the {@link RxJavaPlugins#setNewThreadSchedulerHandler(io.reactivex.rxjava3.functions.Function)} method. *

- * It is possible to create a fresh instance of this scheduler with a custom ThreadFactory, via the + * It is possible to create a fresh instance of this scheduler with a custom {@link ThreadFactory}, via the * {@link RxJavaPlugins#createNewThreadScheduler(ThreadFactory)} method. Note that such custom * instances require a manual call to {@link Scheduler#shutdown()} to allow the JVM to exit or the * (J2EE) container to unload properly. *

Operators on the base reactive classes that use this scheduler are marked with the * @{@link io.reactivex.rxjava3.annotations.SchedulerSupport SchedulerSupport}({@link io.reactivex.rxjava3.annotations.SchedulerSupport#NEW_THREAD NEW_TRHEAD}) * annotation. - * @return a {@link Scheduler} that creates new threads + * @return a {@code Scheduler} that creates new threads */ @NonNull public static Scheduler newThread() { @@ -247,7 +270,7 @@ public static Scheduler newThread() { * Uses: *

    *
  • event loop
  • - *
  • support Schedulers.from(Executor) and from(ExecutorService) with delayed scheduling
  • + *
  • support {@code Schedulers.from(}{@link Executor}{@code )} and {@code from(}{@link ExecutorService}{@code )} with delayed scheduling
  • *
  • support benchmarks that pipeline data from some thread to another thread and * avoid core-bashing of computation's round-robin nature
  • *
@@ -258,31 +281,31 @@ public static Scheduler newThread() { * not disposing a worker that has timed/delayed tasks not cancelled by other means may leak resources and/or * execute those tasks "unexpectedly". *

- * If the {@link RxJavaPlugins#setFailOnNonBlockingScheduler(boolean)} is set to true, attempting to execute + * If the {@link RxJavaPlugins#setFailOnNonBlockingScheduler(boolean)} is set to {@code true}, attempting to execute * operators that block while running on this scheduler will throw an {@link IllegalStateException}. *

* You can control certain properties of this standard scheduler via system properties that have to be set - * before the {@link Schedulers} class is referenced in your code. + * before the {@code Schedulers} class is referenced in your code. *

Supported system properties ({@code System.getProperty()}): *

    - *
  • {@code rx3.single-priority} (int): sets the thread priority of the {@code single()} Scheduler, default is {@link Thread#NORM_PRIORITY}
  • + *
  • {@code rx3.single-priority} (int): sets the thread priority of the {@code single()} {@code Scheduler}, default is {@link Thread#NORM_PRIORITY}
  • *
*

* The default value of this scheduler can be overridden at initialization time via the * {@link RxJavaPlugins#setInitSingleSchedulerHandler(io.reactivex.rxjava3.functions.Function)} plugin method. * Note that due to possible initialization cycles, using any of the other scheduler-returning methods will - * result in a {@code NullPointerException}. - * Once the {@link Schedulers} class has been initialized, you can override the returned {@link Scheduler} instance + * result in a {@link NullPointerException}. + * Once the {@code Schedulers} class has been initialized, you can override the returned {@code Scheduler} instance * via the {@link RxJavaPlugins#setSingleSchedulerHandler(io.reactivex.rxjava3.functions.Function)} method. *

- * It is possible to create a fresh instance of this scheduler with a custom ThreadFactory, via the + * It is possible to create a fresh instance of this scheduler with a custom {@link ThreadFactory}, via the * {@link RxJavaPlugins#createSingleScheduler(ThreadFactory)} method. Note that such custom * instances require a manual call to {@link Scheduler#shutdown()} to allow the JVM to exit or the * (J2EE) container to unload properly. *

Operators on the base reactive classes that use this scheduler are marked with the * @{@link io.reactivex.rxjava3.annotations.SchedulerSupport SchedulerSupport}({@link io.reactivex.rxjava3.annotations.SchedulerSupport#SINGLE SINGLE}) * annotation. - * @return a {@link Scheduler} that shares a single backing thread. + * @return a {@code Scheduler} that shares a single backing thread. * @since 2.0 */ @NonNull @@ -291,11 +314,11 @@ public static Scheduler single() { } /** - * Wraps an {@link Executor} into a new Scheduler instance and delegates {@code schedule()} + * Wraps an {@link Executor} into a new {@link Scheduler} instance and delegates {@code schedule()} * calls to it. *

* If the provided executor doesn't support any of the more specific standard Java executor - * APIs, cancelling tasks scheduled by this scheduler can't be interrupted when they are + * APIs, tasks scheduled by this scheduler can't be interrupted when they are * executing but only prevented from running prior to that. In addition, tasks scheduled with * a time delay or periodically will use the {@link #single()} scheduler for the timed waiting * before posting the actual task to the given executor. @@ -304,24 +327,24 @@ public static Scheduler single() { * {@link #from(Executor, boolean)} overload to enable task interruption via this wrapper. *

* If the provided executor supports the standard Java {@link ExecutorService} API, - * cancelling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the {@link #single()} scheduler for the timed waiting * before posting the actual task to the given executor. *

* If the provided executor supports the standard Java {@link ScheduledExecutorService} API, - * cancelling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the provided executor. Note, however, if the provided * {@code ScheduledExecutorService} instance is not single threaded, tasks scheduled * with a time delay close to each other may end up executing in different order than * the original schedule() call was issued. This limitation may be lifted in a future patch. *

- * The implementation of the Worker of this wrapper Scheduler is eager and will execute as many + * The implementation of the Worker of this wrapper {@code Scheduler} is eager and will execute as many * non-delayed tasks as it can, which may result in a longer than expected occupation of a - * thread of the given backing Executor. In other terms, it does not allow per-Runnable fairness - * in case the worker runs on a shared underlying thread of the Executor. - * See {@link #from(Executor, boolean, boolean)} to create a wrapper that uses the underlying Executor + * thread of the given backing {@code Executor}. In other terms, it does not allow per-{@link Runnable} fairness + * in case the worker runs on a shared underlying thread of the {@code Executor}. + * See {@link #from(Executor, boolean, boolean)} to create a wrapper that uses the underlying {@code Executor} * more fairly. *

* Starting, stopping and restarting this scheduler is not supported (no-op) and the provided @@ -340,26 +363,40 @@ public static Scheduler single() { * } * *

+ * Note that the provided {@code Executor} should avoid throwing a {@link RejectedExecutionException} + * (for example, by shutting it down prematurely or using a bounded-queue {@code ExecutorService}) + * because such circumstances prevent RxJava from progressing flow-related activities correctly. + * If the {@link Executor#execute(Runnable)} or {@link ExecutorService#submit(Callable)} throws, + * the {@code RejectedExecutionException} is routed to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)}. To avoid shutdown-related problems, it is recommended + * all flows using the returned {@code Scheduler} to be canceled/disposed before the underlying + * {@code Executor} is shut down. To avoid problems due to the {@code Executor} having a bounded-queue, + * it is recommended to rephrase the flow to utilize backpressure as the means to limit outstanding work. + *

* This type of scheduler is less sensitive to leaking {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} instances, although * not disposing a worker that has timed/delayed tasks not cancelled by other means may leak resources and/or * execute those tasks "unexpectedly". *

- * Note that this method returns a new {@link Scheduler} instance, even for the same {@link Executor} instance. + * Note that this method returns a new {@code Scheduler} instance, even for the same {@code Executor} instance. + *

+ * It is possible to wrap an {@code Executor} into a {@code Scheduler} without triggering the initialization of all the + * standard schedulers by using the {@link RxJavaPlugins#createExecutorScheduler(Executor, boolean, boolean)} method + * before the {@code Schedulers} class itself is accessed. * @param executor * the executor to wrap - * @return the new Scheduler wrapping the Executor + * @return the new {@code Scheduler} wrapping the {@code Executor} * @see #from(Executor, boolean, boolean) */ @NonNull public static Scheduler from(@NonNull Executor executor) { - return new ExecutorScheduler(executor, false, false); + return from(executor, false, false); } /** - * Wraps an {@link Executor} into a new Scheduler instance and delegates {@code schedule()} + * Wraps an {@link Executor} into a new {@link Scheduler} instance and delegates {@code schedule()} * calls to it. *

- * The tasks scheduled by the returned {@link Scheduler} and its {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} + * The tasks scheduled by the returned {@code Scheduler} and its {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} * can be optionally interrupted. *

* If the provided executor doesn't support any of the more specific standard Java executor @@ -368,24 +405,24 @@ public static Scheduler from(@NonNull Executor executor) { * before posting the actual task to the given executor. *

* If the provided executor supports the standard Java {@link ExecutorService} API, - * canceling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the {@link #single()} scheduler for the timed waiting * before posting the actual task to the given executor. *

* If the provided executor supports the standard Java {@link ScheduledExecutorService} API, - * canceling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the provided executor. Note, however, if the provided * {@code ScheduledExecutorService} instance is not single threaded, tasks scheduled * with a time delay close to each other may end up executing in different order than * the original schedule() call was issued. This limitation may be lifted in a future patch. *

- * The implementation of the Worker of this wrapper Scheduler is eager and will execute as many + * The implementation of the {@code Worker} of this wrapper {@code Scheduler} is eager and will execute as many * non-delayed tasks as it can, which may result in a longer than expected occupation of a - * thread of the given backing Executor. In other terms, it does not allow per-Runnable fairness - * in case the worker runs on a shared underlying thread of the Executor. - * See {@link #from(Executor, boolean, boolean)} to create a wrapper that uses the underlying Executor + * thread of the given backing {@code Executor}. In other terms, it does not allow per-{@link Runnable} fairness + * in case the worker runs on a shared underlying thread of the {@code Executor}. + * See {@link #from(Executor, boolean, boolean)} to create a wrapper that uses the underlying {@code Executor} * more fairly. *

* Starting, stopping and restarting this scheduler is not supported (no-op) and the provided @@ -404,30 +441,44 @@ public static Scheduler from(@NonNull Executor executor) { * } * *

+ * Note that the provided {@code Executor} should avoid throwing a {@link RejectedExecutionException} + * (for example, by shutting it down prematurely or using a bounded-queue {@code ExecutorService}) + * because such circumstances prevent RxJava from progressing flow-related activities correctly. + * If the {@link Executor#execute(Runnable)} or {@link ExecutorService#submit(Callable)} throws, + * the {@code RejectedExecutionException} is routed to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)}. To avoid shutdown-related problems, it is recommended + * all flows using the returned {@code Scheduler} to be canceled/disposed before the underlying + * {@code Executor} is shut down. To avoid problems due to the {@code Executor} having a bounded-queue, + * it is recommended to rephrase the flow to utilize backpressure as the means to limit outstanding work. + *

* This type of scheduler is less sensitive to leaking {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} instances, although * not disposing a worker that has timed/delayed tasks not cancelled by other means may leak resources and/or * execute those tasks "unexpectedly". *

- * Note that this method returns a new {@link Scheduler} instance, even for the same {@link Executor} instance. + * Note that this method returns a new {@code Scheduler} instance, even for the same {@code Executor} instance. + *

+ * It is possible to wrap an {@code Executor} into a {@code Scheduler} without triggering the initialization of all the + * standard schedulers by using the {@link RxJavaPlugins#createExecutorScheduler(Executor, boolean, boolean)} method + * before the {@code Schedulers} class itself is accessed. *

History: 2.2.6 - experimental * @param executor * the executor to wrap - * @param interruptibleWorker if {@code true} the tasks submitted to the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} will + * @param interruptibleWorker if {@code true}, the tasks submitted to the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} will * be interrupted when the task is disposed. - * @return the new Scheduler wrapping the Executor + * @return the new {@code Scheduler} wrapping the {@code Executor} * @since 3.0.0 * @see #from(Executor, boolean, boolean) */ @NonNull public static Scheduler from(@NonNull Executor executor, boolean interruptibleWorker) { - return new ExecutorScheduler(executor, interruptibleWorker, false); + return from(executor, interruptibleWorker, false); } /** - * Wraps an {@link Executor} into a new Scheduler instance and delegates {@code schedule()} + * Wraps an {@link Executor} into a new {@link Scheduler} instance and delegates {@code schedule()} * calls to it. *

- * The tasks scheduled by the returned {@link Scheduler} and its {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} + * The tasks scheduled by the returned {@code Scheduler} and its {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} * can be optionally interrupted. *

* If the provided executor doesn't support any of the more specific standard Java executor @@ -436,27 +487,27 @@ public static Scheduler from(@NonNull Executor executor, boolean interruptibleWo * before posting the actual task to the given executor. *

* If the provided executor supports the standard Java {@link ExecutorService} API, - * canceling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the {@link #single()} scheduler for the timed waiting * before posting the actual task to the given executor. *

* If the provided executor supports the standard Java {@link ScheduledExecutorService} API, - * canceling tasks scheduled by this scheduler can be cancelled/interrupted by calling + * tasks scheduled by this scheduler can be cancelled/interrupted by calling * {@link io.reactivex.rxjava3.disposables.Disposable#dispose()}. In addition, tasks scheduled with * a time delay or periodically will use the provided executor. Note, however, if the provided * {@code ScheduledExecutorService} instance is not single threaded, tasks scheduled * with a time delay close to each other may end up executing in different order than * the original schedule() call was issued. This limitation may be lifted in a future patch. *

- * The implementation of the Worker of this wrapper Scheduler can operate in both eager (non-fair) and + * The implementation of the Worker of this wrapper {@code Scheduler} can operate in both eager (non-fair) and * fair modes depending on the specified parameter. In eager mode, it will execute as many * non-delayed tasks as it can, which may result in a longer than expected occupation of a - * thread of the given backing Executor. In other terms, it does not allow per-Runnable fairness - * in case the worker runs on a shared underlying thread of the Executor. In fair mode, + * thread of the given backing {@code Executor}. In other terms, it does not allow per-{@link Runnable} fairness + * in case the worker runs on a shared underlying thread of the {@code Executor}. In fair mode, * non-delayed tasks will still be executed in a FIFO and non-overlapping manner, but after each task, - * the execution for the next task is rescheduled with the same underlying Executor, allowing interleaving - * from both the same Scheduler or other external usages of the underlying Executor. + * the execution for the next task is rescheduled with the same underlying {@code Executor}, allowing interleaving + * from both the same {@code Scheduler} or other external usages of the underlying {@code Executor}. *

* Starting, stopping and restarting this scheduler is not supported (no-op) and the provided * executor's lifecycle must be managed externally: @@ -474,28 +525,43 @@ public static Scheduler from(@NonNull Executor executor, boolean interruptibleWo * } * *

+ * Note that the provided {@code Executor} should avoid throwing a {@link RejectedExecutionException} + * (for example, by shutting it down prematurely or using a bounded-queue {@code ExecutorService}) + * because such circumstances prevent RxJava from progressing flow-related activities correctly. + * If the {@link Executor#execute(Runnable)} or {@link ExecutorService#submit(Callable)} throws, + * the {@code RejectedExecutionException} is routed to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)}. To avoid shutdown-related problems, it is recommended + * all flows using the returned {@code Scheduler} to be canceled/disposed before the underlying + * {@code Executor} is shut down. To avoid problems due to the {@code Executor} having a bounded-queue, + * it is recommended to rephrase the flow to utilize backpressure as the means to limit outstanding work. + *

* This type of scheduler is less sensitive to leaking {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} instances, although * not disposing a worker that has timed/delayed tasks not cancelled by other means may leak resources and/or * execute those tasks "unexpectedly". *

- * Note that this method returns a new {@link Scheduler} instance, even for the same {@link Executor} instance. + * Note that this method returns a new {@code Scheduler} instance, even for the same {@code Executor} instance. + *

+ * It is possible to wrap an {@code Executor} into a {@code Scheduler} without triggering the initialization of all the + * standard schedulers by using the {@link RxJavaPlugins#createExecutorScheduler(Executor, boolean, boolean)} method + * before the {@code Schedulers} class itself is accessed. + * * @param executor * the executor to wrap - * @param interruptibleWorker if {@code true} the tasks submitted to the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} will + * @param interruptibleWorker if {@code true}, the tasks submitted to the {@link io.reactivex.rxjava3.core.Scheduler.Worker Scheduler.Worker} will * be interrupted when the task is disposed. - * @param fair if {@code true} tasks submitted to the will be executed by the underlying {@link Executor} one after the other, still + * @param fair if {@code true}, tasks submitted to the {@code Scheduler} or {@code Worker} will be executed by the underlying {@code Executor} one after the other, still * in a FIFO and non-overlapping manner, but allows interleaving with other tasks submitted to the underlying {@code Executor}. * If {@code false}, the underlying FIFO scheme will execute as many tasks as it can before giving up the underlying {@code Executor} thread. - * @return the new Scheduler wrapping the Executor + * @return the new {@code Scheduler} wrapping the {@code Executor} * @since 3.0.0 */ @NonNull public static Scheduler from(@NonNull Executor executor, boolean interruptibleWorker, boolean fair) { - return new ExecutorScheduler(executor, interruptibleWorker, fair); + return RxJavaPlugins.createExecutorScheduler(executor, interruptibleWorker, fair); } /** - * Shuts down the standard Schedulers. + * Shuts down the standard {@link Scheduler}s. *

The operation is idempotent and thread-safe. */ public static void shutdown() { @@ -504,11 +570,10 @@ public static void shutdown() { newThread().shutdown(); single().shutdown(); trampoline().shutdown(); - SchedulerPoolFactory.shutdown(); } /** - * Starts the standard Schedulers. + * Starts the standard {@link Scheduler}s. *

The operation is idempotent and thread-safe. */ public static void start() { @@ -517,7 +582,6 @@ public static void start() { newThread().start(); single().start(); trampoline().start(); - SchedulerPoolFactory.start(); } static final class IOTask implements Supplier { diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/TestScheduler.java b/src/main/java/io/reactivex/rxjava3/schedulers/TestScheduler.java index 3e056652838..33aca58a489 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/TestScheduler.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/TestScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,20 +15,28 @@ import java.util.Queue; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; -import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.Scheduler; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * A special, non thread-safe scheduler for testing operators that require * a scheduler without introducing real concurrency and allows manually advancing * a virtual time. + *

+ * By default, the tasks submitted via the various {@code schedule} methods are not + * wrapped by the {@link RxJavaPlugins#onSchedule(Runnable)} hook. To enable this behavior, + * create a {@code TestScheduler} via {@link #TestScheduler(boolean)} or {@link #TestScheduler(long, TimeUnit, boolean)}. */ public final class TestScheduler extends Scheduler { /** The ordered queue for the runnable tasks. */ final Queue queue = new PriorityBlockingQueue<>(11); + /** Use the {@link RxJavaPlugins#onSchedule(Runnable)} hook when scheduling tasks. */ + final boolean useOnScheduleHook; /** The per-scheduler global order counter. */ long counter; // Storing time in nanoseconds internally. @@ -38,7 +46,20 @@ public final class TestScheduler extends Scheduler { * Creates a new TestScheduler with initial virtual time of zero. */ public TestScheduler() { - // No-op. + this(false); + } + + /** + * Creates a new TestScheduler with the option to use the + * {@link RxJavaPlugins#onSchedule(Runnable)} hook when scheduling tasks. + *

History: 3.0.10 - experimental + * @param useOnScheduleHook if {@code true}, the tasks submitted to this + * TestScheduler is wrapped via the + * {@link RxJavaPlugins#onSchedule(Runnable)} hook + * @since 3.1.0 + */ + public TestScheduler(boolean useOnScheduleHook) { + this.useOnScheduleHook = useOnScheduleHook; } /** @@ -50,7 +71,26 @@ public TestScheduler() { * the units of time that {@code delayTime} is expressed in */ public TestScheduler(long delayTime, TimeUnit unit) { + this(delayTime, unit, false); + } + + /** + * Creates a new TestScheduler with the specified initial virtual time + * and with the option to use the + * {@link RxJavaPlugins#onSchedule(Runnable)} hook when scheduling tasks. + *

History: 3.0.10 - experimental + * @param delayTime + * the point in time to move the Scheduler's clock to + * @param unit + * the units of time that {@code delayTime} is expressed in + * @param useOnScheduleHook if {@code true}, the tasks submitted to this + * TestScheduler is wrapped via the + * {@link RxJavaPlugins#onSchedule(Runnable)} hook + * @since 3.1.0 + */ + public TestScheduler(long delayTime, TimeUnit unit, boolean useOnScheduleHook) { time = unit.toNanos(delayTime); + this.useOnScheduleHook = useOnScheduleHook; } static final class TimedRunnable implements Comparable { @@ -163,10 +203,13 @@ public Disposable schedule(@NonNull Runnable run, long delayTime, @NonNull TimeU if (disposed) { return EmptyDisposable.INSTANCE; } + if (useOnScheduleHook) { + run = RxJavaPlugins.onSchedule(run); + } final TimedRunnable timedAction = new TimedRunnable(this, time + unit.toNanos(delayTime), run, counter++); queue.add(timedAction); - return Disposable.fromRunnable(new QueueRemove(timedAction)); + return new QueueRemove(timedAction); } @NonNull @@ -175,9 +218,12 @@ public Disposable schedule(@NonNull Runnable run) { if (disposed) { return EmptyDisposable.INSTANCE; } + if (useOnScheduleHook) { + run = RxJavaPlugins.onSchedule(run); + } final TimedRunnable timedAction = new TimedRunnable(this, 0, run, counter++); queue.add(timedAction); - return Disposable.fromRunnable(new QueueRemove(timedAction)); + return new QueueRemove(timedAction); } @Override @@ -185,16 +231,25 @@ public long now(@NonNull TimeUnit unit) { return TestScheduler.this.now(unit); } - final class QueueRemove implements Runnable { - final TimedRunnable timedAction; + final class QueueRemove extends AtomicReference implements Disposable { + + private static final long serialVersionUID = -7874968252110604360L; QueueRemove(TimedRunnable timedAction) { - this.timedAction = timedAction; + this.lazySet(timedAction); + } + + @Override + public void dispose() { + TimedRunnable tr = getAndSet(null); + if (tr != null) { + queue.remove(tr); + } } @Override - public void run() { - queue.remove(timedAction); + public boolean isDisposed() { + return get() == null; } } } diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java b/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java index a7b6cc46e7c..3ef19409843 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/package-info.java b/src/main/java/io/reactivex/rxjava3/schedulers/package-info.java index 4bbd9e0da2f..1f96d0fd2ab 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/package-info.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + /** * Contains notably the factory class of {@link io.reactivex.rxjava3.schedulers.Schedulers Schedulers} providing methods for * retrieving the standard scheduler instances, the {@link io.reactivex.rxjava3.schedulers.TestScheduler TestScheduler} for testing flows diff --git a/src/main/java/io/reactivex/rxjava3/subjects/AsyncSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/AsyncSubject.java index cfeafcd4a8d..dd4957fd399 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/AsyncSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/AsyncSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/BehaviorSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/BehaviorSubject.java index abc51887f80..2b19ecdd265 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/BehaviorSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/BehaviorSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ * Subject that emits the most recent item it has observed and all subsequent observed items to each subscribed * {@link Observer}. *

- * + * *

* This subject does not have a public constructor by design; a new empty instance of this * {@code BehaviorSubject} can be created via the {@link #create()} method and @@ -59,9 +59,9 @@ * * TestObserver<Integer> to1 = observable.test(); * - * observable.onNext(1); + * subject.onNext(1); * // this will "clear" the cache - * observable.onNext(EMPTY); + * subject.onNext(EMPTY); * * TestObserver<Integer> to2 = observable.test(); * @@ -151,7 +151,7 @@ public final class BehaviorSubject extends Subject { final AtomicReference value; - final AtomicReference[]> subscribers; + final AtomicReference[]> observers; @SuppressWarnings("rawtypes") static final BehaviorDisposable[] EMPTY = new BehaviorDisposable[0]; @@ -208,7 +208,7 @@ public static BehaviorSubject create() { this.lock = new ReentrantReadWriteLock(); this.readLock = lock.readLock(); this.writeLock = lock.writeLock(); - this.subscribers = new AtomicReference<>(EMPTY); + this.observers = new AtomicReference<>(EMPTY); this.value = new AtomicReference<>(defaultValue); this.terminalEvent = new AtomicReference<>(); } @@ -249,7 +249,7 @@ public void onNext(T t) { } Object o = NotificationLite.next(t); setCurrent(o); - for (BehaviorDisposable bs : subscribers.get()) { + for (BehaviorDisposable bs : observers.get()) { bs.emitNext(o, index); } } @@ -281,12 +281,12 @@ public void onComplete() { @Override @CheckReturnValue public boolean hasObservers() { - return subscribers.get().length != 0; + return observers.get().length != 0; } @CheckReturnValue /* test support*/ int subscriberCount() { - return subscribers.get().length; + return observers.get().length; } @Override @@ -342,7 +342,7 @@ public boolean hasValue() { boolean add(BehaviorDisposable rs) { for (;;) { - BehaviorDisposable[] a = subscribers.get(); + BehaviorDisposable[] a = observers.get(); if (a == TERMINATED) { return false; } @@ -351,7 +351,7 @@ boolean add(BehaviorDisposable rs) { BehaviorDisposable[] b = new BehaviorDisposable[len + 1]; System.arraycopy(a, 0, b, 0, len); b[len] = rs; - if (subscribers.compareAndSet(a, b)) { + if (observers.compareAndSet(a, b)) { return true; } } @@ -360,7 +360,7 @@ boolean add(BehaviorDisposable rs) { @SuppressWarnings("unchecked") void remove(BehaviorDisposable rs) { for (;;) { - BehaviorDisposable[] a = subscribers.get(); + BehaviorDisposable[] a = observers.get(); int len = a.length; if (len == 0) { return; @@ -384,7 +384,7 @@ void remove(BehaviorDisposable rs) { System.arraycopy(a, 0, b, 0, j); System.arraycopy(a, j + 1, b, j, len - j - 1); } - if (subscribers.compareAndSet(a, b)) { + if (observers.compareAndSet(a, b)) { return; } } @@ -393,13 +393,9 @@ void remove(BehaviorDisposable rs) { @SuppressWarnings("unchecked") BehaviorDisposable[] terminate(Object terminalValue) { - BehaviorDisposable[] a = subscribers.getAndSet(TERMINATED); - if (a != TERMINATED) { - // either this or atomics with lots of allocation - setCurrent(terminalValue); - } + setCurrent(terminalValue); - return a; + return observers.getAndSet(TERMINATED); } void setCurrent(Object o) { diff --git a/src/main/java/io/reactivex/rxjava3/subjects/CompletableSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/CompletableSubject.java index 9753d276a11..57be7dbced4 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/CompletableSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/CompletableSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/MaybeSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/MaybeSubject.java index f06d8c1aae2..39dbb78d9c5 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/MaybeSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/MaybeSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/PublishSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/PublishSubject.java index 2c3a8478322..6c2d5ac0336 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/PublishSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/PublishSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/ReplaySubject.java b/src/main/java/io/reactivex/rxjava3/subjects/ReplaySubject.java index a956035c3d3..e103594ba50 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/ReplaySubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/ReplaySubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -335,15 +335,13 @@ protected void subscribeActual(Observer observer) { ReplayDisposable rs = new ReplayDisposable<>(observer, this); observer.onSubscribe(rs); - if (!rs.cancelled) { - if (add(rs)) { - if (rs.cancelled) { - remove(rs); - return; - } + if (add(rs)) { + if (rs.cancelled) { + remove(rs); + return; } - buffer.replay(rs); } + buffer.replay(rs); } @Override @@ -571,10 +569,8 @@ void remove(ReplayDisposable rs) { @SuppressWarnings("unchecked") ReplayDisposable[] terminate(Object terminalValue) { - if (buffer.compareAndSet(null, terminalValue)) { - return observers.getAndSet(TERMINATED); - } - return TERMINATED; + buffer.compareAndSet(null, terminalValue); + return observers.getAndSet(TERMINATED); } /** @@ -656,8 +652,6 @@ static final class UnboundedReplayBuffer final List buffer; - volatile boolean done; - volatile int size; UnboundedReplayBuffer(int capacityHint) { @@ -675,7 +669,6 @@ public void addFinal(Object notificationLite) { buffer.add(notificationLite); trimHead(); size++; - done = true; } @Override @@ -776,20 +769,17 @@ public void replay(ReplayDisposable rs) { Object o = b.get(index); - if (done) { - if (index + 1 == s) { - s = size; - if (index + 1 == s) { - if (NotificationLite.isComplete(o)) { - a.onComplete(); - } else { - a.onError(NotificationLite.getError(o)); - } - rs.index = null; - rs.cancelled = true; - return; - } - } + if (NotificationLite.isComplete(o)) { + a.onComplete(); + rs.index = null; + rs.cancelled = true; + return; + } else + if (NotificationLite.isError(o)) { + a.onError(NotificationLite.getError(o)); + rs.index = null; + rs.cancelled = true; + return; } a.onNext((T)o); @@ -860,8 +850,6 @@ static final class SizeBoundReplayBuffer Node tail; - volatile boolean done; - SizeBoundReplayBuffer(int maxSize) { this.maxSize = maxSize; Node h = new Node<>(null); @@ -899,7 +887,6 @@ public void addFinal(Object notificationLite) { t.lazySet(n); // releases both the tail and size trimHead(); - done = true; } /** @@ -1004,18 +991,17 @@ public void replay(ReplayDisposable rs) { Object o = n.value; - if (done) { - if (n.get() == null) { - - if (NotificationLite.isComplete(o)) { - a.onComplete(); - } else { - a.onError(NotificationLite.getError(o)); - } - rs.index = null; - rs.cancelled = true; - return; - } + if (NotificationLite.isComplete(o)) { + a.onComplete(); + rs.index = null; + rs.cancelled = true; + return; + } else + if (NotificationLite.isError(o)) { + a.onError(NotificationLite.getError(o)); + rs.index = null; + rs.cancelled = true; + return; } a.onNext((T)o); @@ -1073,8 +1059,6 @@ static final class SizeAndTimeBoundReplayBuffer TimedNode tail; - volatile boolean done; - SizeAndTimeBoundReplayBuffer(int maxSize, long maxAge, TimeUnit unit, Scheduler scheduler) { this.maxSize = maxSize; this.maxAge = maxAge; @@ -1101,10 +1085,6 @@ void trim() { break; } TimedNode next = h.get(); - if (next == null) { - head = h; - break; - } if (next.time > limit) { head = h; @@ -1171,8 +1151,6 @@ public void addFinal(Object notificationLite) { size++; t.lazySet(n); // releases both the tail and size trimFinal(); - - done = true; } /** @@ -1284,11 +1262,6 @@ public void replay(ReplayDisposable rs) { for (;;) { - if (rs.cancelled) { - rs.index = null; - return; - } - for (;;) { if (rs.cancelled) { rs.index = null; @@ -1303,18 +1276,17 @@ public void replay(ReplayDisposable rs) { Object o = n.value; - if (done) { - if (n.get() == null) { - - if (NotificationLite.isComplete(o)) { - a.onComplete(); - } else { - a.onError(NotificationLite.getError(o)); - } - rs.index = null; - rs.cancelled = true; - return; - } + if (NotificationLite.isComplete(o)) { + a.onComplete(); + rs.index = null; + rs.cancelled = true; + return; + } else + if (NotificationLite.isError(o)) { + a.onError(NotificationLite.getError(o)); + rs.index = null; + rs.cancelled = true; + return; } a.onNext((T)o); @@ -1322,10 +1294,6 @@ public void replay(ReplayDisposable rs) { index = n; } - if (index.get() != null) { - continue; - } - rs.index = index; missed = rs.addAndGet(-missed); diff --git a/src/main/java/io/reactivex/rxjava3/subjects/SerializedSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/SerializedSubject.java index 137cefc8953..09a45b1da28 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/SerializedSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/SerializedSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/SingleSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/SingleSubject.java index 6f8f8b6f353..7559f0329d9 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/SingleSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/SingleSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/Subject.java b/src/main/java/io/reactivex/rxjava3/subjects/Subject.java index 35d26d49b51..b76a15da33c 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/Subject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/Subject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subjects/UnicastSubject.java b/src/main/java/io/reactivex/rxjava3/subjects/UnicastSubject.java index 63afa9c335f..3092dc73c01 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/UnicastSubject.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/UnicastSubject.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,10 +21,10 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; import io.reactivex.rxjava3.internal.functions.*; -import io.reactivex.rxjava3.internal.fuseable.SimpleQueue; import io.reactivex.rxjava3.internal.observers.BasicIntQueueDisposable; -import io.reactivex.rxjava3.internal.queue.SpscLinkedArrayQueue; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.SimpleQueue; +import io.reactivex.rxjava3.operators.SpscLinkedArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** diff --git a/src/main/java/io/reactivex/rxjava3/subjects/package-info.java b/src/main/java/io/reactivex/rxjava3/subjects/package-info.java index 88fde8391df..a2736d7eee5 100644 --- a/src/main/java/io/reactivex/rxjava3/subjects/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/subjects/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** @@ -21,7 +18,8 @@ *

* Available subject classes with their respective base classes and consumer interfaces: *
- *

The available observer types.
Reactive typeBase interfaceSimpleDisposableResource
{@link io.reactivex.rxjava3.core.Observable Observable}
+ *
+ * * * *
The available subject classes with their respective base classes and consumer interfaces.
Subject typeBase classConsumer interface
{@link io.reactivex.rxjava3.subjects.Subject Subject} diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/DefaultSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/DefaultSubscriber.java index 6a936eb8d97..9f8385b5869 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/DefaultSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/DefaultSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/DisposableSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/DisposableSubscriber.java index 566b0097f79..a3212830182 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/DisposableSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/DisposableSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/ResourceSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/ResourceSubscriber.java index 7d9411048a1..95dccfd2b10 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/ResourceSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/ResourceSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/SafeSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/SafeSubscriber.java index 0db19796fa6..f66c34b9b97 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/SafeSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/SafeSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.subscribers; import org.reactivestreams.*; @@ -27,7 +28,7 @@ * * @param the value type */ -public final class SafeSubscriber implements FlowableSubscriber, Subscription { +public final class SafeSubscriber<@NonNull T> implements FlowableSubscriber, Subscription { /** The actual Subscriber. */ final Subscriber downstream; /** The subscription. */ diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/SerializedSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/SerializedSubscriber.java index 9698d97e210..1ea8b4021a7 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/SerializedSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/SerializedSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.subscribers; import org.reactivestreams.*; diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/TestSubscriber.java b/src/main/java/io/reactivex/rxjava3/subscribers/TestSubscriber.java index cbc9d103202..1d96e7cfd36 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/TestSubscriber.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/TestSubscriber.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.subscribers; import java.util.concurrent.atomic.*; @@ -179,15 +180,16 @@ public void onError(@NonNull Throwable t) { if (!checkSubscriptionOnce) { checkSubscriptionOnce = true; if (upstream.get() == null) { - errors.add(new NullPointerException("onSubscribe not called in proper order")); + errors.add(new IllegalStateException("onSubscribe not called in proper order")); } } try { lastThread = Thread.currentThread(); - errors.add(t); if (t == null) { - errors.add(new IllegalStateException("onError received a null Throwable")); + errors.add(new NullPointerException("onError received a null Throwable")); + } else { + errors.add(t); } downstream.onError(t); diff --git a/src/main/java/io/reactivex/rxjava3/subscribers/package-info.java b/src/main/java/io/reactivex/rxjava3/subscribers/package-info.java index 348792062ae..592aea185b8 100644 --- a/src/main/java/io/reactivex/rxjava3/subscribers/package-info.java +++ b/src/main/java/io/reactivex/rxjava3/subscribers/package-info.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ /** diff --git a/src/main/module/module-info.java b/src/main/module/module-info.java new file mode 100644 index 00000000000..4bed327f1a7 --- /dev/null +++ b/src/main/module/module-info.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +module io.reactivex.rxjava3 { + exports io.reactivex.rxjava3.annotations; + exports io.reactivex.rxjava3.core; + exports io.reactivex.rxjava3.disposables; + exports io.reactivex.rxjava3.exceptions; + exports io.reactivex.rxjava3.flowables; + exports io.reactivex.rxjava3.functions; + exports io.reactivex.rxjava3.observables; + exports io.reactivex.rxjava3.observers; + exports io.reactivex.rxjava3.operators; + exports io.reactivex.rxjava3.parallel; + exports io.reactivex.rxjava3.plugins; + exports io.reactivex.rxjava3.processors; + exports io.reactivex.rxjava3.schedulers; + exports io.reactivex.rxjava3.subjects; + exports io.reactivex.rxjava3.subscribers; + + requires transitive org.reactivestreams; +} \ No newline at end of file diff --git a/src/test/java/io/reactivex/rxjava3/completable/CapturingUncaughtExceptionHandler.java b/src/test/java/io/reactivex/rxjava3/completable/CapturingUncaughtExceptionHandler.java index 66738a55130..8379925bee4 100644 --- a/src/test/java/io/reactivex/rxjava3/completable/CapturingUncaughtExceptionHandler.java +++ b/src/test/java/io/reactivex/rxjava3/completable/CapturingUncaughtExceptionHandler.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.completable; diff --git a/src/test/java/io/reactivex/rxjava3/completable/CompletableRetryTest.java b/src/test/java/io/reactivex/rxjava3/completable/CompletableRetryTest.java index c805f68c6fa..3d3ad659688 100644 --- a/src/test/java/io/reactivex/rxjava3/completable/CompletableRetryTest.java +++ b/src/test/java/io/reactivex/rxjava3/completable/CompletableRetryTest.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2017-present, RxJava Contributors. +/* + * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at diff --git a/src/test/java/io/reactivex/rxjava3/completable/CompletableTest.java b/src/test/java/io/reactivex/rxjava3/completable/CompletableTest.java index 904a31701ae..9f64b81d120 100644 --- a/src/test/java/io/reactivex/rxjava3/completable/CompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/completable/CompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/completable/CompletableTimerTest.java b/src/test/java/io/reactivex/rxjava3/completable/CompletableTimerTest.java index 17f1e7beaef..cad1780eb6a 100644 --- a/src/test/java/io/reactivex/rxjava3/completable/CompletableTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/completable/CompletableTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/core/BackpressureEnumTest.java b/src/test/java/io/reactivex/rxjava3/core/BackpressureEnumTest.java index 583899167db..e007bfe8ef1 100644 --- a/src/test/java/io/reactivex/rxjava3/core/BackpressureEnumTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/BackpressureEnumTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/core/ConverterTest.java b/src/test/java/io/reactivex/rxjava3/core/ConverterTest.java index 68006e3c643..1d0ddd5e40b 100644 --- a/src/test/java/io/reactivex/rxjava3/core/ConverterTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/ConverterTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/core/DisposeTaskTest.java b/src/test/java/io/reactivex/rxjava3/core/DisposeTaskTest.java new file mode 100644 index 00000000000..d429b588f73 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/core/DisposeTaskTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.core; + +import static org.junit.Assert.fail; +import static org.testng.Assert.assertTrue; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Scheduler.DisposeTask; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class DisposeTaskTest extends RxJavaTest { + + @Test + public void runnableThrows() throws Throwable { + TestHelper.withErrorTracking(errors -> { + + Scheduler.Worker worker = Schedulers.single().createWorker(); + + DisposeTask task = new DisposeTask(() -> { + throw new TestException(); + }, worker); + + try { + task.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + assertTrue(worker.isDisposed()); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/core/NotificationTest.java b/src/test/java/io/reactivex/rxjava3/core/NotificationTest.java index 1c1a6adf597..b26262c15c7 100644 --- a/src/test/java/io/reactivex/rxjava3/core/NotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/NotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -42,10 +42,21 @@ public void valueOfOnCompleteIsNull() { public void notEqualsToObject() { Notification n1 = Notification.createOnNext(0); assertNotEquals(0, n1); + assertNotEquals(n1, 0); Notification n2 = Notification.createOnError(new TestException()); assertNotEquals(0, n2); + assertNotEquals(n2, 0); Notification n3 = Notification.createOnComplete(); assertNotEquals(0, n3); + assertNotEquals(n3, 0); + } + + @Test + public void twoEqual() { + Notification n1 = Notification.createOnNext(0); + Notification n2 = Notification.createOnNext(0); + assertEquals(n1, n2); + assertEquals(n2, n1); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/core/PeriodicDirectTaskTest.java b/src/test/java/io/reactivex/rxjava3/core/PeriodicDirectTaskTest.java new file mode 100644 index 00000000000..077171acdb9 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/core/PeriodicDirectTaskTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.core; + +import static org.junit.Assert.fail; +import static org.testng.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Scheduler.PeriodicDirectTask; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class PeriodicDirectTaskTest extends RxJavaTest { + + @Test + public void runnableThrows() { + List errors = TestHelper.trackPluginErrors(); + try { + Scheduler.Worker worker = Schedulers.single().createWorker(); + + PeriodicDirectTask task = new PeriodicDirectTask(() -> { + throw new TestException(); + }, worker); + + try { + task.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + assertTrue(worker.isDisposed()); + + task.run(); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/core/Retry.java b/src/test/java/io/reactivex/rxjava3/core/Retry.java index a738e0e3c78..5d543afb1c2 100644 --- a/src/test/java/io/reactivex/rxjava3/core/Retry.java +++ b/src/test/java/io/reactivex/rxjava3/core/Retry.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -75,4 +75,4 @@ public Statement apply(Statement base, Description description) { private Statement statement(final Statement base, final Description description) { return new RetryStatement(base, description); } -} \ No newline at end of file +} diff --git a/src/test/java/io/reactivex/rxjava3/core/RxJavaTest.java b/src/test/java/io/reactivex/rxjava3/core/RxJavaTest.java index d903a87f0c9..1e6d9fd33d6 100644 --- a/src/test/java/io/reactivex/rxjava3/core/RxJavaTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/RxJavaTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.core; import java.util.concurrent.TimeUnit; @@ -20,9 +18,13 @@ import org.junit.*; import org.junit.rules.Timeout; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverableRule; + public abstract class RxJavaTest { @Rule public Timeout globalTimeout = new Timeout(5, TimeUnit.MINUTES); + @Rule + public final SuppressUndeliverableRule suppressUndeliverableRule = new SuppressUndeliverableRule(); /** * Announce creates a log print preventing Travis CI from killing the build. diff --git a/src/test/java/io/reactivex/rxjava3/core/SchedulerTest.java b/src/test/java/io/reactivex/rxjava3/core/SchedulerTest.java new file mode 100644 index 00000000000..bbb36f15948 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/core/SchedulerTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +public class SchedulerTest { + private static final String DRIFT_USE_NANOTIME = "rx3.scheduler.use-nanotime"; + + @After + public void cleanup() { + // reset value to default in order to not influence other tests + Scheduler.IS_DRIFT_USE_NANOTIME = false; + } + + @Test + public void driftUseNanoTimeNotSetByDefault() { + assertFalse(Scheduler.IS_DRIFT_USE_NANOTIME); + assertFalse(Boolean.getBoolean(DRIFT_USE_NANOTIME)); + } + + @Test + public void computeNow_currentTimeMillis() { + TimeUnit unit = TimeUnit.MILLISECONDS; + assertTrue(isInRange(System.currentTimeMillis(), Scheduler.computeNow(unit), unit, 250, TimeUnit.MILLISECONDS)); + } + + @Test + public void computeNow_nanoTime() { + TimeUnit unit = TimeUnit.NANOSECONDS; + Scheduler.IS_DRIFT_USE_NANOTIME = true; + + assertFalse(isInRange(System.currentTimeMillis(), Scheduler.computeNow(unit), unit, 250, TimeUnit.MILLISECONDS)); + assertTrue(isInRange(System.nanoTime(), Scheduler.computeNow(unit), TimeUnit.NANOSECONDS, 250, TimeUnit.MILLISECONDS)); + } + + private boolean isInRange(long start, long stop, TimeUnit source, long maxDiff, TimeUnit diffUnit) { + long diff = Math.abs(stop - start); + return diffUnit.convert(diff, source) <= maxDiff; + } + + @Test + public void clockDriftCalculation() { + assertEquals(100_000_000L, Scheduler.computeClockDrift(100, "milliseconds")); + + assertEquals(2_000_000_000L, Scheduler.computeClockDrift(2, "seconds")); + + assertEquals(180_000_000_000L, Scheduler.computeClockDrift(3, "minutes")); + + assertEquals(240_000_000_000L, Scheduler.computeClockDrift(4, "random")); + + assertEquals(300_000_000_000L, Scheduler.computeClockDrift(5, null)); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/core/TransformerTest.java b/src/test/java/io/reactivex/rxjava3/core/TransformerTest.java index 20725c80fa6..c672196b605 100644 --- a/src/test/java/io/reactivex/rxjava3/core/TransformerTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/TransformerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java index 06394de7ab9..16ebfcb9a37 100644 --- a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/disposables/CompositeDisposableTest.java b/src/test/java/io/reactivex/rxjava3/disposables/CompositeDisposableTest.java index 73d605c2ccf..3f76d283d7f 100644 --- a/src/test/java/io/reactivex/rxjava3/disposables/CompositeDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/disposables/CompositeDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -290,7 +290,7 @@ public void tryRemoveIfNotIn() { cd.remove(cd1); cd.add(cd2); - cd.remove(cd1); // try removing agian + cd.remove(cd1); // try removing again } @Test(expected = NullPointerException.class) diff --git a/src/test/java/io/reactivex/rxjava3/disposables/DisposableTest.java b/src/test/java/io/reactivex/rxjava3/disposables/DisposableTest.java index b966a1db0f6..e541d404da7 100644 --- a/src/test/java/io/reactivex/rxjava3/disposables/DisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/disposables/DisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/disposables/FutureDisposableTest.java b/src/test/java/io/reactivex/rxjava3/disposables/FutureDisposableTest.java index 3ae97dd3064..544e39ad1b6 100644 --- a/src/test/java/io/reactivex/rxjava3/disposables/FutureDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/disposables/FutureDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/disposables/SequentialDisposableTest.java b/src/test/java/io/reactivex/rxjava3/disposables/SequentialDisposableTest.java index 62248db45eb..30663433013 100644 --- a/src/test/java/io/reactivex/rxjava3/disposables/SequentialDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/disposables/SequentialDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/disposables/SerialDisposableTests.java b/src/test/java/io/reactivex/rxjava3/disposables/SerialDisposableTests.java index aa53f2ecb05..3a2e73582bd 100644 --- a/src/test/java/io/reactivex/rxjava3/disposables/SerialDisposableTests.java +++ b/src/test/java/io/reactivex/rxjava3/disposables/SerialDisposableTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/exceptions/CompositeExceptionTest.java b/src/test/java/io/reactivex/rxjava3/exceptions/CompositeExceptionTest.java index 331a7dce9c0..cc34f62b899 100644 --- a/src/test/java/io/reactivex/rxjava3/exceptions/CompositeExceptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/exceptions/CompositeExceptionTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.exceptions; import static org.junit.Assert.*; @@ -150,7 +148,7 @@ public void compositeExceptionFromTwoDuplicateComposites() { cex.getCause().printStackTrace(); } - /** + /* * This hijacks the Throwable.printStackTrace() output and puts it in a string, where we can look for * "CIRCULAR REFERENCE" (a String added by Throwable.printEnclosedStackTrace) */ diff --git a/src/test/java/io/reactivex/rxjava3/exceptions/ExceptionsTest.java b/src/test/java/io/reactivex/rxjava3/exceptions/ExceptionsTest.java index 3d2e1eeec4a..b6aa0690100 100644 --- a/src/test/java/io/reactivex/rxjava3/exceptions/ExceptionsTest.java +++ b/src/test/java/io/reactivex/rxjava3/exceptions/ExceptionsTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.exceptions; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedExceptionTest.java b/src/test/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedExceptionTest.java index b8a78de7dcb..70ba775bc11 100644 --- a/src/test/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedExceptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/exceptions/OnErrorNotImplementedExceptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/exceptions/TestException.java b/src/test/java/io/reactivex/rxjava3/exceptions/TestException.java index 8618c7df5e3..7bcdd318fd8 100644 --- a/src/test/java/io/reactivex/rxjava3/exceptions/TestException.java +++ b/src/test/java/io/reactivex/rxjava3/exceptions/TestException.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,7 +14,7 @@ package io.reactivex.rxjava3.exceptions; /** - * Exception for testing if unchecked expections propagate as-is without confusing with + * Exception for testing if unchecked exceptions propagate as-is without confusing with * other type of common exceptions. */ public final class TestException extends RuntimeException { diff --git a/src/test/java/io/reactivex/rxjava3/flowable/Burst.java b/src/test/java/io/reactivex/rxjava3/flowable/Burst.java index 791ec79a2f5..efa0993042a 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/Burst.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/Burst.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowable; import java.util.*; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableBackpressureTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableBackpressureTests.java index 7d0687dd723..e6b3a02c684 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableBackpressureTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableBackpressureTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.MissingBackpressureException; +import io.reactivex.rxjava3.exceptions.QueueOverflowException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; import io.reactivex.rxjava3.internal.util.BackpressureHelper; @@ -132,7 +132,7 @@ public void mergeSync() { assertEquals(num, ts.values().size()); // either one can starve the other, but neither should be capable of doing more than 5 batches (taking 4.1) // TODO is it possible to make this deterministic rather than one possibly starving the other? - // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algoritms generally take a performance hit + // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algorithms generally take a performance hit assertTrue(c1.get() < Flowable.bufferSize() * 5); assertTrue(c2.get() < Flowable.bufferSize() * 5); } @@ -154,7 +154,7 @@ public void mergeAsync() { assertEquals(num, ts.values().size()); // either one can starve the other, but neither should be capable of doing more than 5 batches (taking 4.1) // TODO is it possible to make this deterministic rather than one possibly starving the other? - // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algoritms generally take a performance hit + // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algorithms generally take a performance hit int max = Flowable.bufferSize() * 7; assertTrue("" + c1.get() + " >= " + max, c1.get() < max); assertTrue("" + c2.get() + " >= " + max, c2.get() < max); @@ -206,7 +206,7 @@ public void mergeAsyncThenObserveOn() { assertEquals(num, ts.values().size()); // either one can starve the other, but neither should be capable of doing more than 5 batches (taking 4.1) // TODO is it possible to make this deterministic rather than one possibly starving the other? - // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algoritms generally take a performance hit + // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" algorithms generally take a performance hit // akarnokd => run this in a loop over 10k times and never saw values get as high as 7*SIZE, but since observeOn delays the unsubscription non-deterministically, the test will remain unreliable assertTrue(c1.get() < Flowable.bufferSize() * 7); assertTrue(c2.get() < Flowable.bufferSize() * 7); @@ -475,7 +475,7 @@ public Integer apply(Integer v) { int vc = ts.values().size(); assertTrue("10 < " + vc, vc <= 10); - ts.assertError(MissingBackpressureException.class); + ts.assertError(QueueOverflowException.class); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCollectTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCollectTest.java index ea93877cdcf..70779959829 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCollectTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCollectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCombineLatestTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCombineLatestTests.java index 3adac790ae0..107c5e583f4 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCombineLatestTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCombineLatestTests.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowable; import org.junit.Test; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableConcatTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableConcatTests.java index 5d54f9df5f3..5efb4195e62 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableConcatTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableConcatTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowable; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableConversionTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableConversionTest.java index a579a82ae70..7079f833f2a 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableConversionTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableConversionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCovarianceTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCovarianceTest.java index ae50092ce9e..9d7ca31319b 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableCovarianceTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableCovarianceTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.flowable; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoAfterNextTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoAfterNextTest.java index 58f21b10d31..eb6878edbdf 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoAfterNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoAfterNextTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowable; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoOnTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoOnTest.java index b1b12c55772..f4ff588d53f 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableDoOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableErrorHandlingTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableErrorHandlingTests.java index df123ee3044..e15c7a1dec8 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableErrorHandlingTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableErrorHandlingTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStream.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStream.java index 861d67c68d0..2428d6cb049 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStream.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStreamTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStreamTest.java index 8965376b8ad..dd38b88afce 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableEventStreamTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.flowable; diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableFuseableTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableFuseableTest.java index 02fa0e5be70..7bf54e8aba0 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableFuseableTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableFuseableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.flowable; import java.util.Arrays; @@ -17,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.TestHelper; public class FlowableFuseableTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableGroupByTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableGroupByTests.java index b7e4edcab4c..e37934eadd3 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableGroupByTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableGroupByTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableMergeTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableMergeTests.java index e200cd0f12b..d549c3fbb40 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableMergeTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableMergeTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableNotificationTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableNotificationTest.java index 2e2b95bbd87..08d1994fcb6 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableNotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableNotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableNullTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableNullTests.java index b08d6824e51..748a12d3c33 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableNullTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableNullTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableReduceTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableReduceTests.java index 1e6abe83c9d..5dd3c28cb25 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableReduceTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableReduceTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableStartWithTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableStartWithTests.java index 7ac13a4bd6e..28549b1a90f 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableStartWithTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableStartWithTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableSubscriberTest.java index 2a27aaada08..b1eb9ce600f 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableTests.java index 7662f3ebdfb..1fa80701be2 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleLastTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleLastTests.java index c6db747cf1a..c5c858c4303 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleLastTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleLastTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,10 +13,14 @@ package io.reactivex.rxjava3.flowable; -import static org.mockito.Mockito.inOrder; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; import java.util.concurrent.TimeUnit; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Action; import org.junit.Test; import org.mockito.InOrder; import org.reactivestreams.Subscriber; @@ -28,6 +32,72 @@ public class FlowableThrottleLastTests extends RxJavaTest { + @Test + public void throttleWithDroppedCallbackException() throws Throwable { + Subscriber subscriber = TestHelper.mockSubscriber(); + Action whenDisposed = mock(Action.class); + + TestScheduler s = new TestScheduler(); + PublishProcessor o = PublishProcessor.create(); + o.doOnCancel(whenDisposed) + .throttleLast(500, TimeUnit.MILLISECONDS, s, e-> { + if (e == 1) { + throw new TestException("forced"); + } + }) + .subscribe(subscriber); + + // send events with simulated time increments + s.advanceTimeTo(0, TimeUnit.MILLISECONDS); + o.onNext(1); // skip + o.onNext(2); // deliver + s.advanceTimeTo(501, TimeUnit.MILLISECONDS); + + InOrder inOrder = inOrder(subscriber); + inOrder.verify(subscriber).onError(any(TestException.class)); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void throttleWithDroppedCallback() { + Subscriber subscriber = TestHelper.mockSubscriber(); + Observer dropCallbackObserver = TestHelper.mockObserver(); + + TestScheduler s = new TestScheduler(); + PublishProcessor o = PublishProcessor.create(); + o.throttleLast(500, TimeUnit.MILLISECONDS, s, dropCallbackObserver::onNext).subscribe(subscriber); + + // send events with simulated time increments + s.advanceTimeTo(0, TimeUnit.MILLISECONDS); + o.onNext(1); // skip + o.onNext(2); // deliver + s.advanceTimeTo(501, TimeUnit.MILLISECONDS); + o.onNext(3); // skip + s.advanceTimeTo(600, TimeUnit.MILLISECONDS); + o.onNext(4); // skip + s.advanceTimeTo(700, TimeUnit.MILLISECONDS); + o.onNext(5); // skip + o.onNext(6); // deliver + s.advanceTimeTo(1001, TimeUnit.MILLISECONDS); + o.onNext(7); // deliver + s.advanceTimeTo(1501, TimeUnit.MILLISECONDS); + o.onComplete(); + + InOrder inOrder = inOrder(subscriber); + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + dropCallbackOrder.verify(dropCallbackObserver).onNext(1); + inOrder.verify(subscriber).onNext(2); + dropCallbackOrder.verify(dropCallbackObserver).onNext(3); + dropCallbackOrder.verify(dropCallbackObserver).onNext(4); + dropCallbackOrder.verify(dropCallbackObserver).onNext(5); + inOrder.verify(subscriber).onNext(6); + inOrder.verify(subscriber).onNext(7); + inOrder.verify(subscriber).onComplete(); + inOrder.verifyNoMoreInteractions(); + dropCallbackOrder.verifyNoMoreInteractions(); + } + @Test public void throttle() { Subscriber subscriber = TestHelper.mockSubscriber(); diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleWithTimeoutTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleWithTimeoutTests.java index f84d27a00d8..be94bf9d38c 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleWithTimeoutTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableThrottleWithTimeoutTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableWindowTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableWindowTests.java index f96a010728d..2ba648282fa 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableWindowTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableWindowTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/flowable/FlowableZipTests.java b/src/test/java/io/reactivex/rxjava3/flowable/FlowableZipTests.java index e1b2e2809b0..7f77992bfe3 100644 --- a/src/test/java/io/reactivex/rxjava3/flowable/FlowableZipTests.java +++ b/src/test/java/io/reactivex/rxjava3/flowable/FlowableZipTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/SubscribeWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/SubscribeWithTest.java index e1b858507a0..a24562a8542 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/SubscribeWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/SubscribeWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposableTest.java index 8871cc4e500..c0319dfd3ad 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/disposables/ArrayCompositeDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposableTest.java index 03f54c92189..ab40e7c03ce 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/disposables/DisposableHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/disposables/DisposableHelperTest.java index 0332b025565..a3102ea44f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/disposables/DisposableHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/disposables/DisposableHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposableTest.java index b66f27036ee..1f0d370dcd7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/disposables/EmptyDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.TestHelper; public class EmptyDisposableTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposableTest.java index 0325d005004..1a0070e22de 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/disposables/ListCompositeDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/functions/FunctionsTest.java b/src/test/java/io/reactivex/rxjava3/internal/functions/FunctionsTest.java index 72e188fe997..635fcc4472f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/functions/FunctionsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/functions/FunctionsTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -39,12 +39,12 @@ public void utilityClass() { public void hashSetCallableEnum() { // inlined TestHelper.checkEnum due to access restrictions try { - Method m = Functions.HashSetCallable.class.getMethod("values"); + Method m = Functions.HashSetSupplier.class.getMethod("values"); m.setAccessible(true); - Method e = Functions.HashSetCallable.class.getMethod("valueOf", String.class); + Method e = Functions.HashSetSupplier.class.getMethod("valueOf", String.class); e.setAccessible(true); - for (Enum o : (Enum[])m.invoke(null)) { + for (Enum o : (Enum[])m.invoke(null)) { assertSame(o, e.invoke(null, o.name())); } diff --git a/src/test/java/io/reactivex/rxjava3/internal/functions/ObjectHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/functions/ObjectHelperTest.java index 16c182061d7..fb7e912da4d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/functions/ObjectHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/functions/ObjectHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java index e87bfd315af..67144abea29 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,6 +25,16 @@ public void offer() { TestHelper.assertNoOffer(new CancellableQueueFuseable<>()); } + @Test + public void pollClear() throws Throwable { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + + assertNull(qs.poll()); + + qs.clear(); + assertNull(qs.poll()); + } + @Test public void cancel() { CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CollectWithCollectorTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CollectWithCollectorTckTest.java index 99fb2dcff94..4745b9c8096 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CollectWithCollectorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CollectWithCollectorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStageTest.java index 3519cc54541..6e9bf78e1d9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableToCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableToCompletionStageTest.java index 91fdfb9cde6..8917b1c6754 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableToCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/CompletableToCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0HTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0HTckTest.java index 57365f58578..e499ac1b9a5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0HTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0HTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0TckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0TckTest.java index 232ded7321f..fa33b67ebfa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0TckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream0TckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1HTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1HTckTest.java index aa65a19ca7b..ee1a27b5483 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1HTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1HTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1TckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1TckTest.java index 20e99b1ec14..21492d61b88 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1TckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream1TckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2HTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2HTckTest.java index 0c06e4de40b..14e44d69eee 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2HTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2HTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2TckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2TckTest.java index d799a720c9a..c42e6f7a80e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2TckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlatMapStream2TckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableBlockingStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableBlockingStreamTest.java index 2cf932f40ed..be49e2ed11f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableBlockingStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableBlockingStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorTest.java index ecef7665e00..3a8a1d5b192 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableCollectWithCollectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStreamTest.java index 548a66a7098..c865d35a526 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFlatMapStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -274,7 +274,7 @@ protected void subscribeActual(Subscriber s) { } .flatMapStream(v -> Stream.of(1, 2), 1) .test(0) - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); TestHelper.assertUndeliverable(errors, 0, TestException.class); }); diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStageTest.java index 8a71bbd9b38..aebeea58b60 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromOptionalTest.java index 6676bcee611..743dc0f5735 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStreamTest.java index 7d5f7a0a74e..57a8caf6bf6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableFromStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,9 @@ import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptionalTest.java index 85fc8d75bef..fbffd790011 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableMapOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,10 +23,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.processors.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FlowableMapOptionalTest extends RxJavaTest { @@ -467,4 +468,20 @@ public void boundaryFusedMixedConditional() { .assertFusionMode(QueueFuseable.NONE) .assertResult(2, 4, 6, 8, 10); } + + @Test + public void conditionalFusionNoNPE() { + TestSubscriberEx ts = new TestSubscriberEx<>() + .setInitialFusionMode(QueueFuseable.ANY); + + Flowable.empty() + .observeOn(ImmediateThinScheduler.INSTANCE) + .filter(v -> true) + .mapOptional(Optional::of) + .filter(v -> true) + .subscribe(ts) + ; + + ts.assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrDefaultTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrDefaultTest.java index 882fd83dfb4..d63a81c8ef9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrDefaultTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrDefaultTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrErrorTest.java index c34e4739fa8..763a1e04445 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FlowableStageSubscriberOrErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromCompletionStageTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromCompletionStageTckTest.java index 2c48611cd99..6d2e9d21551 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromCompletionStageTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromCompletionStageTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional0TckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional0TckTest.java index 76c1246eb30..ff30aa4b2dc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional0TckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional0TckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional1TckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional1TckTest.java index 27e596d708e..f6b56a582dc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional1TckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromOptional1TckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromStreamTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromStreamTckTest.java index 06f3b02b979..a0995dad39a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromStreamTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/FromStreamTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MapOptionalTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MapOptionalTckTest.java index b7cb4d97259..345159da4a1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MapOptionalTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MapOptionalTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTckTest.java index 94906fdd2f0..55e6778d3f9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTest.java index 8e1e75b8e05..d8377eac603 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,8 +28,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservableTest.java index dd0fb5c2edb..145112987db 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFlattenStreamAsObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,8 +27,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStageTest.java index 90ad2bc6261..552a4afc106 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromOptionalTest.java index 4e09fea0b19..8af5faf5d70 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptionalTest.java index e8b9f2aac30..a8adbcb6f8e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeMapOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeToCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeToCompletionStageTest.java index c6c83e68a3e..12e4ca5f1ea 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeToCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeToCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableBlockingStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableBlockingStreamTest.java index b62bedb6f81..275b38a57b4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableBlockingStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableBlockingStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorTest.java index 923a7dbaa3a..f18f42a3d0c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableCollectWithCollectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStreamTest.java index 8341aa03dd1..5afcfa33ff8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFlatMapStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStageTest.java index 612ab0724b9..2be5ecf510d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromOptionalTest.java index e2e4059e705..5fbeb1f2ff5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStreamTest.java index 6074e54689d..2b943e5338e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableFromStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,8 +26,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.testsupport.*; public class ObservableFromStreamTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptionalTest.java index ba38417b125..1b0a7f0a7d4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableMapOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrDefaultTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrDefaultTest.java index 9b02622c9b8..f652c9b3276 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrDefaultTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrDefaultTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrErrorTest.java index d8e6fbe9185..5646fc3d597 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ObservableStageSubscriberOrErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollectorTest.java index 8e558a00489..9d0fc09f62e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelCollectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -148,6 +148,7 @@ public Set characteristics() { } @Test + @SuppressUndeliverable public void collectorCombinerCrash() { Flowable.range(1, 5) .parallel() diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStreamTest.java index 0f39d4c8421..f1d34491d50 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelFlatMapStreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptionalTest.java index 67cab4087eb..ca7385b7f64 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptionalTest.java index b7cae915684..459b3f884a8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/ParallelMapTryOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTckTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTckTest.java index 509429d4afe..53c42065105 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTest.java index 72dc8fb2393..6e74b423704 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,8 +28,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservableTest.java index 2b3a624d509..2c50634823f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFlattenStreamAsObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,8 +27,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStageTest.java index 7adb3664be0..c62996e5868 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptionalTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptionalTest.java index b8ab17a17c0..56bc5dbae51 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptionalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleMapOptionalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleToCompletionStageTest.java b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleToCompletionStageTest.java index 2560c68ed84..2709b6ee40f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleToCompletionStageTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleToCompletionStageTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserverTest.java index 1764ea6a474..f48d0a574e7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/BasicFuseableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposableTest.java index e5ed0fb605d..d9bf9947460 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/BasicQueueDisposableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserverTest.java index 0b33e6ddfff..3a65016574c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingFirstObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserverTest.java index b9ec5d276bd..0ea5b468ac0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingObserverTest.java index 1a07bdf9073..cbf8b7ce7c5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/BlockingObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserverTest.java index e52ab8c023a..46c4cc44636 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/CallbackCompletableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,7 @@ public final class CallbackCompletableObserverTest extends RxJavaTest { @Test public void emptyActionShouldReportNoCustomOnError() { - CallbackCompletableObserver o = new CallbackCompletableObserver(Functions.EMPTY_ACTION); + CallbackCompletableObserver o = new CallbackCompletableObserver(Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION); assertFalse(o.hasCustomOnError()); } diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/CompletableConsumersTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/CompletableConsumersTest.java new file mode 100644 index 00000000000..eb17ead3db0 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/CompletableConsumersTest.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.CompositeException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subjects.CompletableSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class CompletableConsumersTest implements Consumer, Action { + + final CompositeDisposable composite = new CompositeDisposable(); + + final CompletableSubject processor = CompletableSubject.create(); + + final List events = new ArrayList<>(); + + @Override + public void run() throws Exception { + events.add("OnComplete"); + } + + @Override + public void accept(Object t) throws Exception { + events.add(t); + } + + @Test + public void onErrorNormal() { + + processor.subscribe(this, this, composite); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onComplete(); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList("OnComplete"), events); + + } + + @Test + public void onErrorError() { + + Disposable d = processor.subscribe(this, this, composite); + + assertTrue(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onError(new IOException()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteNormal() { + + processor.subscribe(this, this, composite); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onComplete(); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList("OnComplete"), events); + + } + + @Test + public void onCompleteError() { + + processor.subscribe(this, this, composite); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onError(new IOException()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteDispose() { + + Disposable d = processor.subscribe(this, this, composite); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + assertFalse(d.isDisposed()); + + d.dispose(); + d.dispose(); + + assertTrue(d.isDisposed()); + + assertEquals(0, composite.size()); + + assertFalse(processor.hasObservers()); + } + + @Test + public void onErrorCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + processor.subscribe(this, t -> { + throw new IOException(t); + }, composite); + + processor.onError(new IllegalArgumentException()); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, CompositeException.class); + List inners = TestHelper.compositeList(errors.get(0)); + TestHelper.assertError(inners, 0, IllegalArgumentException.class); + TestHelper.assertError(inners, 1, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onCompleteCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + processor.subscribe(new Action() { + @Override + public void run() throws Exception { + throw new IOException(); + } + }, this, composite); + + processor.onComplete(); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void badSource() { + List errors = TestHelper.trackPluginErrors(); + try { + new Completable() { + @Override + protected void subscribeActual( + CompletableObserver observer) { + observer.onSubscribe(Disposable.empty()); + observer.onComplete(); + + observer.onSubscribe(Disposable.empty()); + observer.onComplete(); + observer.onError(new IOException()); + } + }.subscribe(this, this, composite); + + assertEquals(Arrays.asList("OnComplete"), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserverTest.java index 5e264bc4d7d..f6ebdb498f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/ConsumerSingleObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposableTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposableTest.java new file mode 100644 index 00000000000..19c5b7db273 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarDisposableTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.observers.TestObserver; + +public class DeferredScalarDisposableTest extends RxJavaTest { + + @Test + public void tryDispose() { + TestObserver to = new TestObserver<>(); + + DeferredScalarDisposable d = new DeferredScalarDisposable<>(to); + to.onSubscribe(d); + + assertTrue(d.tryDispose()); + assertFalse(d.tryDispose()); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserverTest.java index e9668c81cea..165de9b4676 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/DeferredScalarObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,8 +22,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserverTest.java index 964301f6e43..294892507b4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/DisposableLambdaObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserverTest.java index e8733263754..c58de8f0f95 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/EmptyCompletableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserverTest.java new file mode 100644 index 00000000000..7499b99ca18 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserverTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.disposables.Disposable; + +public class FutureMultiObserverTest extends RxJavaTest { + + @Test + public void cancelBeforeOnSubscribe() { + FutureMultiObserver f = new FutureMultiObserver<>(); + + assertTrue(f.cancel(true)); + + Disposable d = Disposable.empty(); + + f.onSubscribe(d); + + assertTrue(d.isDisposed()); + } + + @Test + public void onCompleteJustAfterDispose() { + FutureMultiObserver f = new FutureMultiObserver<>(); + Disposable d = Disposable.empty(); + f.onSubscribe(d); + assertTrue(f.cancel(true)); + + f.onComplete(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/FutureObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureObserverTest.java index a4a8f353c2b..8c475eb0383 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/FutureObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,11 +22,9 @@ import org.junit.*; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.subscribers.FutureSubscriber; -import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -157,7 +155,7 @@ public void onSubscribe() throws Exception { @Test public void cancelRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { - final FutureSubscriber fo = new FutureSubscriber<>(); + final FutureObserver fo = new FutureObserver<>(); Runnable r = new Runnable() { @Override @@ -188,7 +186,7 @@ public void onErrorCancelRace() { RxJavaPlugins.setErrorHandler(Functions.emptyConsumer()); try { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { - final FutureSubscriber fo = new FutureSubscriber<>(); + final FutureObserver fo = new FutureObserver<>(); final TestException ex = new TestException(); @@ -218,10 +216,10 @@ public void onCompleteCancelRace() { RxJavaPlugins.setErrorHandler(Functions.emptyConsumer()); try { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { - final FutureSubscriber fo = new FutureSubscriber<>(); + final FutureObserver fo = new FutureObserver<>(); if (i % 3 == 0) { - fo.onSubscribe(new BooleanSubscription()); + fo.onSubscribe(Disposable.empty()); } if (i % 2 == 0) { @@ -288,6 +286,22 @@ public void onCompleteOnError() throws Exception { } } + @Test + public void onNextCompleteOnError() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + fo.onNext(1); + fo.onComplete(); + fo.onError(new TestException("One")); + + assertEquals((Integer)1, fo.get(5, TimeUnit.MILLISECONDS)); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } + @Test public void cancelOnError() throws Exception { List errors = TestHelper.trackPluginErrors(); @@ -364,4 +378,22 @@ public void getTimedOut() throws Exception { assertEquals(timeoutMessage(1, TimeUnit.NANOSECONDS), expected.getMessage()); } } + + @Test + public void cancelOnSubscribeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + final FutureObserver fo = new FutureObserver<>(); + + Runnable r = new Runnable() { + @Override + public void run() { + fo.cancel(false); + } + }; + + Disposable d = Disposable.empty(); + + TestHelper.race(r, () -> fo.onSubscribe(d)); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserverTest.java index eb11be24c3b..db8b414347a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverTest.java new file mode 100644 index 00000000000..549c72534ad --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/InnerQueuedObserverTest.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class InnerQueuedObserverTest extends RxJavaTest { + + @Test + public void dispose() { + TestHelper.checkDisposed(new InnerQueuedObserver<>(null, 1)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/LambdaObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/LambdaObserverTest.java index c19b6ff2dbb..7ce43074191 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/LambdaObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/LambdaObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/MaybeConsumersTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/MaybeConsumersTest.java new file mode 100644 index 00000000000..92b32c000e6 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/MaybeConsumersTest.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.CompositeException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeConsumersTest implements Consumer, Action { + + final CompositeDisposable composite = new CompositeDisposable(); + + final MaybeSubject processor = MaybeSubject.create(); + + final List events = new ArrayList<>(); + + @Override + public void run() throws Exception { + events.add("OnComplete"); + } + + @Override + public void accept(Object t) throws Exception { + events.add(t); + } + + static Disposable subscribeAutoDispose(Maybe source, CompositeDisposable composite, + Consumer onSuccess, Consumer onError, Action onComplete) { + return source.subscribe(onSuccess, onError, onComplete, composite); + } + + @Test + public void onSuccessNormal() { + + Disposable d = subscribeAutoDispose(processor, composite, this, Functions.ON_ERROR_MISSING, () -> { }); + + assertFalse(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onSuccess(1); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList(1), events); + + } + + @Test + public void onErrorNormal() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onSuccess(1); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList(1), events); + + } + + @Test + public void onErrorError() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onError(new IOException()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteNormal() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onComplete(); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList("OnComplete"), events); + + } + + @Test + public void onCompleteError() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onError(new IOException()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteDispose() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + assertFalse(d.isDisposed()); + + d.dispose(); + d.dispose(); + + assertTrue(d.isDisposed()); + + assertEquals(0, composite.size()); + + assertFalse(processor.hasObservers()); + } + + @Test + public void onSuccessCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, new Consumer() { + @Override + public void accept(Object t) throws Exception { + throw new IOException(); + } + }, this, this); + + processor.onSuccess(1); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onErrorCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, new Consumer() { + @Override + public void accept(Throwable t) throws Exception { + throw new IOException(t); + } + }, this); + + processor.onError(new IllegalArgumentException()); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, CompositeException.class); + List inners = TestHelper.compositeList(errors.get(0)); + TestHelper.assertError(inners, 0, IllegalArgumentException.class); + TestHelper.assertError(inners, 1, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onCompleteCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, this, new Action() { + @Override + public void run() throws Exception { + throw new IOException(); + } + }); + + processor.onComplete(); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void badSource() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose( + new Maybe() { + @Override + protected void subscribeActual( + MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + observer.onComplete(); + + observer.onSubscribe(Disposable.empty()); + observer.onSuccess(2); + observer.onComplete(); + observer.onError(new IOException()); + } + }, composite, this, this, this + ); + + assertEquals(Arrays.asList("OnComplete"), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/ObservableConsumersTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/ObservableConsumersTest.java new file mode 100644 index 00000000000..b5d26340e75 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/ObservableConsumersTest.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class ObservableConsumersTest implements Consumer, Action { + + final CompositeDisposable composite = new CompositeDisposable(); + + final PublishSubject processor = PublishSubject.create(); + + final List events = new ArrayList<>(); + + @Override + public void run() throws Exception { + events.add("OnComplete"); + } + + @Override + public void accept(Object t) throws Exception { + events.add(t); + } + + static Disposable subscribeAutoDispose(Observable source, CompositeDisposable composite, + Consumer onNext, Consumer onError, Action onComplete) { + return source.subscribe(onNext, onError, onComplete, composite); + } + + @Test + public void onNextNormal() { + + Disposable d = subscribeAutoDispose(processor, composite, this, Functions.ON_ERROR_MISSING, () -> { }); + + assertFalse(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onErrorNormal() { + + subscribeAutoDispose(processor, composite, this, Functions.ON_ERROR_MISSING, () -> { }); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onErrorError() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onError(new IOException()); + + assertEquals(events.toString(), 1, events.get(0)); + assertTrue(events.toString(), events.get(1) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteNormal() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1, "OnComplete"), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteError() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onError(new IOException()); + + assertEquals(events.toString(), 1, events.get(0)); + assertTrue(events.toString(), events.get(1) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteDispose() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + assertFalse(d.isDisposed()); + + d.dispose(); + d.dispose(); + + assertTrue(d.isDisposed()); + + assertEquals(0, composite.size()); + + assertFalse(processor.hasObservers()); + } + + @Test + public void onNextCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, new Consumer() { + @Override + public void accept(Object t) throws Exception { + throw new IOException(); + } + }, this, this); + + processor.onNext(1); + + assertTrue(errors.toString(), errors.isEmpty()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onNextCrashOnError() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, new Consumer() { + @Override + public void accept(Throwable t) throws Exception { + throw new IOException(t); + } + }, this); + + processor.onError(new IllegalArgumentException()); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, CompositeException.class); + List inners = TestHelper.compositeList(errors.get(0)); + TestHelper.assertError(inners, 0, IllegalArgumentException.class); + TestHelper.assertError(inners, 1, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onNextCrashNoError() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, t -> { + throw new IOException(); + }, Functions.ON_ERROR_MISSING, () -> { }); + + processor.onNext(1); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, OnErrorNotImplementedException.class); + assertTrue(errors.get(0).getCause() instanceof IOException); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onCompleteCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, this, new Action() { + @Override + public void run() throws Exception { + throw new IOException(); + } + }); + + processor.onNext(1); + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void badSource() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose( + new Observable() { + @Override + protected void subscribeActual( + Observer observer) { + observer.onSubscribe(Disposable.empty()); + observer.onNext(1); + observer.onComplete(); + + observer.onSubscribe(Disposable.empty()); + observer.onNext(2); + observer.onComplete(); + observer.onError(new IOException()); + } + }, composite, this, this, this + ); + + assertEquals(Arrays.asList(1, "OnComplete"), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserverTest.java index 9afd31e95f1..eb2523a4662 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,8 +17,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.*; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.testsupport.TestHelper; public class QueueDrainObserverTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/observers/SingleConsumersTest.java b/src/test/java/io/reactivex/rxjava3/internal/observers/SingleConsumersTest.java new file mode 100644 index 00000000000..a840d8f71aa --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/observers/SingleConsumersTest.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.CompositeException; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleConsumersTest implements Consumer { + + final CompositeDisposable composite = new CompositeDisposable(); + + final SingleSubject processor = SingleSubject.create(); + + final List events = new ArrayList<>(); + + @Override + public void accept(Object t) throws Exception { + events.add(t); + } + + static Disposable subscribeAutoDispose(Single source, CompositeDisposable composite, + Consumer onSuccess, Consumer onError) { + return source.subscribe(onSuccess, onError, composite); + } + + @Test + public void onSuccessNormal() { + + Disposable d = subscribeAutoDispose(processor, composite, this, Functions.ON_ERROR_MISSING); + + assertFalse(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onSuccess(1); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList(1), events); + + } + + @Test + public void onErrorNormal() { + + subscribeAutoDispose(processor, composite, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onSuccess(1); + + assertEquals(0, composite.size()); + + assertEquals(Arrays.asList(1), events); + + } + + @Test + public void onErrorError() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this); + + assertTrue(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onError(new IOException()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onSuccessCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, new Consumer() { + @Override + public void accept(Object t) throws Exception { + throw new IOException(); + } + }, this); + + processor.onSuccess(1); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onErrorCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, new Consumer() { + @Override + public void accept(Throwable t) throws Exception { + throw new IOException(t); + } + }); + + processor.onError(new IllegalArgumentException()); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, CompositeException.class); + List inners = TestHelper.compositeList(errors.get(0)); + TestHelper.assertError(inners, 0, IllegalArgumentException.class); + TestHelper.assertError(inners, 1, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void badSource() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose( + new Single() { + @Override + protected void subscribeActual( + SingleObserver observer) { + observer.onSubscribe(Disposable.empty()); + observer.onSuccess(1); + + observer.onSubscribe(Disposable.empty()); + observer.onSuccess(2); + observer.onError(new IOException()); + } + }, composite, this, this + ); + + assertEquals(Arrays.asList(1), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmbTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmbTest.java index 60c69b5f204..0c9971017b6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmbTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAmbTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableTest.java similarity index 96% rename from src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java rename to src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableTest.java index 051dd4e3642..070fa8cb4dd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,7 +27,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.TestHelper; -public class CompletableAndThenCompletableabTest extends RxJavaTest { +public class CompletableAndThenCompletableTest extends RxJavaTest { @Test public void andThenCompletableCompleteComplete() { Completable.complete() @@ -177,4 +177,9 @@ public void run() throws Exception { assertFalse("The second Completable was interrupted!", interrupted[0]); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeCompletable(c -> c.andThen(c)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenTest.java index b72fda422ce..943d44b9f27 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAwaitTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAwaitTest.java index b7d6d61ea31..b614e2d79ea 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAwaitTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAwaitTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java index e70aac71576..a84f78ad73c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCacheTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCacheTest.java index fd286681c85..3e6193a2e92 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java index 229d00acc67..418afc70ccf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java index fd3124a96cd..8a9f9477d83 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatTest.java index b41086ce3be..11bc1a9b064 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -52,9 +52,9 @@ public void subscribe(Subscriber s) { }), 1 ) .test() - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); - TestHelper.assertError(errors, 0, MissingBackpressureException.class); + TestHelper.assertError(errors, 0, QueueOverflowException.class); } finally { RxJavaPlugins.reset(); } @@ -300,4 +300,9 @@ public void run() throws Exception { assertFalse("The second Completable was interrupted!", interrupted[0]); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowableToCompletable(f -> Completable.concat(f)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreateTest.java index d0323011fb8..bda1166ef92 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelaySubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelaySubscriptionTest.java index d467d8e2cfa..6e524eff27d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelaySubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelaySubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelayTest.java index 94e34fe7285..c84972863db 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDelayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetachTest.java index b5b52b67c28..5373499d301 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDetachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOnTest.java index 32b5a85aa98..73a4e58c772 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDisposeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ import io.reactivex.rxjava3.functions.Action; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.schedulers.TestScheduler; +import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -138,4 +138,9 @@ public void run() throws Exception { assertEquals(0, call[0]); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeCompletable(c -> c.unsubscribeOn(Schedulers.computation())); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinallyTest.java index 815482b02f5..14bd307b379 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java index 3e85e1e0278..1f66038f19f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnTest.java index c2bf4948379..6f9698afbf3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java index 1f4df16f44a..e697a91d349 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,6 +23,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Action; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.testsupport.TestHelper; public class CompletableFromActionTest extends RxJavaTest { @Test @@ -138,4 +140,31 @@ public void disposedUpfront() throws Throwable { verify(run, never()).run(); } + + @Test + public void disposeWhileRunningComplete() { + TestObserver to = new TestObserver<>(); + + Completable.fromAction(() -> { + to.dispose(); + }) + .subscribeWith(to) + .assertEmpty(); + } + + @Test + public void disposeWhileRunningError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestObserver to = new TestObserver<>(); + + Completable.fromAction(() -> { + to.dispose(); + throw new TestException(); + }) + .subscribeWith(to) + .assertEmpty(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallableTest.java index 7bd5011ca7f..940444f7a98 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromCallableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -29,9 +29,10 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class CompletableFromCallableTest extends RxJavaTest { + @Test public void fromCallable() { final AtomicInteger atomicInteger = new AtomicInteger(); @@ -161,6 +162,7 @@ public String answer(InvocationOnMock invocation) throws Throwable { } @Test + @SuppressUndeliverable public void fromActionErrorsDisposed() { final AtomicInteger calls = new AtomicInteger(); Completable.fromCallable(new Callable() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromMaybeTest.java index 2651f04f2c2..db201e07a73 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservableTest.java index ab72061437c..5fc8ba08c64 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisherTest.java index c6d37d738d8..177dc4e156b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java index 2559f09187b..2b3e9a65142 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,6 +22,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.testsupport.TestHelper; public class CompletableFromRunnableTest extends RxJavaTest { @Test @@ -137,4 +139,31 @@ public void disposedUpfront() throws Throwable { verify(run, never()).run(); } + + @Test + public void disposeWhileRunningComplete() { + TestObserver to = new TestObserver<>(); + + Completable.fromRunnable(() -> { + to.dispose(); + }) + .subscribeWith(to) + .assertEmpty(); + } + + @Test + public void disposeWhileRunningError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestObserver to = new TestObserver<>(); + + Completable.fromRunnable(() -> { + to.dispose(); + throw new TestException(); + }) + .subscribeWith(to) + .assertEmpty(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingleTest.java index e8595f299ee..14e5a29ac9e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplierTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplierTest.java index bcad666785f..453fc4c2c0c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplierTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromSupplierTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.functions.Supplier; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class CompletableFromSupplierTest extends RxJavaTest { @@ -163,6 +163,7 @@ public String answer(InvocationOnMock invocation) throws Throwable { } @Test + @SuppressUndeliverable public void fromActionErrorsDisposed() { final AtomicInteger calls = new AtomicInteger(); Completable.fromSupplier(new Supplier() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHideTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHideTest.java index 59352d76a5a..16afcaa075a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHideTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableHideTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLiftTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLiftTest.java index 4f0ba23ce86..21cf3fb3050 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLiftTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableLiftTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterializeTest.java index aa77e6a9758..8c301f50fa4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMaterializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterableTest.java index bacfc8521a2..cf3dc03c698 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,11 +14,14 @@ package io.reactivex.rxjava3.internal.operators.completable; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.operators.completable.CompletableMergeIterable.MergeCompletableObserver; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.PublishSubject; @@ -124,4 +127,9 @@ public void remove() { to.assertEmpty(); } + + @Test + public void dispose() { + TestHelper.checkDisposed(new MergeCompletableObserver(new TestObserver(), new CompositeDisposable(), new AtomicInteger())); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeTest.java index 3482a53409d..38166ea6598 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableMergeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,6 +16,7 @@ import static org.junit.Assert.*; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import org.reactivestreams.Subscriber; @@ -25,9 +26,11 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.internal.util.AtomicThrowable; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.subjects.CompletableSubject; import io.reactivex.rxjava3.testsupport.*; public class CompletableMergeTest extends RxJavaTest { @@ -593,4 +596,33 @@ public Completable apply(Flowable upstream) { } }); } + + @Test + public void iterableCompleteLater() { + CompletableSubject cs = CompletableSubject.create(); + + TestObserver to = Completable.mergeDelayError(Arrays.asList(cs, cs, cs)) + .test(); + + to.assertEmpty(); + + cs.onComplete(); + + to.assertResult(); + } + + @Test + public void terminalDisposed() { + TestHelper.checkDisposed(new CompletableMergeArrayDelayError.TryTerminateAndReportDisposable(new AtomicThrowable())); + } + + @Test + public void innerDisposed() { + TestHelper.checkDisposed(new CompletableMergeArray.InnerCompletableObserver(new TestObserver(), new AtomicBoolean(), new CompositeDisposable(), 1)); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowableToCompletable(f -> Completable.merge(f)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOnTest.java index 6d5cc210640..f4613f5c597 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableObserveOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java index 531f13b8cc0..d7b1cae653f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeekTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeekTest.java index ddc5a16056e..827599e353e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeekTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletablePeekTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableRepeatWhenTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableRepeatWhenTest.java index 6a80eda644b..d9a262b317e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableRepeatWhenTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableRepeatWhenTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java index fb5390cdccb..a8f0390c632 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java index 234fb0290c0..40c618ac0ab 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java index b7b68ad3216..9e3fd56b99c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java index 065a600a0e3..4b2ed6d588d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOnTest.java index 22d826fc702..3c20a125881 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeTest.java index 7c140db31d3..f0fded59963 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSwitchOnNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSwitchOnNextTest.java index ad6147fef58..312f9653ed3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSwitchOnNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSwitchOnNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilTest.java index 3458ef97722..1eefff19565 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTakeUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeoutTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeoutTest.java index a2f0771ab4c..86f2f2890a5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeoutTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimeoutTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimerTest.java index 7f6b3399616..bfd87a1af66 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ public void dispose() { public void timerInterruptible() throws Exception { ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); try { - for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) { + for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec, true) }) { final AtomicBoolean interrupted = new AtomicBoolean(); TestObserver to = Completable.timer(1, TimeUnit.MILLISECONDS, s) .doOnComplete(new Action() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowableTest.java index d1fdb548fa4..8c10ea5225a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java index 7501a2fe859..c857e95ebb8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java index 96404e81673..7ad93e9bef6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUnsafeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUnsafeTest.java index 4581a8944d0..72b28edea03 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUnsafeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUnsafeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsingTest.java index 6a7ddd564bd..72e4d164917 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableUsingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstreamTest.java index e109a0a5448..65f593211cd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/AbstractFlowableWithUpstreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatestTest.java index 825c74e3219..a842c39c2be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java index 82ae58730f2..92513b30724 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNextTest.java index 35c1501ae09..718a7ba6a16 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -223,8 +223,8 @@ public void nextWithCallingHasNextMultipleTimes() { /** * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value. - *

- * This results in output such as => a: 1 b: 2 c: 89 + *

+ * This results in output such as {@code => a: 1 b: 2 c: 89} * * @throws Throwable some method call is declared throws */ diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToFutureTest.java index cf8ad48a5fd..6da74eea030 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToFutureTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToIteratorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToIteratorTest.java index 64b22b17859..e5ad7806d36 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToIteratorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableToIteratorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -152,7 +152,7 @@ public void emptyThrowsNoSuch() { it.next(); } - @Test(expected = MissingBackpressureException.class) + @Test(expected = QueueOverflowException.class) public void overflowQueue() { Iterator it = new Flowable() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BufferUntilSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BufferUntilSubscriberTest.java index 69abd706ebe..6cdc17d210a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BufferUntilSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BufferUntilSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllTest.java index 387a2017dd6..2b66a48bd0d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAllTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmbTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmbTest.java index 0657a154741..1a1ceca9266 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmbTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAmbTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,6 +25,7 @@ import org.mockito.InOrder; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.exceptions.TestException; @@ -401,7 +402,8 @@ public void disposed() { @Test public void manySources() { - Flowable[] a = new Flowable[32]; + @SuppressWarnings("unchecked") + Flowable[] a = new Flowable[32]; Arrays.fill(a, Flowable.never()); a[31] = Flowable.just(1); @@ -660,4 +662,34 @@ public void subscribe(Subscriber subscriber) { .test() .assertResult(1); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.amb(Arrays.asList(Flowable.never(), Flowable.never()))); + } + + @Test + public void requestAfterCancel() { + Flowable.amb(Arrays.asList(Flowable.never(), Flowable.never())) + .subscribe(new FlowableSubscriber() { + + @Override + public void onNext(@NonNull Object t) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + } + + @Override + public void onSubscribe(@NonNull Subscription s) { + s.cancel(); + s.request(1); + } + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnyTest.java index e121cbc9249..2f18a90c64e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAnyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAsObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAsObservableTest.java index 15cd39ea0aa..d922ef48c34 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAsObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAsObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnectTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnectTest.java index d2213dd9111..07d1e66214e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnectTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAutoConnectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingTest.java index db560e03278..a1facf40460 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBlockingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTest.java index 87a0eeaf385..c1b08990bb7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableBufferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -34,7 +34,7 @@ import io.reactivex.rxjava3.internal.operators.flowable.FlowableBufferTimed.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subscribers.*; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -2388,4 +2388,112 @@ public List get() throws Exception { .assertFailure(TestException.class) ; } + + @Test + public void exactBadRequest() { + TestHelper.assertBadRequestReported(Flowable.never().buffer(1)); + } + + @Test + public void skipBadRequest() { + TestHelper.assertBadRequestReported(Flowable.never().buffer(1, 2)); + } + + @Test + public void overlapBadRequest() { + TestHelper.assertBadRequestReported(Flowable.never().buffer(2, 1)); + } + + @Test + public void bufferExactBoundedOnNextAfterDispose() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.unsafeCreate(s -> { + s.onSubscribe(new BooleanSubscription()); + ts.cancel(); + s.onNext(1); + }) + .buffer(1, TimeUnit.MINUTES, 2) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void boundaryCloseCompleteRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + BehaviorProcessor bp = BehaviorProcessor.createDefault(1); + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = bp + .buffer(BehaviorProcessor.createDefault(0), v -> pp) + .test(); + + TestHelper.race( + () -> bp.onComplete(), + () -> pp.onComplete() + ); + + ts.assertResult(Arrays.asList(1)); + } + } + + @Test + public void doubleOnSubscribeStartEnd() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.buffer(Flowable.never(), v -> Flowable.never())); + } + + @Test + public void cancel() { + TestHelper.checkDisposed(Flowable.never().buffer(Flowable.never(), v -> Flowable.never())); + } + + @Test + public void startEndCancelAfterOneBuffer() { + BehaviorProcessor.createDefault(1) + .buffer(BehaviorProcessor.createDefault(2), v -> Flowable.just(1)) + .takeUntil(v -> true) + .test() + .assertResult(Arrays.asList()); + } + + @Test + public void startEndCompleteOnBoundary() { + Flowable.empty() + .buffer(Flowable.never(), v -> Flowable.just(1)) + .take(1) + .test() + .assertResult(); + } + + @Test + public void startEndBackpressure() { + BehaviorProcessor.createDefault(1) + .buffer(BehaviorProcessor.createDefault(2), v -> Flowable.just(1)) + .test(1L) + .assertValuesOnly(Arrays.asList()); + } + + @Test + public void startEndBackpressureMoreWork() { + PublishProcessor bp = PublishProcessor.create(); + PublishProcessor pp = PublishProcessor.create(); + AtomicInteger counter = new AtomicInteger(); + + TestSubscriber> ts = bp + .buffer(pp, v -> Flowable.just(1)) + .doOnNext(v -> { + if (counter.getAndIncrement() == 0) { + pp.onNext(2); + pp.onComplete(); + } + }) + .test(1L); + + pp.onNext(1); + bp.onNext(1); + + ts + .assertValuesOnly(Arrays.asList()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCacheTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCacheTest.java index a3170558897..e71315351d0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -511,4 +511,18 @@ public void backpressure() { .requestMore(3) .assertResult(1, 2, 3, 4, 5); } + + @Test + public void addRemoveRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + Flowable f = Flowable.never().cache(); + + TestSubscriber ts = f.test(); + + TestHelper.race( + () -> ts.cancel(), + () -> f.test() + ); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCastTest.java index c39b1972f00..dc26fdccaa1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatestTest.java index 302ae3757b9..0f07148179d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCombineLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,8 +30,9 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.operators.flowable.FlowableZipTest.ArgsToString; +import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.*; @@ -1394,7 +1395,7 @@ public Object apply(Object[] a) throws Exception { public void combine2Flowable2Errors() throws Exception { List errors = TestHelper.trackPluginErrors(); try { - TestSubscriber testObserver = TestSubscriber.create(); + TestSubscriber testSubscriber = TestSubscriber.create(); TestScheduler testScheduler = new TestScheduler(); @@ -1459,11 +1460,11 @@ public void run() throws Exception { System.out.println("combineLatestDelayError: doFinally"); } }) - .subscribe(testObserver); + .subscribe(testSubscriber); testScheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS); - testObserver.awaitDone(5, TimeUnit.SECONDS); + testSubscriber.awaitDone(5, TimeUnit.SECONDS); assertTrue(errors.toString(), errors.isEmpty()); } finally { @@ -1558,4 +1559,230 @@ public Integer apply(Object[] t) throws Throwable { .test() .assertResult(2); } + + @Test + public void FlowableSourcesInIterable() { + Flowable source = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + Flowable.just(1).subscribe(s); + } + }; + + Flowable.combineLatest(Arrays.asList(source, source), new Function() { + @Override + public Integer apply(Object[] t) throws Throwable { + return 2; + } + }) + .test() + .assertResult(2); + } + + @Test + public void onCompleteDisposeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + TestSubscriber ts = new TestSubscriber<>(); + PublishProcessor pp = PublishProcessor.create(); + + Flowable.combineLatest(pp, Flowable.never(), (a, b) -> a) + .subscribe(ts); + + TestHelper.race(() -> pp.onComplete(), () -> ts.cancel()); + } + } + + @Test + public void onErrorDisposeDelayErrorRace() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestException ex = new TestException(); + + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + TestSubscriberEx ts = new TestSubscriberEx<>(); + AtomicReference> ref = new AtomicReference<>(); + Flowable f = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + ref.set(s); + } + }; + + Flowable.combineLatestDelayError(Arrays.asList(f, Flowable.never()), (a) -> a) + .subscribe(ts); + + ref.get().onSubscribe(new BooleanSubscription()); + + TestHelper.race(() -> ref.get().onError(ex), () -> ts.cancel()); + + if (ts.errors().isEmpty()) { + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } + } + }); + } + + @Test + public void doneButNotEmpty() { + PublishProcessor pp1 = PublishProcessor.create(); + PublishProcessor pp2 = PublishProcessor.create(); + + TestSubscriber ts = Flowable.combineLatest(pp1, pp2, (a, b) -> a + b) + .doOnNext(v -> { + if (v == 2) { + pp2.onNext(3); + pp2.onComplete(); + pp1.onComplete(); + } + }) + .test(); + + pp1.onNext(1); + pp2.onNext(1); + + ts.assertResult(2, 4); + } + + @Test + public void iterableNullPublisher() { + Flowable.combineLatest(Arrays.asList(Flowable.never(), null), (a) -> a) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.combineLatest(Flowable.never(), Flowable.never(), (a, b) -> a)); + } + + @Test + public void syncFusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Flowable.combineLatest(Flowable.never(), Flowable.never(), (a, b) -> a) + .subscribe(ts); + + ts.assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + } + + @Test + public void bounderyFusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY | QueueFuseable.BOUNDARY); + + Flowable.combineLatest(Flowable.never(), Flowable.never(), (a, b) -> a) + .subscribe(ts); + + ts.assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + } + + @Test + public void fusedNormal() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + Flowable.combineLatest(Flowable.just(1), Flowable.just(2), (a, b) -> a + b) + .subscribeWith(ts) + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertResult(3); + } + + @Test + public void fusedToParallel() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + Flowable.combineLatest(Flowable.just(1), Flowable.just(2), (a, b) -> a + b) + .parallel() + .sequential() + .subscribeWith(ts) + .assertResult(3); + } + + @Test + public void fusedToParallel2() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + Flowable.combineLatest(Flowable.just(1), Flowable.just(2), (a, b) -> a + b) + .compose(TestHelper.flowableStripBoundary()) + .parallel() + .sequential() + .subscribeWith(ts) + .assertResult(3); + } + + @Test + public void fusedError() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + Flowable.combineLatest(Flowable.just(1), Flowable.error(new TestException()), (a, b) -> a + b) + .subscribeWith(ts) + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertFailure(TestException.class); + } + + @Test + public void nonFusedMoreWorkBeforeTermination() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = Flowable.combineLatest(pp, Flowable.just(1), (a, b) -> a + b) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + pp.onComplete(); + } + }) + .test(); + + pp.onNext(0); + + ts.assertResult(1, 3); + } + + @Test + public void nonFusedDelayErrorMoreWorkBeforeTermination() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = Flowable.combineLatestDelayError(Arrays.asList(pp, Flowable.just(1)), a -> Arrays.asList(a)) + .doOnNext(v -> { + if (((Integer)v.get(0)) == 0) { + pp.onNext(2); + pp.onComplete(); + } + }) + .test(); + + pp.onNext(0); + + ts.assertResult(Arrays.asList(0, 1), Arrays.asList(2, 1)); + } + + @Test + public void fusedCombinerCrashError() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + Flowable.combineLatest(Flowable.just(1), Flowable.just(1), (a, b) -> { throw new TestException(); }) + .subscribeWith(ts) + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertFailure(TestException.class); + } + + @Test + public void fusedCombinerCrashError2() { + Flowable.combineLatest(Flowable.just(1), Flowable.just(1), (a, b) -> { throw new TestException(); }) + .compose(TestHelper.flowableStripBoundary()) + .rebatchRequests(10) + .test() + .assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatDelayErrorTest.java index 22e23a43914..39d6cf6ff59 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java index b8c2eaaff39..3711aecec41 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -1395,4 +1395,40 @@ public void publisherDelayErrorMaxConcurrency() { .test() .assertFailure(TestException.class, 1, 2, 3, 4, 5); } + + @Test + public void innerSyncFused() { + Flowable.just(1) + .hide() + .concatMapEagerDelayError(v -> Flowable.range(1, 10), true, 1, 1) + .test() + .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().concatMapEagerDelayError(v -> Flowable.never(), false)); + } + + @Test + public void cancelAfterOnNext() { + Flowable.just(1) + .hide() + .concatMapEagerDelayError(v -> Flowable.range(1, 5).hide(), true) + .takeUntil(v -> true) + .test() + .assertResult(1); + } + + @Test + public void noInnerQueue() { + Flowable.just(1) + .hide() + .concatMapEagerDelayError(v -> Flowable.fromPublisher(s -> { }), true) + .test(0L) + .assertEmpty() + .requestMore(1L) + .assertEmpty() + ; + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapSchedulerTest.java index 0cd75621998..027157ce027 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,17 +18,18 @@ import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.*; import org.junit.Test; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; -import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -65,6 +66,56 @@ public Publisher apply(String v) .assertResult("RxSingleScheduler"); } + @Test + public void innerScalarRequestRace() { + Flowable just = Flowable.just(1); + int n = 1000; + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor> source = PublishProcessor.create(); + + TestSubscriber ts = source + .concatMap(v -> v, n + 1, ImmediateThinScheduler.INSTANCE) + .test(1L); + + TestHelper.race(() -> { + for (int j = 0; j < n; j++) { + source.onNext(just); + } + }, () -> { + for (int j = 0; j < n; j++) { + ts.request(1); + } + }); + + ts.assertValueCount(n); + } + } + + @Test + public void innerScalarRequestRaceDelayError() { + Flowable just = Flowable.just(1); + int n = 1000; + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor> source = PublishProcessor.create(); + + TestSubscriber ts = source + .concatMapDelayError(v -> v, true, n + 1, ImmediateThinScheduler.INSTANCE) + .test(1L); + + TestHelper.race(() -> { + for (int j = 0; j < n; j++) { + source.onNext(just); + } + }, () -> { + for (int j = 0; j < n; j++) { + ts.request(1); + } + }); + + ts.assertValueCount(n); + } + } + @Test public void boundaryFusionDelayError() { Flowable.range(1, 10000) @@ -304,7 +355,7 @@ public Flowable apply(Integer t) throws Throwable { } @Test - public void issue2890NoStackoverflow() throws InterruptedException { + public void issue2890NoStackoverflow() throws InterruptedException, TimeoutException { final ExecutorService executor = Executors.newFixedThreadPool(2); final Scheduler sch = Schedulers.from(executor); @@ -349,7 +400,11 @@ public void onError(Throwable e) { } }); - executor.awaitTermination(20000, TimeUnit.MILLISECONDS); + long awaitTerminationTimeoutMillis = 100_000; + if (!executor.awaitTermination(awaitTerminationTimeoutMillis, TimeUnit.MILLISECONDS)) { + throw new TimeoutException("Completed " + counter.get() + "/" + n + " before timed out after " + + awaitTerminationTimeoutMillis + " milliseconds."); + } assertEquals(n, counter.get()); } @@ -569,7 +624,7 @@ protected void subscribeActual(Subscriber s) { } .concatMap(Functions.justFunction(Flowable.just(2)), 8, ImmediateThinScheduler.INSTANCE) .test(0L) - .assertFailure(IllegalStateException.class); + .assertFailure(QueueOverflowException.class); } @Test @@ -1088,4 +1143,141 @@ public Publisher apply(Integer v) throws Throwable { } }); } + + @Test + public void fusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + TestHelper.rejectFlowableFusion() + .concatMap(v -> Flowable.never(), 2, ImmediateThinScheduler.INSTANCE) + .subscribe(ts); + } + + @Test + public void fusionRejectedDelayErrorr() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + TestHelper.rejectFlowableFusion() + .concatMapDelayError(v -> Flowable.never(), true, 2, ImmediateThinScheduler.INSTANCE) + .subscribe(ts); + } + + @Test + public void scalarInnerJustDispose() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .hide() + .concatMap(v -> Flowable.fromCallable(() -> { + ts.cancel(); + return 1; + }), 2, ImmediateThinScheduler.INSTANCE) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void scalarInnerJustDisposeDelayError() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .hide() + .concatMapDelayError(v -> Flowable.fromCallable(() -> { + ts.cancel(); + return 1; + }), true, 2, ImmediateThinScheduler.INSTANCE) + .subscribe(ts); + + ts.assertEmpty(); + } + + static final class EmptyDisposingFlowable extends Flowable + implements Supplier { + final TestSubscriber ts; + EmptyDisposingFlowable(TestSubscriber ts) { + this.ts = ts; + } + + @Override + protected void subscribeActual(@NonNull Subscriber subscriber) { + EmptySubscription.complete(subscriber); + } + + @Override + public @NonNull Object get() throws Throwable { + ts.cancel(); + return null; + } + } + + @Test + public void scalarInnerEmptyDisposeDelayError() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .hide() + .concatMapDelayError(v -> new EmptyDisposingFlowable(ts), + true, 2, ImmediateThinScheduler.INSTANCE + ) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void mainErrorInnerNextIgnoreCancel() { + AtomicReference> ref = new AtomicReference<>(); + + Flowable.just(1).concatWith(Flowable.error(new TestException())) + .concatMap(v -> Flowable.fromPublisher(ref::set), 2, ImmediateThinScheduler.INSTANCE) + .doOnError(e -> { + ref.get().onSubscribe(new BooleanSubscription()); + ref.get().onNext(1); + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void scalarSupplierMainError() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.concatMap(v -> Flowable.fromCallable(() -> { + pp.onError(new TestException()); + return 2; + }), 2, ImmediateThinScheduler.INSTANCE) + .test() + ; + + pp.onNext(1); + + ts.assertFailure(TestException.class); + } + + @Test + public void mainErrorInnerErrorRace() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestException ex1 = new TestException(); + TestException ex2 = new TestException(); + + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + TestSubscriber ts = Flowable.fromPublisher(ref1::set) + .concatMap(v -> Flowable.fromPublisher(ref2::set), 2, ImmediateThinScheduler.INSTANCE) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + ref2.get().onSubscribe(new BooleanSubscription()); + + TestHelper.race(() -> ref1.get().onError(ex1), () -> ref2.get().onError(ex2)); + + ts.assertError(RuntimeException.class); + errors.clear(); + } + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapTest.java index e815c3675e0..10df043ba54 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatMap.WeakScalarSubscription; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatMap.SimpleScalarSubscription; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -32,9 +33,9 @@ public class FlowableConcatMapTest extends RxJavaTest { @Test - public void weakSubscriptionRequest() { + public void simpleSubscriptionRequest() { TestSubscriber ts = new TestSubscriber<>(0); - WeakScalarSubscription ws = new WeakScalarSubscription<>(1, ts); + SimpleScalarSubscription ws = new SimpleScalarSubscription<>(1, ts); ts.onSubscribe(ws); ws.request(0); @@ -78,6 +79,56 @@ public Publisher apply(String v) .assertResult("RxSingleScheduler"); } + @Test + public void innerScalarRequestRace() { + Flowable just = Flowable.just(1); + int n = 1000; + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor> source = PublishProcessor.create(); + + TestSubscriber ts = source + .concatMap(v -> v, n + 1) + .test(1L); + + TestHelper.race(() -> { + for (int j = 0; j < n; j++) { + source.onNext(just); + } + }, () -> { + for (int j = 0; j < n; j++) { + ts.request(1); + } + }); + + ts.assertValueCount(n); + } + } + + @Test + public void innerScalarRequestRaceDelayError() { + Flowable just = Flowable.just(1); + int n = 1000; + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor> source = PublishProcessor.create(); + + TestSubscriber ts = source + .concatMapDelayError(v -> v, true, n + 1) + .test(1L); + + TestHelper.race(() -> { + for (int j = 0; j < n; j++) { + source.onNext(just); + } + }, () -> { + for (int j = 0; j < n; j++) { + ts.request(1); + } + }); + + ts.assertValueCount(n); + } + } + @Test public void boundaryFusionDelayError() { Flowable.range(1, 10000) @@ -252,4 +303,23 @@ public Publisher apply(Integer v) throws Throwable { } }); } + + @Test + public void asyncFusedSource() { + UnicastProcessor up = UnicastProcessor.create(); + up.onNext(1); + up.onComplete(); + + up.concatMap(v -> Flowable.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void scalarCallableSource() { + Flowable.fromCallable(() -> 1) + .concatMap(v -> Flowable.just(1)) + .test() + .assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatTest.java index 208f7b1b513..5a0634ffb66 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.io.IOException; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.*; @@ -27,7 +28,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; @@ -728,7 +729,7 @@ public void subscribe(Subscriber s) { } @Test - public void issue2890NoStackoverflow() throws InterruptedException { + public void issue2890NoStackoverflow() throws InterruptedException, TimeoutException { final ExecutorService executor = Executors.newFixedThreadPool(2); final Scheduler sch = Schedulers.from(executor); @@ -773,7 +774,11 @@ public void onError(Throwable e) { } }); - executor.awaitTermination(20000, TimeUnit.MILLISECONDS); + long awaitTerminationTimeoutMillis = 100_000; + if (!executor.awaitTermination(awaitTerminationTimeoutMillis, TimeUnit.MILLISECONDS)) { + throw new TimeoutException("Completed " + counter.get() + "/" + n + " before timed out after " + + awaitTerminationTimeoutMillis + " milliseconds."); + } assertEquals(n, counter.get()); } @@ -1286,7 +1291,7 @@ protected void subscribeActual(Subscriber s) { } .concatMap(Functions.justFunction(Flowable.just(2)), 8) .test(0L) - .assertFailure(IllegalStateException.class); + .assertFailure(QueueOverflowException.class); } @Test @@ -1644,4 +1649,28 @@ public void run() throws Exception { assertEquals(0, counter.get()); } + + @Test + public void arrayDelayErrorMultipleErrors() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + Flowable.concatArrayDelayError(Flowable.error(new IOException()), Flowable.error(new TestException())) + .subscribe(ts); + + ts.assertFailure(CompositeException.class); + + TestHelper.assertCompositeExceptions(ts, IOException.class, TestException.class); + } + + @Test + public void arrayDelayErrorMultipleNullErrors() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + Flowable.concatArrayDelayError(null, null) + .subscribe(ts); + + ts.assertFailure(CompositeException.class); + + TestHelper.assertCompositeExceptions(ts, NullPointerException.class, NullPointerException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletableTest.java index fcf199dfd01..845c814dbcf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybeTest.java index a855c09c265..5b45eafc7f3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingleTest.java index 4301746a86d..8a7ed3cd658 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatWithSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountTest.java index 158a3232f0f..608138e3572 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCountTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreateTest.java index 38b05b0920a..4c3b7354764 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,16 +17,18 @@ import java.io.IOException; import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Cancellable; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; public class FlowableCreateTest extends RxJavaTest { @@ -1063,4 +1065,66 @@ public void subscribe(FlowableEmitter emitter) throws Exception { }, entry.getKey()).test().assertEmpty(); } } + + @Test + public void serializedMissingMoreWorkWithComplete() { + AtomicReference> ref = new AtomicReference<>(); + + Flowable.create(emitter -> { + emitter = emitter.serialize(); + ref.set(emitter); + assertEquals(Long.MAX_VALUE, emitter.requested()); + emitter.onNext(1); + }, BackpressureStrategy.MISSING) + .doOnNext(v -> { + if (v == 1) { + ref.get().onNext(2); + ref.get().onComplete(); + } + }) + .test() + .assertResult(1, 2); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.create(e -> { }, BackpressureStrategy.BUFFER)); + } + + @Test + public void tryOnErrorNull() { + Flowable.create(emitter -> emitter.tryOnError(null), BackpressureStrategy.MISSING) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void serializedCompleteOnNext() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.create(emitter -> { + emitter = emitter.serialize(); + + emitter.onComplete(); + emitter.onNext(1); + }, BackpressureStrategy.MISSING) + .subscribe(ts); + + ts.assertResult(); + } + + @Test + public void serializedCancelOnNext() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.create(emitter -> { + emitter = emitter.serialize(); + + ts.cancel(); + emitter.onNext(1); + }, BackpressureStrategy.MISSING) + .subscribe(ts); + + ts.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTest.java index bfb33f0e8e2..01122106c86 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDebounceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import io.reactivex.rxjava3.functions.Action; import org.junit.*; import org.mockito.InOrder; import org.reactivestreams.*; @@ -41,16 +42,86 @@ public class FlowableDebounceTest extends RxJavaTest { private TestScheduler scheduler; - private Subscriber Subscriber; + private Subscriber subscriber; private Scheduler.Worker innerScheduler; @Before public void before() { scheduler = new TestScheduler(); - Subscriber = TestHelper.mockSubscriber(); + subscriber = TestHelper.mockSubscriber(); innerScheduler = scheduler.createWorker(); } + @Test + public void debounceWithOnDroppedCallbackWithEx() throws Throwable { + Flowable source = Flowable.unsafeCreate(new Publisher() { + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + publishNext(subscriber, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. + publishNext(subscriber, 400, "two"); // Should be published since "three" will arrive after the timeout expires. + publishNext(subscriber, 900, "three"); // Should be skipped since "four" will arrive before the timout expires. + publishNext(subscriber, 999, "four"); // Should be skipped since onComplete will arrive before the timeout expires. + publishCompleted(subscriber, 1000); // Should be published as soon as the timeout expires. + } + }); + + Action whenDisposed = mock(Action.class); + + Flowable sampled = source + .doOnCancel(whenDisposed) + .debounce(400, TimeUnit.MILLISECONDS, scheduler, e -> { + if ("three".equals(e)) { + throw new TestException("forced"); + } + }); + sampled.subscribe(subscriber); + + InOrder inOrder = inOrder(subscriber); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(subscriber, times(1)).onNext("two"); + inOrder.verify(subscriber, times(1)).onError(any(TestException.class)); + inOrder.verify(subscriber, times(0)).onNext("three"); + inOrder.verify(subscriber, times(0)).onNext("four"); + inOrder.verify(subscriber, times(0)).onComplete(); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void debounceWithOnDroppedCallback() { + Flowable source = Flowable.unsafeCreate(new Publisher() { + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + publishNext(subscriber, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. + publishNext(subscriber, 400, "two"); // Should be published since "three" will arrive after the timeout expires. + publishNext(subscriber, 900, "three"); // Should be skipped since "four" will arrive before the timout expires. + publishNext(subscriber, 999, "four"); // Should be skipped since onComplete will arrive before the timeout expires. + publishCompleted(subscriber, 1000); // Should be published as soon as the timeout expires. + } + }); + + Observer dropCallbackObserver = TestHelper.mockObserver(); + Flowable sampled = source.debounce(400, TimeUnit.MILLISECONDS, scheduler, dropCallbackObserver::onNext); + sampled.subscribe(subscriber); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(subscriber); + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + + // must go to 800 since it must be 400 after when two is sent, which is at 400 + scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); + inOrder.verify(subscriber, times(1)).onNext("two"); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("one"); + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("three"); + inOrder.verify(subscriber, times(1)).onComplete(); + inOrder.verifyNoMoreInteractions(); + dropCallbackOrder.verifyNoMoreInteractions(); + } + @Test public void debounceWithCompleted() { Flowable source = Flowable.unsafeCreate(new Publisher() { @@ -65,15 +136,15 @@ public void subscribe(Subscriber subscriber) { }); Flowable sampled = source.debounce(400, TimeUnit.MILLISECONDS, scheduler); - sampled.subscribe(Subscriber); + sampled.subscribe(subscriber); scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(Subscriber); + InOrder inOrder = inOrder(subscriber); // must go to 800 since it must be 400 after when two is sent, which is at 400 scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); - inOrder.verify(Subscriber, times(1)).onNext("two"); + inOrder.verify(subscriber, times(1)).onNext("two"); scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(Subscriber, times(1)).onComplete(); + inOrder.verify(subscriber, times(1)).onComplete(); inOrder.verifyNoMoreInteractions(); } @@ -97,13 +168,13 @@ public void subscribe(Subscriber subscriber) { }); Flowable sampled = source.debounce(200, TimeUnit.MILLISECONDS, scheduler); - sampled.subscribe(Subscriber); + sampled.subscribe(subscriber); scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(Subscriber); - inOrder.verify(Subscriber, times(0)).onNext(anyString()); + InOrder inOrder = inOrder(subscriber); + inOrder.verify(subscriber, times(0)).onNext(anyString()); scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); - inOrder.verify(Subscriber, times(1)).onComplete(); + inOrder.verify(subscriber, times(1)).onComplete(); inOrder.verifyNoMoreInteractions(); } @@ -121,15 +192,15 @@ public void subscribe(Subscriber subscriber) { }); Flowable sampled = source.debounce(400, TimeUnit.MILLISECONDS, scheduler); - sampled.subscribe(Subscriber); + sampled.subscribe(subscriber); scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); - InOrder inOrder = inOrder(Subscriber); + InOrder inOrder = inOrder(subscriber); // 100 + 400 means it triggers at 500 scheduler.advanceTimeTo(500, TimeUnit.MILLISECONDS); - inOrder.verify(Subscriber).onNext("one"); + inOrder.verify(subscriber).onNext("one"); scheduler.advanceTimeTo(701, TimeUnit.MILLISECONDS); - inOrder.verify(Subscriber).onError(any(TestException.class)); + inOrder.verify(subscriber).onError(any(TestException.class)); inOrder.verifyNoMoreInteractions(); } @@ -530,7 +601,7 @@ public void timedBadRequest() { public void timedLateEmit() { TestSubscriber ts = new TestSubscriber<>(); DebounceTimedSubscriber sub = new DebounceTimedSubscriber<>( - ts, 1, TimeUnit.SECONDS, new TestScheduler().createWorker()); + ts, 1, TimeUnit.SECONDS, new TestScheduler().createWorker(), null); sub.onSubscribe(new BooleanSubscription()); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefaultIfEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefaultIfEmptyTest.java index dadec04fbed..fc2c7e15a88 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefaultIfEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDefaultIfEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDeferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDeferTest.java index 8a1b48d4e97..caec2443fc4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDeferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDeferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOtherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOtherTest.java index bb9faa4bcaf..57a8af4586f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOtherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelaySubscriptionOtherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.util.concurrent.*; @@ -343,4 +344,19 @@ public void subscribe(FlowableEmitter emitter) throws Exception { exec.shutdown(); } } + + @Test + public void doubleOnSubscribeMain() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.delaySubscription(Flowable.empty())); + } + + @Test + public void doubleOnSubscribeOther() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> PublishProcessor.create().delaySubscription(f)); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(PublishProcessor.create().delaySubscription(Flowable.empty())); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelayTest.java index 79740ee44c9..4d67594a177 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDelayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,6 +20,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.LockSupport; import org.junit.*; import org.mockito.InOrder; @@ -28,6 +29,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.SequentialDisposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.*; @@ -1030,4 +1032,38 @@ public Publisher apply(Integer t) throws Exception { .to(TestHelper.testConsumer()) .assertFailureAndMessage(NullPointerException.class, "The itemDelay returned a null Publisher"); } + + @Test + public void cancelShouldPreventRandomSubsequentEmissions() { + for (int attempt = 1; attempt < 100; attempt ++) { + + SequentialDisposable disposable = new SequentialDisposable(); + ConcurrentLinkedQueue sink = new ConcurrentLinkedQueue<>(); + + disposable.replace( + Flowable.range(1, 10) + .delay(1, TimeUnit.MICROSECONDS, Schedulers.computation(), true) + .doOnNext(v -> { + if (v == 1) { + Schedulers.computation().scheduleDirect(disposable::dispose); + } + sink.offer(v); + }) + .subscribe()); + + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1)); + + Integer last = null; + + while (!sink.isEmpty()) { + Integer current = sink.poll(); + + if (last != null && last + 1 != current) { + fail("Emission hole: " + last + " -> " + current); + } + + last = current; + } + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerializeTest.java index d4578db5291..89a14546141 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDematerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -223,7 +223,7 @@ protected void subscribeActual(Subscriber> subscrib } @Test - public void nonNotificationInstanceAfterDispose() { + public void notificationInstanceAfterDispose() { new Flowable>() { @Override protected void subscribeActual(Subscriber> subscriber) { @@ -236,4 +236,20 @@ protected void subscribeActual(Subscriber> subscrib .test() .assertResult(); } + + @Test + @SuppressWarnings("unchecked") + public void nonNotificationInstanceAfterDispose() { + new Flowable() { + @Override + protected void subscribeActual(Subscriber subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + subscriber.onNext(Notification.createOnComplete()); + subscriber.onNext(1); + } + } + .dematerialize(v -> (Notification)v) + .test() + .assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetachTest.java index 3c87bfeb9af..23d895ca08b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDetachTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import java.lang.ref.WeakReference; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctTest.java index 87d5cda476b..362283c7193 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,9 +27,10 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChangedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChangedTest.java index 9d9aa55fd84..00525b562bc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChangedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDistinctUntilChangedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,8 +28,8 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNextTest.java index 2ef5d0e0829..1e36eee49f6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.processors.UnicastProcessor; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterTerminateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterTerminateTest.java index cee677cf41d..ab1a3bd8ab4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterTerminateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoAfterTerminateTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinallyTest.java index 850c531203b..79cba18b3d3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,8 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; import io.reactivex.rxjava3.testsupport.*; @@ -208,7 +209,7 @@ public void syncFusedConditional() { Flowable.range(1, 5) .doFinally(this) - .filter(Functions.alwaysTrue()) + .compose(TestHelper.conditional()) .subscribe(ts); ts.assertFusionMode(QueueFuseable.SYNC) @@ -237,7 +238,7 @@ public void nonFusedConditional() { Flowable.range(1, 5).hide() .doFinally(this) - .filter(Functions.alwaysTrue()) + .compose(TestHelper.conditional()) .subscribe(ts); ts.assertFusionMode(QueueFuseable.NONE) @@ -252,7 +253,7 @@ public void syncFusedBoundaryConditional() { Flowable.range(1, 5) .doFinally(this) - .filter(Functions.alwaysTrue()) + .compose(TestHelper.conditional()) .subscribe(ts); ts.assertFusionMode(QueueFuseable.NONE) @@ -270,7 +271,7 @@ public void asyncFusedConditional() { up .doFinally(this) - .filter(Functions.alwaysTrue()) + .compose(TestHelper.conditional()) .subscribe(ts); ts.assertFusionMode(QueueFuseable.ASYNC) @@ -288,7 +289,7 @@ public void asyncFusedBoundaryConditional() { up .doFinally(this) - .filter(Functions.alwaysTrue()) + .compose(TestHelper.conditional()) .subscribe(ts); ts.assertFusionMode(QueueFuseable.NONE) @@ -512,4 +513,31 @@ public void run() throws Exception { assertEquals(Arrays.asList("onNext", "onComplete", "finally"), list); } + + @Test + public void fusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + TestHelper.rejectFlowableFusion() + .doFinally(() -> { }) + .subscribeWith(ts); + + ts.assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + } + + @Test + public void fusionRejectedConditional() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ANY); + + TestHelper.rejectFlowableFusion() + .doFinally(() -> { }) + .compose(TestHelper.conditional()) + .subscribeWith(ts); + + ts.assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEachTest.java index fc346086b62..484d62c19e2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnEachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -29,8 +29,9 @@ import io.reactivex.rxjava3.flowables.ConnectableFlowable; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycleTest.java index 524a0b5acb4..e1df09d7ee2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnLifecycleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnRequestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnRequestTest.java index b07470a3981..3e123089dcc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnRequestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnRequestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnSubscribeTest.java index c9ea4359d17..6dff7a53219 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnUnsubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnUnsubscribeTest.java index eab0324ba85..d060928deea 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnUnsubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableDoOnUnsubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtTest.java index 56297cbe057..0e36e075a85 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilterTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilterTest.java index 586a7b56c28..4b62f1e2a46 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilterTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFilterTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,8 +28,9 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFirstTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFirstTest.java index efcdb290c0e..b6100ddeb3c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFirstTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFirstTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableTest.java index 1c87d6f3b39..5e4e5c8f774 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,18 +16,19 @@ import static org.junit.Assert.*; import java.util.List; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import org.junit.Test; import org.reactivestreams.Subscription; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; @@ -510,6 +511,23 @@ protected void subscribeActual(CompletableObserver observer) { @Test public void delayErrorMaxConcurrency() { + Flowable.range(1, 3) + .flatMapCompletable(new Function() { + @Override + public CompletableSource apply(Integer v) throws Exception { + if (v == 2) { + return Completable.error(new TestException()); + } + return Completable.complete(); + } + }, true, 1) + .toFlowable() + .test() + .assertFailure(TestException.class); + } + + @Test + public void delayErrorMaxConcurrencyCompletable() { Flowable.range(1, 3) .flatMapCompletable(new Function() { @Override @@ -570,4 +588,59 @@ public Completable apply(Integer v) throws Throwable { } }); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.flatMapCompletable(v -> Completable.never()).toFlowable()); + } + + @Test + public void doubleOnSubscribeCompletable() { + TestHelper.checkDoubleOnSubscribeFlowableToCompletable(f -> f.flatMapCompletable(v -> Completable.never())); + } + + @Test + public void cancelWhileMapping() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor pp1 = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber<>(); + CountDownLatch cdl = new CountDownLatch(1); + + pp1.flatMapCompletable(v -> { + TestHelper.raceOther(() -> { + ts.cancel(); + }, cdl); + return Completable.complete(); + }) + .toFlowable() + .subscribe(ts); + + pp1.onNext(1); + + cdl.await(); + } + } + + @Test + public void cancelWhileMappingCompletable() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor pp1 = PublishProcessor.create(); + + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + + pp1.flatMapCompletable(v -> { + TestHelper.raceOther(() -> { + to.dispose(); + }, cdl); + return Completable.complete(); + }) + .subscribe(to); + + pp1.onNext(1); + + cdl.await(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybeTest.java index 8faad86fef1..a377761f0cf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,7 +22,7 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; @@ -30,6 +30,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -641,4 +642,57 @@ public Maybe apply(Integer v) throws Throwable { } }); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().flatMapMaybe(v -> Maybe.never())); + } + + @Test + public void successRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + MaybeSubject ss1 = MaybeSubject.create(); + MaybeSubject ss2 = MaybeSubject.create(); + + TestSubscriber ts = Flowable.just(ss1, ss2).flatMapMaybe(v -> v) + .test(); + + TestHelper.race( + () -> ss1.onSuccess(1), + () -> ss2.onSuccess(1) + ); + + ts.assertResult(1, 1); + } + } + + @Test + public void successCompleteRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + MaybeSubject ss1 = MaybeSubject.create(); + MaybeSubject ss2 = MaybeSubject.create(); + + TestSubscriber ts = Flowable.just(ss1, ss2).flatMapMaybe(v -> v) + .test(); + + TestHelper.race( + () -> ss1.onSuccess(1), + () -> ss2.onComplete() + ); + + ts.assertResult(1); + } + } + + @Test + public void successShortcut() { + MaybeSubject ss1 = MaybeSubject.create(); + + TestSubscriber ts = Flowable.just(ss1).hide().flatMapMaybe(v -> v) + .test(); + + ss1.onSuccess(1); + + ts.assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingleTest.java index 1a0cd3854ff..b13e8316af7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,7 +22,7 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; @@ -30,6 +30,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -541,4 +542,39 @@ public Single apply(Integer v) throws Throwable { } }); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().flatMapSingle(v -> Single.never())); + } + + @Test + public void successRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + SingleSubject ss1 = SingleSubject.create(); + SingleSubject ss2 = SingleSubject.create(); + + TestSubscriber ts = Flowable.just(ss1, ss2).flatMapSingle(v -> v) + .test(); + + TestHelper.race( + () -> ss1.onSuccess(1), + () -> ss2.onSuccess(1) + ); + + ts.assertResult(1, 1); + } + } + + @Test + public void successShortcut() { + SingleSubject ss1 = SingleSubject.create(); + + TestSubscriber ts = Flowable.just(ss1).hide().flatMapSingle(v -> v) + .test(); + + ss1.onSuccess(1); + + ts.assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapTest.java index 6df4dc72116..be94c5e57c7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,19 +17,22 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +import java.io.IOException; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.*; import org.junit.*; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -1150,4 +1153,353 @@ public void innerErrorsMainCancelled() { assertFalse("Has subscribers?", pp1.hasSubscribers()); } + + @Test + public void innerIsDisposed() { + FlowableFlatMap.InnerSubscriber inner = new FlowableFlatMap.InnerSubscriber<>(null, 10, 0L); + + assertFalse(inner.isDisposed()); + + inner.dispose(); + + assertTrue(inner.isDisposed()); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().flatMap(v -> Flowable.never())); + } + + @Test + public void signalsAfterMapperCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + s.onNext(1); + s.onNext(2); + s.onComplete(); + s.onError(new IOException()); + } + } + .flatMap(v -> { + throw new TestException(); + }) + .test() + .assertFailure(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + }); + } + + @Test + public void scalarQueueTerminate() { + PublishProcessor pp = PublishProcessor.create(); + TestSubscriber ts = new TestSubscriber<>(); + + pp + .flatMap(v -> Flowable.just(v)) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + pp.onNext(3); + } + }) + .take(2) + .subscribe(ts); + + pp.onNext(1); + + ts.assertResult(1, 2); + } + + @Test + public void scalarQueueCompleteMain() throws Exception { + PublishProcessor pp = PublishProcessor.create(); + TestSubscriber ts = new TestSubscriber<>(); + CountDownLatch cdl = new CountDownLatch(1); + pp + .flatMap(v -> Flowable.just(v)) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + TestHelper.raceOther(() -> pp.onComplete(), cdl); + } + }) + .subscribe(ts); + + pp.onNext(1); + + cdl.await(); + ts.assertResult(1, 2); + } + + @Test + public void fusedInnerCrash() { + UnicastProcessor up = UnicastProcessor.create(); + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = Flowable.just( + pp, + up.map(v -> { + if (v == 10) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.flowableStripBoundary()) + ) + .flatMap(v -> v, true) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + up.onNext(10); + } + }) + .test(); + + pp.onNext(1); + pp.onComplete(); + + ts.assertFailure(TestException.class, 1, 2); + } + + @Test + public void fusedInnerCrash2() { + UnicastProcessor up = UnicastProcessor.create(); + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = Flowable.just( + up.map(v -> { + if (v == 10) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.flowableStripBoundary()) + , pp + ) + .flatMap(v -> v, true) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + up.onNext(10); + } + }) + .test(); + + pp.onNext(1); + pp.onComplete(); + + ts.assertFailure(TestException.class, 1, 2); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.flatMap(v -> Flowable.never())); + } + + @Test + public void allConcurrency() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.just(2).hide(), Integer.MAX_VALUE) + .test() + .assertResult(2); + } + + @Test + public void allConcurrencyScalarInner() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.just(2), Integer.MAX_VALUE) + .test() + .assertResult(2); + } + + @Test + public void allConcurrencyScalarInnerEmpty() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.empty(), Integer.MAX_VALUE) + .test() + .assertResult(); + } + + static final class ScalarEmptyCancel extends Flowable implements Supplier { + final TestSubscriber ts; + + ScalarEmptyCancel(TestSubscriber ts) { + this.ts = ts; + } + + @Override + public @NonNull Integer get() throws Throwable { + ts.cancel(); + return null; + } + + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super @NonNull Integer> subscriber) { + EmptySubscription.complete(subscriber); + } + } + + @Test + public void someConcurrencyScalarInnerCancel() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .hide() + .flatMap(v -> new ScalarEmptyCancel(ts)) + .subscribeWith(ts) + .assertEmpty(); + } + + @Test + public void allConcurrencyBackpressured() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.just(2), Integer.MAX_VALUE) + .test(0L) + .assertEmpty() + .requestMore(1) + .assertResult(2); + } + + @Test + public void someConcurrencyInnerScalarCancel() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.just(2), 2) + .takeUntil(v -> true) + .test() + .assertResult(2); + } + + @Test + public void scalarInnerOuterOverflow() { + new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super @NonNull Integer> subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + subscriber.onNext(1); + subscriber.onNext(2); + subscriber.onNext(3); + } + } + .flatMap(v -> Flowable.just(v), 1) + .test(0L) + .assertFailure(QueueOverflowException.class); + } + + @Test + public void scalarInnerOuterOverflowSlowPath() { + AtomicReference> ref = new AtomicReference<>(); + new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super @NonNull Integer> subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + ref.set(subscriber); + subscriber.onNext(1); + } + } + .flatMap(v -> Flowable.just(v), 1) + .doOnNext(v -> { + if (v == 1) { + ref.get().onNext(2); + ref.get().onNext(3); + } + }) + .test() + .assertFailure(QueueOverflowException.class, 1); + } + + @Test + public void innerFastPathEmitOverflow() { + Flowable.just(1) + .hide() + .flatMap(v -> new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super @NonNull Integer> subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + subscriber.onNext(1); + subscriber.onNext(2); + subscriber.onNext(3); + } + }, false, 1, 1) + .test(0L) + .assertFailure(QueueOverflowException.class); + } + + @Test + public void takeFromScalarQueue() { + Flowable.just(1) + .hide() + .flatMap(v -> Flowable.just(2), 2) + .takeUntil(v -> true) + .test(0L) + .requestMore(2) + .assertResult(2); + } + + @Test + public void scalarInnerQueueEmpty() { + Flowable.just(1) + .concatWith(Flowable.never()) + .hide() + .flatMap(v -> Flowable.just(2), 2) + .test(0L) + .requestMore(2) + .assertValuesOnly(2); + } + + @Test + public void innerCompletesAfterOnNextInDrainThenCancels() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber<>(0L); + + Flowable.just(1) + .hide() + .flatMap(v -> pp) + .doOnNext(v -> { + if (v == 1) { + pp.onComplete(); + ts.cancel(); + } + }) + .subscribe(ts); + + pp.onNext(1); + + ts + .requestMore(1) + .assertValuesOnly(1); + } + + @Test(timeout = 5000) + public void mixedScalarAsync() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + Flowable + .range(0, 20) + .flatMap( + integer -> { + if (integer % 5 != 0) { + return Flowable + .just(integer); + } + + return Flowable + .just(-integer) + .observeOn(Schedulers.computation()); + }, + false, + 1 + ) + .ignoreElements() + .blockingAwait(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterableTest.java index c65cf4b5b47..2cb9392e19c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlattenIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,10 +26,11 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.flowable.FlowableFlattenIterable.FlattenIterableSubscriber; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.subscribers.TestSubscriber; @@ -813,7 +814,7 @@ protected void subscribeActual(Subscriber s) { } .flatMapIterable(Functions.justFunction(Arrays.asList(1)), 1) .test(0L) - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableForEachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableForEachTest.java index d9ff63257ca..e74d5caf261 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableForEachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableForEachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,6 +22,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.testsupport.TestHelper; public class FlowableForEachTest extends RxJavaTest { @@ -72,4 +73,11 @@ public void accept(Throwable e) throws Exception { assertEquals(Arrays.asList(1, 2, 3, 4, 5, 100), list); } + @Test + public void dispose() { + TestHelper.checkDisposed( + Flowable.never() + .forEachWhile(v -> true) + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java index b19a03159c3..5395ae30680 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArrayTest.java index d4dda817540..d3195ad8b22 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromArrayTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; @@ -21,7 +18,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Predicate; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallableTest.java index f8f3ed670c9..b603fd2d9b3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCallableTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java index 47c0b815fb4..fc8e4ec977f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; @@ -193,4 +194,11 @@ public void syncFusedRejected() throws Throwable { verify(action).run(); } + + @Test + public void upstream() { + Flowable f = Flowable.fromCompletable(Completable.never()); + assertTrue(f instanceof HasUpstreamCompletableSource); + assertSame(Completable.never(), ((HasUpstreamCompletableSource)f).source()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterableTest.java index d49111c25b2..5fe804a3102 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,18 +19,21 @@ import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.*; import org.junit.Test; import org.mockito.Mockito; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.*; @@ -962,4 +965,259 @@ public void remove() { .assertNoErrors() .assertNotComplete(); } + + @Test + public void hasNextCancelsAndCompletesFastPath() { + final TestSubscriber ts = new TestSubscriber<>(); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + int count; + + @Override + public boolean hasNext() { + if (++count == 2) { + ts.cancel(); + return false; + } + return true; + } + + @Override + public Integer next() { + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .subscribe(ts); + + ts.assertValue(1) + .assertNoErrors() + .assertNotComplete(); + } + + @Test + public void hasNextCancelsAndCompletesSlowPath() { + final TestSubscriber ts = new TestSubscriber<>(10L); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + int count; + + @Override + public boolean hasNext() { + if (++count == 2) { + ts.cancel(); + return false; + } + return true; + } + + @Override + public Integer next() { + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .subscribe(ts); + + ts.assertValue(1) + .assertNoErrors() + .assertNotComplete(); + } + + @Test + public void hasNextCancelsAndCompletesFastPathConditional() { + final TestSubscriber ts = new TestSubscriber<>(); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + int count; + + @Override + public boolean hasNext() { + if (++count == 2) { + ts.cancel(); + return false; + } + return true; + } + + @Override + public Integer next() { + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .filter(v -> true) + .subscribe(ts); + + ts.assertValue(1) + .assertNoErrors() + .assertNotComplete(); + } + + @Test + public void hasNextCancelsAndCompletesSlowPathConditional() { + final TestSubscriber ts = new TestSubscriber<>(10); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + int count; + + @Override + public boolean hasNext() { + if (++count == 2) { + ts.cancel(); + return false; + } + return true; + } + + @Override + public Integer next() { + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .filter(v -> true) + .subscribe(ts); + + ts.assertValue(1) + .assertNoErrors() + .assertNotComplete(); + } + + @Test + public void fusedPoll() throws Throwable { + AtomicReference> queue = new AtomicReference<>(); + + Flowable.fromIterable(Arrays.asList(1)) + .subscribe(new FlowableSubscriber() { + @Override + public void onSubscribe(@NonNull Subscription s) { + queue.set((SimpleQueue)s); + ((QueueSubscription)s).requestFusion(QueueFuseable.ANY); + } + + @Override + public void onNext(Integer t) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + } + }); + + SimpleQueue q = queue.get(); + + assertFalse(q.isEmpty()); + + assertEquals(1, q.poll()); + + assertTrue(q.isEmpty()); + + q.clear(); + + assertTrue(q.isEmpty()); + } + + @Test + public void disposeWhileIteratorNext() { + final TestSubscriber ts = new TestSubscriber<>(10); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return true; + } + + @Override + public Integer next() { + ts.cancel(); + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void disposeWhileIteratorNextConditional() { + final TestSubscriber ts = new TestSubscriber<>(10); + + Flowable.fromIterable(new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return true; + } + + @Override + public Integer next() { + ts.cancel(); + return 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }) + .filter(v -> true) + .subscribe(ts); + + ts.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java index 5eca34f9cb5..d33b9f1e409 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestSubscriberEx; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java index 0ef64d192c4..f9f666d7fd4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java index f133c8fb996..19ef5eb0180 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Supplier; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java index 01f6b1661fc..1aa15032990 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestSubscriberEx; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSourceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSourceTest.java index fefbf1533ec..6506c010ea9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSourceTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSourceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -137,7 +137,7 @@ public void normalError() { ts.assertError(MissingBackpressureException.class); ts.assertNotComplete(); - Assert.assertEquals("create: could not emit value due to lack of requests", ts.errors().get(0).getMessage()); + Assert.assertEquals("create: " + MissingBackpressureException.DEFAULT_MESSAGE, ts.errors().get(0).getMessage()); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplierTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplierTest.java index 5753e8ff66c..423b1409c1a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplierTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSupplierTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerateTest.java index ecd965a4f89..92746851186 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGenerateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -282,4 +282,17 @@ public void accept(Emitter e) throws Exception { .test(1) .assertResult(); } + + @Test + public void onNextAfterOnComplete() { + Flowable.generate(new Consumer>() { + @Override + public void accept(Emitter e) throws Exception { + e.onComplete(); + e.onNext(1); + } + }) + .test() + .assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java index ddc34f1d98b..d0d7dbea440 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,6 +18,7 @@ import static org.mockito.Mockito.*; import java.io.IOException; +import java.time.Duration; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -34,9 +35,9 @@ import io.reactivex.rxjava3.flowables.GroupedFlowable; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; @@ -45,6 +46,15 @@ public class FlowableGroupByTest extends RxJavaTest { + static Function, Flowable> FLATTEN_INTEGER = new Function, Flowable>() { + + @Override + public Flowable apply(GroupedFlowable t) { + return t; + } + + }; + final Function length = new Function() { @Override public Integer apply(String s) { @@ -102,6 +112,7 @@ public void empty() { } @Test + @SuppressUndeliverable public void error() { Flowable sourceStrings = Flowable.just("one", "two", "three", "four", "five", "six"); Flowable errorSource = Flowable.error(new TestException("forced failure")); @@ -1186,6 +1197,7 @@ public void keySelectorThrows() { } @Test + @SuppressUndeliverable public void valueSelectorThrows() { Flowable source = Flowable.just(0, 1, 2, 3, 4, 5, 6); @@ -1241,6 +1253,7 @@ public void accept(GroupedFlowable t1) { } @Test + @SuppressUndeliverable public void error2() { Flowable source = Flowable.concat(Flowable.just(0), Flowable. error(new TestException("Forced failure"))); @@ -1350,15 +1363,6 @@ public String apply(Integer l) { ts.assertNoErrors(); } - static Function, Flowable> FLATTEN_INTEGER = new Function, Flowable>() { - - @Override - public Flowable apply(GroupedFlowable t) { - return t; - } - - }; - @Test public void groupByWithNullKey() { final String[] key = new String[]{"uninitialized"}; @@ -1671,7 +1675,9 @@ public void accept(GroupedFlowable g) { .subscribe(ts2); ts1 - .assertFusionMode(QueueFuseable.ASYNC) + // FIXME fusion mode causes hangs + //.assertFusionMode(QueueFuseable.ASYNC) + .assertFusionMode(QueueFuseable.NONE) .assertValues(2, 3, 4, 5, 6, 7, 8, 9, 10, 11) .assertNoErrors() .assertComplete(); @@ -1683,6 +1689,7 @@ public void accept(GroupedFlowable g) { } @Test + @SuppressUndeliverable public void keySelectorAndDelayError() { Flowable.just(1).concatWith(Flowable.error(new TestException())) .groupBy(Functions.identity(), true) @@ -1697,6 +1704,7 @@ public Flowable apply(GroupedFlowable g) throws Excep } @Test + @SuppressUndeliverable public void keyAndValueSelectorAndDelayError() { Flowable.just(1).concatWith(Flowable.error(new TestException())) .groupBy(Functions.identity(), Functions.identity(), true) @@ -1805,10 +1813,21 @@ public Object apply(Flowable f) throws Exception { @Test public void badRequest() { - TestHelper.assertBadRequestReported(Flowable.just(1) + TestHelper.assertBadRequestReported(Flowable.just(1).hide() .groupBy(Functions.justFunction(1))); } + @Test + public void badRequestInner() { + Flowable.just(1).hide() + .groupBy(Functions.justFunction(1)) + .doOnNext(g -> { + TestHelper.assertBadRequestReported(g); + }) + .test() + .assertNoErrors(); + } + @Test public void doubleOnSubscribe() { TestHelper.checkDoubleOnSubscribeFlowable(new Function, Publisher>>() { @@ -1839,6 +1858,7 @@ public Publisher apply(GroupedFlowable g) throws Excep } @Test + @SuppressUndeliverable public void groupError() { Flowable.just(1).concatWith(Flowable.error(new TestException())) .groupBy(Functions.justFunction(1), true) @@ -1883,6 +1903,39 @@ public Map apply(final Consumer notify) throws Exceptio .assertNoValues() .assertError(ex); } + // ----------------------------------------------------------------------------------------------------------------------- + + private static final Function mod5 = new Function() { + + @Override + public Integer apply(Integer n) throws Exception { + return n % 5; + } + }; + + private static Function, Publisher> addCompletedKey( + final List completed) { + return new Function, Publisher>() { + @Override + public Publisher apply(final GroupedFlowable g) throws Exception { + return g.doOnComplete(new Action() { + @Override + public void run() throws Exception { + completed.add(g.getKey()); + } + }); + } + }; + } + + private static final class TestTicker extends Ticker { + long tick; + + @Override + public long read() { + return tick; + } + } @Test public void mapFactoryExpiryCompletesGroupedFlowable() { @@ -1905,32 +1958,6 @@ public void mapFactoryExpiryCompletesGroupedFlowable() { ts.assertValueCount(3); } - private static final Function mod5 = new Function() { - - @Override - public Integer apply(Integer n) throws Exception { - return n % 5; - } - }; - - @Test - public void mapFactoryWithExpiringGuavaCacheDemonstrationCodeForUseInJavadoc() { - //javadoc will be a version of this using lambdas and without assertions - final List completed = new CopyOnWriteArrayList<>(); - //size should be less than 5 to notice the effect - Function, Map> evictingMapFactory = createEvictingMapFactoryGuava(3); - int numValues = 1000; - TestSubscriber ts = - Flowable.range(1, numValues) - .groupBy(mod5, Functions.identity(), true, 16, evictingMapFactory) - .flatMap(addCompletedKey(completed)) - .test() - .assertComplete(); - ts.assertValueCount(numValues); - //the exact eviction behaviour of the guava cache is not specified so we make some approximate tests - assertTrue(completed.size() > numValues * 0.9); - } - @Test public void mapFactoryEvictionQueueClearedOnErrorCoverageOnly() { Function, Map> evictingMapFactory = createEvictingMapFactorySynchronousOnly(1); @@ -1952,28 +1979,28 @@ public Publisher apply(GroupedFlowable g) throws Exce .assertError(ex); } - private static Function, Publisher> addCompletedKey( - final List completed) { - return new Function, Publisher>() { - @Override - public Publisher apply(final GroupedFlowable g) throws Exception { - return g.doOnComplete(new Action() { - @Override - public void run() throws Exception { - completed.add(g.getKey()); - } - }); - } - }; - } + @Test + public void mapFactoryWithExpiringGuavaCacheDemonstrationCodeForUseInJavadoc() { + //javadoc will be a version of this using lambdas and without assertions + final List completed = new CopyOnWriteArrayList<>(); - private static final class TestTicker extends Ticker { - long tick; + AtomicReference> cacheOut = new AtomicReference<>(); - @Override - public long read() { - return tick; - } + //size should be less than 5 to notice the effect + Function, Map> evictingMapFactory = createEvictingMapFactoryGuava(3, cacheOut); + int numValues = 1000; + TestSubscriber ts = + Flowable.range(1, numValues) + .groupBy(mod5, Functions.identity(), true, 16, evictingMapFactory) + .flatMap(addCompletedKey(completed)) + .test() + .assertComplete() + ; + ts.assertValueCount(numValues); + //the exact eviction behaviour of the guava cache is not specified so we make some approximate tests + assertTrue(completed.size() > numValues * 0.9); + + cacheOut.get().invalidateAll(); } @Test @@ -2066,28 +2093,6 @@ public void run() throws Exception { ), list); } - @Test - public void cancellationOfUpstreamWhenGroupedFlowableCompletes() { - final AtomicBoolean cancelled = new AtomicBoolean(); - Flowable.just(1).repeat().doOnCancel(new Action() { - @Override - public void run() throws Exception { - cancelled.set(true); - } - }) - .groupBy(Functions.identity(), Functions.identity()) // - .flatMap(new Function, Publisher>() { - @Override - public Publisher apply(GroupedFlowable g) throws Exception { - return g.first(0).toFlowable(); - } - }) - .take(4) // - .test() // - .assertComplete(); - assertTrue(cancelled.get()); - } - //not thread safe private static final class SingleThreadEvictingHashMap implements Map { @@ -2185,13 +2190,14 @@ public Set> entrySet() { } } - private static Function, Map> createEvictingMapFactoryGuava(final int maxSize) { + private static Function, Map> createEvictingMapFactoryGuava(final int maxSize, + final AtomicReference> cacheOut) { Function, Map> evictingMapFactory = // new Function, Map>() { @Override public Map apply(final Consumer notify) throws Exception { - return CacheBuilder.newBuilder() // + Cache cache = CacheBuilder.newBuilder() // .maximumSize(maxSize) // .removalListener(new RemovalListener() { @Override @@ -2202,8 +2208,9 @@ public void onRemoval(RemovalNotification notification) { throw new RuntimeException(e); } }}) - . build() - .asMap(); + . build(); + cacheOut.set(cache); + return cache.asMap(); }}; return evictingMapFactory; } @@ -2228,6 +2235,30 @@ public void accept(Object object) { return evictingMapFactory; } + // ----------------------------------------------------------------------------------------------------------------------- + + @Test + public void cancellationOfUpstreamWhenGroupedFlowableCompletes() { + final AtomicBoolean cancelled = new AtomicBoolean(); + Flowable.just(1).repeat().doOnCancel(new Action() { + @Override + public void run() throws Exception { + cancelled.set(true); + } + }) + .groupBy(Functions.identity(), Functions.identity()) // + .flatMap(new Function, Publisher>() { + @Override + public Publisher apply(GroupedFlowable g) throws Exception { + return g.first(0).toFlowable(); + } + }) + .take(4) // + .test() // + .assertComplete(); + assertTrue(cancelled.get()); + } + @Test public void cancelOverFlatmapRace() { for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { @@ -2478,4 +2509,450 @@ public void run() throws Exception { assertEquals(1000, counter.get()); } + + @Test + public void delayErrorCompleteMoreWorkInGroup() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.groupBy(v -> 1, true) + .flatMap(g -> g.doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + pp.onComplete(); + } + }) + ) + .test() + ; + + pp.onNext(1); + + ts.assertResult(1, 2); + } + + @Test + public void groupSyncFusionRejected() { + Flowable.just(1) + .groupBy(v -> 1) + .doOnNext(g -> { + g.subscribeWith(new TestSubscriberEx().setInitialFusionMode(QueueFuseable.SYNC)) + .assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + }) + .test() + .assertComplete(); + } + + @Test + public void subscribeAbandonRace() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = TestSubscriber.create(); + + CountDownLatch cdl = new CountDownLatch(1); + + pp.groupBy(v -> 1) + .doOnNext(g -> { + TestHelper.raceOther(() -> { + g.subscribe(ts); + }, cdl); + }) + .test(); + + pp.onNext(1); + + cdl.await(); + + ts.assertValueCount(1); + } + } + + @Test + public void issue6974() { + + FlowableTransformer operation = + source -> source.publish(shared -> + shared + .firstElement() + .flatMapPublisher(firstElement -> + Flowable.just(firstElement).concatWith(shared) + ) + ); + + issue6974Run(20, 500_000, 20 - 1, 20 * 2, operation, false); + + issue6974Run(20, 500_000, 20, 20 * 2, operation, false); + } + + static void issue6974Run(int groups, int iterations, int sizeCap, int flatMapConcurrency, + FlowableTransformer operation, boolean notifyOnExplicitRevoke) { + TestSubscriber test = Flowable + .range(1, groups) + .repeat(iterations / groups) + .groupBy(i -> i, i -> i, false, 128, sizeCap(sizeCap, notifyOnExplicitRevoke)) + .flatMap(gf -> gf.compose(operation), flatMapConcurrency) + .test(); + test.awaitDone(5, TimeUnit.SECONDS); + test.assertValueCount(iterations); + } + + static Function, Map> sizeCap(int maxCapacity, boolean notifyOnExplicit) { + return itemEvictConsumer -> + CacheBuilder + .newBuilder() + .maximumSize(maxCapacity) + .removalListener(notification -> { + if (notification.getCause() != RemovalCause.EXPLICIT || notifyOnExplicit) { + try { + itemEvictConsumer.accept(notification.getValue()); + } catch (Throwable throwable) { + throw new RuntimeException(throwable); + } + } + }) + .build().asMap(); + } + + static void issue6974RunPart2(int groupByBufferSize, int flatMapMaxConcurrency, int groups, + boolean notifyOnExplicitEviction) { + TestSubscriber ts = Flowable + .range(1, 500_000) + .map(i -> i % groups) + .groupBy(i -> i, i -> i, false, groupByBufferSize, + // set cap too high + sizeCap(groups * 100, notifyOnExplicitEviction)) + .flatMap(gf -> gf + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .test(); + + ts + .awaitDone(5, TimeUnit.SECONDS) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void issue6974Part2Case1() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + issue6974RunPart2(groupByBufferSize, flatMapMaxConcurrency, groups, notifyOnExplicitEviction); + } + + @Test + public void issue6974Part2Case2() { + final int groups = 20; + + // Timeout... explicit eviction notification makes difference + int groupByBufferSize = groups * 30; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = true; + issue6974RunPart2(groupByBufferSize, flatMapMaxConcurrency, groups, notifyOnExplicitEviction); + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6974Part2Case2Loop() { + for (int i = 0; i < 1000; i++) { + issue6974Part2Case2(); + } + } + */ + + static void issue6974RunPart2NoEvict(int groupByBufferSize, int flatMapMaxConcurrency, int groups, + boolean notifyOnExplicitEviction) { + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .groupBy(i -> i) + .flatMap(gf -> gf + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .subscribeWith(new TestSubscriberEx<>()) + .awaitDone(5, TimeUnit.SECONDS) + .assertTerminated(); // MBE is possible if the async group closing is slow + } + + @Test + public void issue6974Part2Case1NoEvict() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + issue6974RunPart2NoEvict(groupByBufferSize, flatMapMaxConcurrency, groups, notifyOnExplicitEviction); + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6974Part2Case1NoEvictLoop() { + for (int i = 0; i < 1000; i++) { + issue6974Part2Case1NoEvict(); + } + } + */ + + @Test + public void issue6974Part2Case1ObserveOn() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnCancel(() -> { + System.out.println("Cancelling upstream"); + }) + .groupBy(i -> i, i -> i, false, groupByBufferSize, + sizeCap(groups * 2, notifyOnExplicitEviction)) + .flatMap(gf -> gf + .observeOn(Schedulers.computation()) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .subscribeWith(new TestSubscriberEx<>()) + .awaitDone(5, TimeUnit.SECONDS) + .assertTerminated(); // MBE is possible if the async group closing is slow + } + + @Test + public void issue6974Part2Case1ObserveOnHide() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnCancel(() -> System.out.println("Cancelling upstream")) + .groupBy(i -> i, i -> i, false, groupByBufferSize, + sizeCap(groups * 2, notifyOnExplicitEviction)) + .flatMap(gf -> gf + .hide() + .observeOn(Schedulers.computation()) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .subscribeWith(new TestSubscriberEx<>()) + .awaitDone(5, TimeUnit.SECONDS) + .assertTerminated(); // MBE is possible if the async group closing is slow + } + + @Test + public void issue6974Part2Case1ObserveOnNoCap() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int flatMapMaxConcurrency = 1_000_000; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnRequest(v -> { + System.out.println("Source: " + v); + }) + .groupBy(i -> i) + .flatMap(gf -> gf + .observeOn(Schedulers.computation()) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void issue6974Part2Case1ObserveOnNoCapHide() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int flatMapMaxConcurrency = 1_000_000; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnRequest(v -> { + System.out.println("Source: " + v); + }) + .groupBy(i -> i) + .flatMap(gf -> gf + .hide() + .observeOn(Schedulers.computation()) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertNoErrors() + .assertComplete(); + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6974Part2Case1ObserveOnNoCapHideLoop() { + for (int i = 0; i < 100; i++) { + issue6974Part2Case1ObserveOnNoCapHide(); + } + } + */ + + @Test + public void issue6974Part2Case1ObserveOnConditional() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnCancel(() -> System.out.println("Cancelling upstream")) + .groupBy(i -> i, i -> i, false, groupByBufferSize, + sizeCap(groups * 2, notifyOnExplicitEviction)) + .flatMap(gf -> gf + .observeOn(Schedulers.computation()) + .filter(v -> true) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .subscribeWith(new TestSubscriberEx<>()) + .awaitDone(5, TimeUnit.SECONDS) + .assertTerminated(); // MBE is possible if the async group closing is slow + } + + @Test + public void issue6974Part2Case1ObserveOnConditionalHide() { + final int groups = 20; + + // Not completed (Timed out), buffer is too small + int groupByBufferSize = groups * 2; + int flatMapMaxConcurrency = 2 * groups; + boolean notifyOnExplicitEviction = false; + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .doOnCancel(() -> System.out.println("Cancelling upstream")) + .groupBy(i -> i, i -> i, false, groupByBufferSize, + sizeCap(groups * 2, notifyOnExplicitEviction)) + .flatMap(gf -> gf + .hide() + .observeOn(Schedulers.computation()) + .filter(v -> true) + // .take(10) + .take(10, TimeUnit.MILLISECONDS) + , flatMapMaxConcurrency) + .subscribeWith(new TestSubscriberEx<>()) + .awaitDone(5, TimeUnit.SECONDS) + .assertTerminated(); // MBE is possible if the async group closing is slow + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6974Part2Case1ObserveOnHideLoop() { + for (int i = 0; i < 100; i++) { + issue6974Part2Case1ObserveOnHide(); + } + } + */ + + static Function, ConcurrentMap> ttlCapGuava(Duration ttl) { + return itemEvictConsumer -> + CacheBuilder + .newBuilder() + .expireAfterWrite(ttl) + .removalListener(n -> { + if (n.getCause() != com.google.common.cache.RemovalCause.EXPLICIT) { + try { + itemEvictConsumer.accept(n.getValue()); + } catch (Throwable throwable) { + throw new RuntimeException(throwable); + } + } + }).build().asMap(); + } + + @Test + public void issue6982Case1() { + final int groups = 20; + + int groupByBufferSize = 2; + int flatMapMaxConcurrency = 200 * groups; + + // ~50% of executions - Not completed (latch = 1, values = 500000, errors = 0, completions = 0, timeout!, + // disposed!) + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .groupBy(i -> i, i -> i, false, groupByBufferSize, ttlCapGuava(Duration.ofMillis(10))) + .flatMap(gf -> gf.observeOn(Schedulers.computation()), flatMapMaxConcurrency) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertNoErrors() + .assertComplete(); + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6982Case1Loop() { + for (int i = 0; i < 200; i++) { + System.out.println("issue6982Case1Loop " + i); + issue6982Case1(); + } + } + */ + + @Test + public void issue6982Case2() { + final int groups = 20; + + int groupByBufferSize = groups * 30; + int flatMapMaxConcurrency = groups * 500; + // Always : Not completed (latch = 1, values = 14100, errors = 0, completions = 0, timeout!, disposed!) + + Flowable + .range(1, 500_000) + .map(i -> i % groups) + .groupBy(i -> i, i -> i, false, groupByBufferSize, ttlCapGuava(Duration.ofMillis(10))) + .flatMap(gf -> gf.observeOn(Schedulers.computation()), flatMapMaxConcurrency) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertNoErrors() + .assertComplete(); + } + + /* + * Disabled: Takes very long. Run it locally only. + @Test + public void issue6982Case2Loop() { + for (int i = 0; i < 200; i++) { + System.out.println("issue6982Case2Loop " + i); + issue6982Case2(); + } + } + */ } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoinTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoinTest.java index bed06869235..fe83ad9fffe 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupJoinTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import static org.junit.Assert.*; @@ -31,7 +29,7 @@ import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.operators.flowable.FlowableGroupJoin.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -79,7 +77,7 @@ public Integer apply(Integer rightValue) throws Throwable { @Before public void before() { - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); } @Test @@ -732,4 +730,55 @@ public void leftRightEndState() { verify(js).innerClose(false, o); } + + @Test + public void disposeAfterOnNext() { + PublishProcessor pp1 = PublishProcessor.create(); + PublishProcessor pp2 = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber<>(); + + pp1.groupJoin(pp2, v -> Flowable.never(), v -> Flowable.never(), (a, b) -> a) + .doOnNext(v -> { + ts.cancel(); + }) + .subscribe(ts); + + pp2.onNext(1); + pp1.onNext(1); + } + + @Test + public void completeWithMoreWork() { + PublishProcessor pp1 = PublishProcessor.create(); + PublishProcessor pp2 = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber<>(); + + pp1.groupJoin(pp2, v -> Flowable.never(), v -> Flowable.never(), (a, b) -> a) + .doOnNext(v -> { + if (v == 1) { + pp2.onNext(2); + pp1.onComplete(); + pp2.onComplete(); + } + }) + .subscribe(ts); + + pp2.onNext(1); + pp1.onNext(1); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().groupJoin(Flowable.never(), v -> Flowable.never(), v -> Flowable.never(), (a, b) -> a)); + } + + @Test + public void missingBackpressure() { + Flowable.just(1) + .groupJoin(Flowable.never(), v -> BehaviorProcessor.createDefault(1), v -> Flowable.never(), (a, b) -> a) + .test(0) + .assertFailure(MissingBackpressureException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHideTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHideTest.java index c2162b2872c..f95775ebda7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHideTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableHideTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsTest.java index 2558b4a4339..dfc0e116808 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIgnoreElementsTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,8 +23,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.DisposableCompletableObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.subscribers.*; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelperTest.java index e570842c981..1549f01d636 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableInternalHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import org.junit.Test; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRangeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRangeTest.java index 46cf13229b9..f8bc3355e9f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRangeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalRangeTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; @@ -118,4 +115,12 @@ public void cancel() { .test() .assertResult(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L); } + + @Test + public void takeSameAsRange() { + Flowable.intervalRange(0, 2, 1, 1, TimeUnit.MILLISECONDS, Schedulers.trampoline()) + .take(2) + .test() + .assertResult(0L, 1L); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalTest.java index 68b8bd59fd8..7fde08d47fd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoinTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoinTest.java index 7c33df579cf..fe28a933204 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableJoinTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import static org.mockito.ArgumentMatchers.any; @@ -55,7 +53,7 @@ public Flowable apply(Integer t1) { @Before public void before() { - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); } @Test @@ -487,4 +485,35 @@ public Object apply(Integer a, Integer b) throws Exception { ts.assertFailure(MissingBackpressureException.class); } + + @Test + public void badRequest() { + PublishProcessor pp1 = PublishProcessor.create(); + PublishProcessor pp2 = PublishProcessor.create(); + + TestHelper.assertBadRequestReported(pp1.join(pp2, Functions.justFunction(Flowable.never()), Functions.justFunction(Flowable.never()), (a, b) -> a + b)); + } + + @Test + public void bothTerminateWithWorkRemaining() { + PublishProcessor pp1 = PublishProcessor.create(); + PublishProcessor pp2 = PublishProcessor.create(); + + TestSubscriber ts = pp1.join( + pp2, + v -> Flowable.never(), + v -> Flowable.never(), + (a, b) -> a + b) + .doOnNext(v -> { + pp1.onComplete(); + pp2.onNext(2); + pp2.onComplete(); + }) + .test(); + + pp1.onNext(0); + pp2.onNext(1); + + ts.assertComplete(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastTest.java index 1897d236d6f..3164802ab6d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLiftTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLiftTest.java index c208b8370b2..68227e8dfc6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLiftTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableLiftTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotificationTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotificationTest.java index 0deec9376b7..905cda55481 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapNotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapTest.java index 1c0e6c58a34..3d77fe5d46e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,8 +27,10 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -617,4 +619,19 @@ public Object apply(Flowable f) throws Exception { }, false, 1, 1, 1); } + @Test + public void conditionalFusionNoNPE() { + TestSubscriberEx ts = new TestSubscriberEx<>() + .setInitialFusionMode(QueueFuseable.ANY); + + Flowable.empty() + .observeOn(ImmediateThinScheduler.INSTANCE) + .filter(v -> true) + .map(v -> v) + .filter(v -> true) + .subscribe(ts) + ; + + ts.assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterializeTest.java index 1d798e62723..0f9c3df225d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMaterializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeDelayErrorTest.java index 64a2206e846..1959921168e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeMaxConcurrentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeMaxConcurrentTest.java index b2582430bb1..25b9cd825a1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeMaxConcurrentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeMaxConcurrentTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeTest.java index 3a1d65fc33f..57b7a4a6670 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -204,7 +204,7 @@ public void mergeArrayWithThreading() { TestSubscriber ts = new TestSubscriber<>(stringSubscriber); m.subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); verify(stringSubscriber, never()).onError(any(Throwable.class)); @@ -598,7 +598,7 @@ public void run() { TestSubscriber ts = new TestSubscriber<>(); merge.subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertComplete(); List onNextEvents = ts.values(); assertEquals(300, onNextEvents.size()); @@ -645,7 +645,7 @@ public void run() { TestSubscriber ts = new TestSubscriber<>(); merge.subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); ts.assertComplete(); List onNextEvents = ts.values(); @@ -706,7 +706,7 @@ public void onNext(Integer t) { }; Flowable.merge(f1.take(Flowable.bufferSize() * 2), Flowable.just(-99)).subscribe(testSubscriber); - testSubscriber.awaitDone(5, TimeUnit.SECONDS); + testSubscriber.awaitDone(10, TimeUnit.SECONDS); List onNextEvents = testSubscriber.values(); @@ -752,7 +752,7 @@ public void onNext(Integer t) { }; Flowable.merge(f1.take(Flowable.bufferSize() * 2), f2.take(Flowable.bufferSize() * 2)).observeOn(Schedulers.computation()).subscribe(testSubscriber); - testSubscriber.awaitDone(5, TimeUnit.SECONDS); + testSubscriber.awaitDone(10, TimeUnit.SECONDS); if (testSubscriber.errors().size() > 0) { testSubscriber.errors().get(0).printStackTrace(); } @@ -795,7 +795,7 @@ public void onNext(Integer t) { }; Flowable.merge(f1).observeOn(Schedulers.computation()).take(Flowable.bufferSize() * 2).subscribe(testSubscriber); - testSubscriber.awaitDone(5, TimeUnit.SECONDS); + testSubscriber.awaitDone(10, TimeUnit.SECONDS); if (testSubscriber.errors().size() > 0) { testSubscriber.errors().get(0).printStackTrace(); } @@ -850,7 +850,7 @@ public void onNext(Integer t) { }; Flowable.merge(f1).observeOn(Schedulers.computation()).take(Flowable.bufferSize() * 2).subscribe(testSubscriber); - testSubscriber.awaitDone(5, TimeUnit.SECONDS); + testSubscriber.awaitDone(10, TimeUnit.SECONDS); if (testSubscriber.errors().size() > 0) { testSubscriber.errors().get(0).printStackTrace(); } @@ -868,7 +868,7 @@ public void onNext(Integer t) { public void merge1AsyncStreamOf1() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(1, 1).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1, ts.values().size()); } @@ -877,7 +877,7 @@ public void merge1AsyncStreamOf1() { public void merge1AsyncStreamOf1000() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(1, 1000).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1000, ts.values().size()); } @@ -886,7 +886,7 @@ public void merge1AsyncStreamOf1000() { public void merge10AsyncStreamOf1000() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(10, 1000).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(10000, ts.values().size()); } @@ -895,7 +895,7 @@ public void merge10AsyncStreamOf1000() { public void merge1000AsyncStreamOf1000() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(1000, 1000).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1000000, ts.values().size()); } @@ -904,7 +904,7 @@ public void merge1000AsyncStreamOf1000() { public void merge2000AsyncStreamOf100() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(2000, 100).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(200000, ts.values().size()); } @@ -913,7 +913,7 @@ public void merge2000AsyncStreamOf100() { public void merge100AsyncStreamOf1() { TestSubscriber ts = new TestSubscriber<>(); mergeNAsyncStreamsOfN(100, 1).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(100, ts.values().size()); } @@ -935,7 +935,7 @@ public Flowable apply(Integer i) { public void merge1SyncStreamOf1() { TestSubscriber ts = new TestSubscriber<>(); mergeNSyncStreamsOfN(1, 1).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1, ts.values().size()); } @@ -944,7 +944,7 @@ public void merge1SyncStreamOf1() { public void merge1SyncStreamOf1000000() { TestSubscriber ts = new TestSubscriber<>(); mergeNSyncStreamsOfN(1, 1000000).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1000000, ts.values().size()); } @@ -953,7 +953,7 @@ public void merge1SyncStreamOf1000000() { public void merge1000SyncStreamOf1000() { TestSubscriber ts = new TestSubscriber<>(); mergeNSyncStreamsOfN(1000, 1000).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1000000, ts.values().size()); } @@ -962,7 +962,7 @@ public void merge1000SyncStreamOf1000() { public void merge10000SyncStreamOf10() { TestSubscriber ts = new TestSubscriber<>(); mergeNSyncStreamsOfN(10000, 10).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(100000, ts.values().size()); } @@ -971,7 +971,7 @@ public void merge10000SyncStreamOf10() { public void merge1000000SyncStreamOf1() { TestSubscriber ts = new TestSubscriber<>(); mergeNSyncStreamsOfN(1000000, 1).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(1000000, ts.values().size()); } @@ -1043,7 +1043,7 @@ public void subscribe(Subscriber s) { }); Flowable.merge(os).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(10, TimeUnit.SECONDS); ts.assertNoErrors(); assertEquals(10000, ts.values().size()); } @@ -1196,7 +1196,7 @@ public void run() { latch.countDown(); } }).subscribe(); - boolean a = latch.await(2, TimeUnit.SECONDS); + boolean a = latch.await(10, TimeUnit.SECONDS); if (!a) { for (String s : messages) { System.out.println("DEBUG => " + s); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletableTest.java index c074796be6d..8eab622ccfd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybeTest.java index e5ef48a4267..aeef5bb09bf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; -import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -448,4 +448,22 @@ public Flowable apply(Flowable upstream) { } }); } + + @Test + public void drainMoreWorkBeforeCancel() { + MaybeSubject ms = MaybeSubject.create(); + + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.range(1, 5).mergeWith(ms) + .doOnNext(v -> { + if (v == 1) { + ms.onSuccess(6); + ts.cancel(); + } + }) + .subscribe(ts); + + ts.assertValuesOnly(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingleTest.java index a48ee16fef9..23612f57546 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableMergeWithSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -444,4 +444,22 @@ public Flowable apply(Flowable upstream) { } }); } + + @Test + public void drainMoreWorkBeforeCancel() { + SingleSubject ss = SingleSubject.create(); + + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.range(1, 5).mergeWith(ss) + .doOnNext(v -> { + if (v == 1) { + ss.onSuccess(6); + ts.cancel(); + } + }) + .subscribe(ts); + + ts.assertValuesOnly(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOnTest.java index 7fbf19fa606..e4e3d6f3fe8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableObserveOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -31,11 +31,13 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.flowable.FlowableObserveOn.BaseObserveOnSubscriber; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.*; @@ -577,13 +579,13 @@ public void onNext(Integer t) { assertEquals(1, errors.size()); System.out.println("Errors: " + errors); Throwable t = errors.get(0); - if (t instanceof MissingBackpressureException) { + if (t instanceof QueueOverflowException) { // success, we expect this } else { - if (t.getCause() instanceof MissingBackpressureException) { + if (t.getCause() instanceof QueueOverflowException) { // this is also okay } else { - fail("Expecting MissingBackpressureException"); + fail("Expecting QueueOverflowException"); } } } @@ -1154,6 +1156,16 @@ public Flowable apply(Flowable f) throws Exception { }); } + @Test + public void doubleOnSubscribeConditional() { + TestHelper.checkDoubleOnSubscribeFlowable(new Function, Flowable>() { + @Override + public Flowable apply(Flowable f) throws Exception { + return f.observeOn(new TestScheduler()).compose(TestHelper.conditional()); + } + }); + } + @Test public void badSource() { List errors = TestHelper.trackPluginErrors(); @@ -1988,4 +2000,120 @@ public void fusedParallelProcessing() { .assertComplete() .assertNoErrors(); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().observeOn(ImmediateThinScheduler.INSTANCE)); + } + + @Test + public void syncFusedCancelAfterPoll() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .map(v -> { + ts.cancel(); + return v + 1; + }) + .compose(TestHelper.flowableStripBoundary()) + .observeOn(ImmediateThinScheduler.INSTANCE) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void syncFusedCancelAfterPollConditional() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1) + .map(v -> { + ts.cancel(); + return v + 1; + }) + .compose(TestHelper.flowableStripBoundary()) + .observeOn(ImmediateThinScheduler.INSTANCE) + .compose(TestHelper.conditional()) + .subscribe(ts); + + ts.assertEmpty(); + } + + @Test + public void backFusedMoreWork() { + final TestSubscriberEx ts = new TestSubscriberEx().setInitialFusionMode(QueueFuseable.ANY); + + PublishProcessor pp = PublishProcessor.create(); + + pp.observeOn(ImmediateThinScheduler.INSTANCE) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + } + }) + .subscribe(ts); + + pp.onNext(1); + + ts.assertValuesOnly(1, 2); + } + + @Test + public void moreWorkInRunAsync() { + final TestSubscriberEx ts = new TestSubscriberEx<>(); + + PublishProcessor pp = PublishProcessor.create(); + + pp.observeOn(ImmediateThinScheduler.INSTANCE) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + } + }) + .subscribe(ts); + + pp.onNext(1); + + ts.assertValuesOnly(1, 2); + } + + @Test + public void backFusedConditionalMoreWork() { + final TestSubscriberEx ts = new TestSubscriberEx().setInitialFusionMode(QueueFuseable.ANY); + + PublishProcessor pp = PublishProcessor.create(); + + pp.observeOn(ImmediateThinScheduler.INSTANCE) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + } + }) + .compose(TestHelper.conditional()) + .subscribe(ts); + + pp.onNext(1); + + ts.assertValuesOnly(1, 2); + } + + @Test + public void conditionalMoreWorkInRunAsync() { + final TestSubscriberEx ts = new TestSubscriberEx<>(); + + PublishProcessor pp = PublishProcessor.create(); + + pp.observeOn(ImmediateThinScheduler.INSTANCE) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + } + }) + .compose(TestHelper.conditional()) + .subscribe(ts); + + pp.onNext(1); + + ts.assertValuesOnly(1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategyTest.java index 327078ad602..217162c206c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferStrategyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,7 +15,9 @@ import static io.reactivex.rxjava3.core.BackpressureOverflowStrategy.*; import static io.reactivex.rxjava3.internal.functions.Functions.EMPTY_ACTION; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -28,8 +30,9 @@ import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.subscribers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FlowableOnBackpressureBufferStrategyTest extends RxJavaTest { @@ -206,4 +209,117 @@ public void justTake() { .test() .assertResult(1); } + + @Test + public void overflowNullAction() { + Flowable.range(1, 5) + .onBackpressureBuffer(1, null, BackpressureOverflowStrategy.DROP_OLDEST) + .test(0L) + .assertEmpty(); + } + + @Test + public void cancelOnDrain() { + Flowable.range(1, 5) + .onBackpressureBuffer(10, null, BackpressureOverflowStrategy.DROP_OLDEST) + .takeUntil(v -> true) + .test(0L) + .assertEmpty() + .requestMore(10) + .assertResult(1); + } + + @Test + public void onDroppedNormalDropOldest() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + @SuppressWarnings("unchecked") + Consumer onDropped = mock(Consumer.class); + + TestSubscriber ts = pp.onBackpressureBuffer(1, null, BackpressureOverflowStrategy.DROP_OLDEST, onDropped) + .test(0L); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertEmpty(); + verify(onDropped, never()).accept(any()); + + pp.onNext(2); + + ts.assertEmpty(); + + verify(onDropped).accept(1); + } + + @Test + public void onDroppedNormalDropLatest() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + @SuppressWarnings("unchecked") + Consumer onDropped = mock(Consumer.class); + + TestSubscriber ts = pp.onBackpressureBuffer(2, null, BackpressureOverflowStrategy.DROP_LATEST, onDropped) + .test(0L); + + ts.assertEmpty(); + + pp.onNext(1); + + pp.onNext(2); + + ts.assertEmpty(); + verify(onDropped, never()).accept(any()); + + pp.onNext(3); + + ts.assertEmpty(); + + verify(onDropped).accept(2); + } + + @Test + public void onDroppedNormalError() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + @SuppressWarnings("unchecked") + Consumer onDropped = mock(Consumer.class); + + TestSubscriber ts = pp.onBackpressureBuffer(1, null, BackpressureOverflowStrategy.ERROR, onDropped) + .test(0L); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertEmpty(); + verify(onDropped, never()).accept(any()); + + pp.onNext(2); + + ts.assertFailure(MissingBackpressureException.class); + + verify(onDropped).accept(2); + } + + @Test + public void onDroppedCrash() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + Consumer onDropped = v -> { throw new TestException(); }; + + TestSubscriberEx ts = pp.onBackpressureBuffer(1, null, BackpressureOverflowStrategy.DROP_OLDEST, onDropped) + .subscribeWith(new TestSubscriberEx(0L)); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferTest.java index cc5992862ba..657ce36f1b3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureBufferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,6 +14,8 @@ package io.reactivex.rxjava3.internal.operators.flowable; import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; import java.util.List; import java.util.concurrent.*; @@ -26,9 +28,9 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -340,4 +342,60 @@ public void fusedNoConcurrentCleanDueToCancel() { } } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.onBackpressureBuffer()); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().onBackpressureBuffer()); + } + + @Test + public void onDroppedNormal() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + @SuppressWarnings("unchecked") + Consumer onDropped = mock(Consumer.class); + + TestSubscriber ts = pp.onBackpressureBuffer(1, false, false, () -> { }, onDropped) + .test(0L); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertEmpty(); + verify(onDropped, never()).accept(any()); + + pp.onNext(2); + + ts.assertFailure(MissingBackpressureException.class); + + verify(onDropped).accept(2); + } + + @Test + public void onDroppedCrash() throws Throwable { + PublishProcessor pp = PublishProcessor.create(); + + Consumer onDropped = v -> { throw new TestException(); }; + + TestSubscriberEx ts = pp.onBackpressureBuffer(1, false, false, () -> { }, onDropped) + .subscribeWith(new TestSubscriberEx(0L)); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertFailure(MissingBackpressureException.class); + + assertTrue(ts.errors().get(0).getCause() instanceof TestException); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDropTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDropTest.java index 811e27f7669..0dfec9422ce 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDropTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureDropTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureErrorTest.java index 76fad7bf491..2693bf30145 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureErrorTest.java @@ -1,11 +1,11 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at - *

+ * * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. @@ -13,11 +13,16 @@ package io.reactivex.rxjava3.internal.operators.flowable; +import static org.junit.Assert.*; + import org.junit.Test; import org.reactivestreams.Publisher; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; public class FlowableOnBackpressureErrorTest extends RxJavaTest { @@ -51,4 +56,20 @@ public Object apply(Flowable f) throws Exception { } }, false, 1, 1, 1); } + + @Test + public void overflowCancels() { + PublishSubject ps = PublishSubject.create(); + + TestSubscriber ts = ps.toFlowable(BackpressureStrategy.ERROR) + .test(0L); + + assertTrue(ps.hasObservers()); + + ps.onNext(1); + + assertFalse(ps.hasObservers()); + + ts.assertFailure(MissingBackpressureException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatestTest.java index 438ebb1415e..f0d50994ed7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit; import org.junit.*; +import org.mockito.InOrder; import org.reactivestreams.Publisher; import io.reactivex.rxjava3.core.*; @@ -27,6 +28,8 @@ import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; +import static org.mockito.Mockito.inOrder; + public class FlowableOnBackpressureLatestTest extends RxJavaTest { @Test public void simple() { @@ -62,6 +65,68 @@ public void simpleBackpressure() { ts.assertNotComplete(); } + @Test + public void simpleBackpressureWithOnDroppedCallback() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0L); + + Observer dropCallbackObserver = TestHelper.mockObserver(); + + source.onBackpressureLatest(dropCallbackObserver::onNext) + .subscribe(ts); + + ts.assertNoValues(); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + ts.request(1); + + ts.assertValues(3); + + source.onNext(4); + source.onNext(5); + + ts.request(2); + + ts.assertValues(3,5); + + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + dropCallbackOrder.verify(dropCallbackObserver).onNext(1); + dropCallbackOrder.verify(dropCallbackObserver).onNext(2); + dropCallbackOrder.verify(dropCallbackObserver).onNext(4); + dropCallbackOrder.verifyNoMoreInteractions(); + } + + @Test + public void simpleBackpressureWithOnDroppedCallbackEx() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0L); + + source.onBackpressureLatest(e -> { + if (e == 3) { + throw new TestException("forced"); + } + }) + .subscribe(ts); + + ts.assertNoValues(); + + source.onNext(1); + source.onNext(2); + + ts.request(1); + + ts.assertValues(2); + + source.onNext(3); + source.onNext(4); + + ts.assertError(TestException.class); + ts.assertValues(2); + } + @Test public void synchronousDrop() { PublishProcessor source = PublishProcessor.create(); @@ -105,7 +170,7 @@ public void synchronousDrop() { } @Test - public void asynchronousDrop() throws InterruptedException { + public void asynchronousDrop() { TestSubscriberEx ts = new TestSubscriberEx(1L) { final Random rnd = new Random(); @Override @@ -133,6 +198,12 @@ public void onNext(Integer t) { int n = ts.values().size(); System.out.println("testAsynchronousDrop -> " + n); Assert.assertTrue("All events received?", n < m); + int previous = 0; + for (Integer current : ts.values()) { + Assert.assertTrue("The sequence must be increasing [current value=" + previous + + ", previous value=" + current + "]", previous <= current); + previous = current; + } } @Test diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceTest.java new file mode 100644 index 00000000000..5f7b7ad9571 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceTest.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.BiFunction; +import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.TestSubscriberEx; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +public class FlowableOnBackpressureReduceTest extends RxJavaTest { + + static final BiFunction TEST_INT_REDUCER = (previous, current) -> previous + current + 50; + + static final BiFunction TEST_OBJECT_REDUCER = (previous, current) -> current; + + @Test + public void simple() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + Flowable.range(1, 5).onBackpressureReduce(TEST_INT_REDUCER).subscribe(ts); + + ts.assertNoErrors(); + ts.assertTerminated(); + ts.assertValues(1, 2, 3, 4, 5); + } + + @Test + public void simpleError() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + + Flowable.range(1, 5).concatWith(Flowable.error(new TestException())) + .onBackpressureReduce(TEST_INT_REDUCER).subscribe(ts); + + ts.assertTerminated(); + ts.assertError(TestException.class); + ts.assertValues(1, 2, 3, 4, 5); + } + + @Test + public void simpleBackpressure() { + TestSubscriber ts = new TestSubscriber<>(2L); + + Flowable.range(1, 5).onBackpressureReduce(TEST_INT_REDUCER).subscribe(ts); + + ts.assertNoErrors(); + ts.assertValues(1, 2); + ts.assertNotComplete(); + } + + @Test + public void synchronousDrop() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0L); + + source.onBackpressureReduce(TEST_INT_REDUCER).subscribe(ts); + + ts.assertNoValues(); + + source.onNext(1); + ts.request(2); + + ts.assertValue(1); + + source.onNext(2); + + ts.assertValues(1, 2); + + source.onNext(3); + source.onNext(4); //3 + 4 + 50 == 57 + source.onNext(5); //57 + 5 + 50 == 112 + source.onNext(6); //112 + 6 + 50 == 168 + + ts.request(2); + + ts.assertValues(1, 2, 168); + + source.onNext(7); + + ts.assertValues(1, 2, 168, 7); + + source.onNext(8); + source.onNext(9); //8 + 9 + 50 == 67 + source.onComplete(); + + ts.request(1); + + ts.assertValues(1, 2, 168, 7, 67); + ts.assertNoErrors(); + ts.assertTerminated(); + } + + @Test + public void reduceBackpressuredSync() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0L); + + source.onBackpressureReduce(Integer::sum).subscribe(ts); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + ts.request(1); + + ts.assertValuesOnly(6); + + source.onNext(4); + source.onComplete(); + + ts.assertValuesOnly(6); + + ts.request(1); + ts.assertResult(6, 4); + } + + private TestSubscriberEx createDelayedSubscriber() { + return new TestSubscriberEx(1L) { + final Random rnd = new Random(); + + @Override + public void onNext(T t) { + super.onNext(t); + if (rnd.nextDouble() < 0.001) { + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + request(1); + } + }; + } + + private void assertValuesDropped(TestSubscriberEx ts, int totalValues) { + int n = ts.values().size(); + System.out.println("testAsynchronousDrop -> " + n); + Assert.assertTrue("All events received?", n < totalValues); + } + + private void assertIncreasingSequence(TestSubscriberEx ts) { + int previous = 0; + for (Integer current : ts.values()) { + Assert.assertTrue("The sequence must be increasing [current value=" + previous + + ", previous value=" + current + "]", previous <= current); + previous = current; + } + } + + @Test + public void asynchronousDrop() { + TestSubscriberEx ts = createDelayedSubscriber(); + int m = 100000; + Flowable.range(1, m) + .subscribeOn(Schedulers.computation()) + .onBackpressureReduce((previous, current) -> { + //in that case it works like onBackpressureLatest + //the output sequence of number must be increasing + return current; + }) + .observeOn(Schedulers.io()) + .subscribe(ts); + + ts.awaitDone(2, TimeUnit.SECONDS); + ts.assertTerminated(); + assertValuesDropped(ts, m); + assertIncreasingSequence(ts); + } + + @Test + public void asynchronousDrop2() { + TestSubscriberEx ts = createDelayedSubscriber(); + int m = 100000; + Flowable.rangeLong(1, m) + .subscribeOn(Schedulers.computation()) + .onBackpressureReduce(Long::sum) + .observeOn(Schedulers.io()) + .subscribe(ts); + + ts.awaitDone(2, TimeUnit.SECONDS); + ts.assertTerminated(); + assertValuesDropped(ts, m); + long sum = 0; + for (Long i : ts.values()) { + sum += i; + } + //sum = (A1 + An) * n / 2 = 100_001 * 50_000 = 50_000_00000 + 50_000 = 50_000_50_000 + Assert.assertEquals("Wrong sum: " + sum, 5000050000L, sum); + } + + @Test + public void nullPointerFromReducer() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0); + source.onBackpressureReduce((l, r) -> null).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, NullPointerException.class, "The reducer returned a null value"); + } + + @Test + public void exceptionFromReducer() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0); + source.onBackpressureReduce((l, r) -> { + throw new TestException("Test exception"); + }).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, TestException.class, "Test exception"); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.onBackpressureReduce(TEST_OBJECT_REDUCER)); + } + + @Test + public void take() { + Flowable.just(1, 2) + .onBackpressureReduce(TEST_INT_REDUCER) + .take(1) + .test() + .assertResult(1); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(Flowable.never().onBackpressureReduce(TEST_OBJECT_REDUCER)); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().onBackpressureReduce(TEST_OBJECT_REDUCER)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWithTest.java new file mode 100644 index 00000000000..32cee35603b --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureReduceWithTest.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.BiFunction; +import io.reactivex.rxjava3.functions.Supplier; +import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.TestSubscriberEx; +import org.junit.Assert; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class FlowableOnBackpressureReduceWithTest extends RxJavaTest { + + private static BiFunction, T, List> createTestReducer() { + return (list, number) -> { + list.add(number); + return list; + }; + } + + private static Supplier> createTestSupplier() { + return ArrayList::new; + } + + @Test + public void simple() { + TestSubscriberEx> ts = new TestSubscriberEx<>(); + + Flowable.range(1, 5).onBackpressureReduce(createTestSupplier(), createTestReducer()).subscribe(ts); + + ts.assertNoErrors(); + ts.assertTerminated(); + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2), + Collections.singletonList(3), + Collections.singletonList(4), + Collections.singletonList(5) + ); + } + + @Test + public void simpleError() { + TestSubscriberEx> ts = new TestSubscriberEx<>(); + + Flowable.range(1, 5).concatWith(Flowable.error(new TestException())) + .onBackpressureReduce(createTestSupplier(), createTestReducer()).subscribe(ts); + + ts.assertTerminated(); + ts.assertError(TestException.class); + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2), + Collections.singletonList(3), + Collections.singletonList(4), + Collections.singletonList(5) + ); + } + + @Test + public void simpleBackpressure() { + TestSubscriberEx> ts = new TestSubscriberEx<>(2L); + + Flowable.range(1, 5).onBackpressureReduce(createTestSupplier(), createTestReducer()).subscribe(ts); + + ts.assertNoErrors(); + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2) + ); + ts.assertNotComplete(); + } + + @Test + public void reduceBackpressuredSync() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx ts = new TestSubscriberEx<>(0L); + + source.onBackpressureReduce(() -> 0, Integer::sum).subscribe(ts); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + ts.request(1); + + ts.assertValuesOnly(6); + + source.onNext(4); + source.onComplete(); + + ts.assertValuesOnly(6); + + ts.request(1); + ts.assertResult(6, 4); + } + + @Test + public void synchronousDrop() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx> ts = new TestSubscriberEx<>(0L); + + source.onBackpressureReduce(createTestSupplier(), createTestReducer()).subscribe(ts); + + ts.assertNoValues(); + + source.onNext(1); + ts.request(2); + + ts.assertValues(Collections.singletonList(1)); + + source.onNext(2); + + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2) + ); + + source.onNext(3); + source.onNext(4); + source.onNext(5); + source.onNext(6); + + ts.request(2); + + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2), + Arrays.asList(3, 4, 5, 6) + ); + + source.onNext(7); + + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2), + Arrays.asList(3, 4, 5, 6), + Collections.singletonList(7) + ); + + source.onNext(8); + source.onNext(9); + source.onComplete(); + + ts.request(1); + + ts.assertValues( + Collections.singletonList(1), + Collections.singletonList(2), + Arrays.asList(3, 4, 5, 6), + Collections.singletonList(7), + Arrays.asList(8, 9) + ); + ts.assertNoErrors(); + ts.assertTerminated(); + } + + private TestSubscriberEx createDelayedSubscriber() { + return new TestSubscriberEx(1L) { + final Random rnd = new Random(); + + @Override + public void onNext(T t) { + super.onNext(t); + if (rnd.nextDouble() < 0.001) { + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + request(1); + } + }; + } + + private void assertValuesDropped(TestSubscriberEx ts, int totalValues) { + int n = ts.values().size(); + System.out.println("testAsynchronousDrop -> " + n); + Assert.assertTrue("All events received?", n < totalValues); + } + + private void assertIncreasingSequence(TestSubscriberEx ts) { + int previous = 0; + for (Integer current : ts.values()) { + Assert.assertTrue("The sequence must be increasing [current value=" + previous + + ", previous value=" + current + "]", previous <= current); + previous = current; + } + } + + @Test + public void asynchronousDrop() { + TestSubscriberEx ts = createDelayedSubscriber(); + int m = 100000; + Flowable.range(1, m) + .subscribeOn(Schedulers.computation()) + .onBackpressureReduce((Supplier>) Collections::emptyList, (list, current) -> { + //in that case it works like onBackpressureLatest + //the output sequence of number must be increasing + return Collections.singletonList(current); + }) + .observeOn(Schedulers.io()) + .concatMap(Flowable::fromIterable) + .subscribe(ts); + + ts.awaitDone(2, TimeUnit.SECONDS); + ts.assertTerminated(); + assertValuesDropped(ts, m); + assertIncreasingSequence(ts); + } + + @Test + public void asynchronousDrop2() { + TestSubscriberEx ts = createDelayedSubscriber(); + int m = 100000; + Flowable.rangeLong(1, m) + .subscribeOn(Schedulers.computation()) + .onBackpressureReduce(createTestSupplier(), createTestReducer()) + .observeOn(Schedulers.io()) + .concatMap(list -> Flowable.just(list.stream().reduce(Long::sum).orElseThrow(() -> { + throw new IllegalArgumentException("No value in list"); + }))) + .subscribe(ts); + + ts.awaitDone(2, TimeUnit.SECONDS); + ts.assertTerminated(); + assertValuesDropped(ts, m); + long sum = 0; + for (Long i : ts.values()) { + sum += i; + } + //sum = (A1 + An) * n / 2 = 100_001 * 50_000 = 50_000_00000 + 50_000 = 50_000_50_000 + Assert.assertEquals("Wrong sum: " + sum, 5000050000L, sum); + } + + @Test + public void nullPointerFromReducer() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx> ts = new TestSubscriberEx<>(0L); + source.onBackpressureReduce(createTestSupplier(), (BiFunction, ? super Integer, List>) (list, number) -> null).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, NullPointerException.class, "The reducer returned a null value"); + } + + @Test + public void nullPointerFromSupplier() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx> ts = new TestSubscriberEx<>(0L); + source.onBackpressureReduce(() -> null, createTestReducer()).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, NullPointerException.class, "The supplier returned a null value"); + } + + @Test + public void exceptionFromReducer() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx> ts = new TestSubscriberEx<>(0L); + source.onBackpressureReduce(createTestSupplier(), (BiFunction, ? super Integer, List>) (l, r) -> { + throw new TestException("Test exception"); + }).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, TestException.class, "Test exception"); + } + + @Test + public void exceptionFromSupplier() { + PublishProcessor source = PublishProcessor.create(); + TestSubscriberEx> ts = new TestSubscriberEx<>(0L); + source.onBackpressureReduce(() -> { + throw new TestException("Test exception"); + }, createTestReducer()).subscribe(ts); + + source.onNext(1); + source.onNext(2); + + TestHelper.assertError(ts.errors(), 0, TestException.class, "Test exception"); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.onBackpressureReduce(createTestSupplier(), createTestReducer())); + } + + @Test + public void take() { + Flowable.just(1, 2) + .onBackpressureReduce(createTestSupplier(), createTestReducer()) + .take(1) + .test() + .assertResult(Collections.singletonList(1)); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(Flowable.never().onBackpressureReduce(createTestSupplier(), createTestReducer())); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().onBackpressureReduce(createTestSupplier(), createTestReducer())); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java index c1c89cbe277..0a6f137ce24 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFlowableTest.java index b8829893fab..8b94b0d6f0a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFunctionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFunctionTest.java index 51de11ae7b7..982ffecd1d1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFunctionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorResumeNextViaFunctionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturnTest.java index ecde026f95e..15007f0228f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorReturnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishFunctionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishFunctionTest.java index 69ed3a4aed8..5511fd0123c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishFunctionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishFunctionTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.flowable; @@ -19,6 +16,7 @@ import static org.junit.Assert.*; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.*; @@ -26,7 +24,6 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; -import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.processors.PublishProcessor; @@ -39,12 +36,9 @@ public class FlowablePublishFunctionTest extends RxJavaTest { public void concatTakeFirstLastCompletes() { TestSubscriber ts = new TestSubscriber<>(); - Flowable.range(1, 3).publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return Flowable.concat(f.take(5), f.takeLast(5)); - } - }).subscribe(ts); + Flowable.range(1, 3) + .publish(f -> Flowable.concat(f.take(5), f.takeLast(5))) + .subscribe(ts); ts.assertValues(1, 2, 3); ts.assertNoErrors(); @@ -55,12 +49,9 @@ public Flowable apply(Flowable f) { public void concatTakeFirstLastBackpressureCompletes() { TestSubscriber ts = TestSubscriber.create(0L); - Flowable.range(1, 6).publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return Flowable.concat(f.take(5), f.takeLast(5)); - } - }).subscribe(ts); + Flowable.range(1, 6) + .publish(f -> Flowable.concat(f.take(5), f.takeLast(5))) + .subscribe(ts); ts.assertNoValues(); ts.assertNoErrors(); @@ -86,12 +77,7 @@ public void canBeCancelled() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return Flowable.concat(f.take(5), f.takeLast(5)); - } - }).subscribe(ts); + pp.publish(f -> Flowable.concat(f.take(5), f.takeLast(5))).subscribe(ts); pp.onNext(1); pp.onNext(2); @@ -108,8 +94,7 @@ public Flowable apply(Flowable f) { @Test public void invalidPrefetch() { try { - Flowable.never().publish( - Functions.>identity(), -99); + Flowable.never().publish(Functions.identity(), -99); fail("Didn't throw IllegalArgumentException"); } catch (IllegalArgumentException ex) { Assert.assertEquals("prefetch > 0 required but it was -99", ex.getMessage()); @@ -122,12 +107,7 @@ public void takeCompletes() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f.take(1); - } - }).subscribe(ts); + pp.publish(f -> f.take(1)).subscribe(ts); pp.onNext(1); @@ -153,12 +133,7 @@ public void onStart() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f.take(1); - } - }).subscribe(ts); + pp.publish(f -> f.take(1)).subscribe(ts); Assert.assertEquals(1, startCount.get()); } @@ -169,12 +144,7 @@ public void takeCompletesUnsafe() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f.take(1); - } - }).subscribe(ts); + pp.publish(f -> f.take(1)).subscribe(ts); pp.onNext(1); @@ -191,12 +161,7 @@ public void directCompletesUnsafe() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f; - } - }).subscribe(ts); + pp.publish(Functions.identity()).subscribe(ts); pp.onNext(1); pp.onComplete(); @@ -214,12 +179,7 @@ public void overflowMissingBackpressureException() { PublishProcessor pp = PublishProcessor.create(); - pp.publish(new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f; - } - }).subscribe(ts); + pp.publish(Functions.identity()).subscribe(ts); for (int i = 0; i < Flowable.bufferSize() * 2; i++) { pp.onNext(i); @@ -229,7 +189,7 @@ public Flowable apply(Flowable f) { ts.assertError(MissingBackpressureException.class); ts.assertNotComplete(); - Assert.assertEquals("Could not emit value due to lack of requests", + Assert.assertEquals(MissingBackpressureException.DEFAULT_MESSAGE, ts.errors().get(0).getMessage()); Assert.assertFalse("Source has subscribers?", pp.hasSubscribers()); } @@ -240,12 +200,7 @@ public void overflowMissingBackpressureExceptionDelayed() { PublishProcessor pp = PublishProcessor.create(); - new FlowablePublishMulticast<>(pp, new Function, Flowable>() { - @Override - public Flowable apply(Flowable f) { - return f; - } - }, Flowable.bufferSize(), true).subscribe(ts); + new FlowablePublishMulticast<>(pp, Functions.identity(), Flowable.bufferSize(), true).subscribe(ts); for (int i = 0; i < Flowable.bufferSize() * 2; i++) { pp.onNext(i); @@ -257,29 +212,23 @@ public Flowable apply(Flowable f) { ts.assertError(MissingBackpressureException.class); ts.assertNotComplete(); - Assert.assertEquals("Could not emit value due to lack of requests", ts.errors().get(0).getMessage()); + Assert.assertEquals(MissingBackpressureException.DEFAULT_MESSAGE, ts.errors().get(0).getMessage()); Assert.assertFalse("Source has subscribers?", pp.hasSubscribers()); } @Test public void emptyIdentityMapped() { Flowable.empty() - .publish(Functions.>identity()) + .publish(Functions.identity()) .test() - .assertResult() - ; + .assertResult(); } @Test public void independentlyMapped() { PublishProcessor pp = PublishProcessor.create(); - TestSubscriber ts = pp.publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable v) throws Exception { - return Flowable.range(1, 5); - } - }).test(0); + TestSubscriber ts = pp.publish(v -> Flowable.range(1, 5)).test(0); assertTrue("pp has no Subscribers?!", pp.hasSubscribers()); @@ -296,12 +245,7 @@ public Publisher apply(Flowable v) throws Exception { @Test public void badSource() { - TestHelper.checkBadSourceFlowable(new Function, Object>() { - @Override - public Object apply(Flowable f) throws Exception { - return f.publish(Functions.>identity()); - } - }, false, 1, 1, 1); + TestHelper.checkBadSourceFlowable(f -> f.publish(Functions.identity()), false, 1, 1, 1); } @Test @@ -315,7 +259,7 @@ protected void subscribeActual(Subscriber s) { } } } - .publish(Functions.>identity(), 8) + .publish(Functions.identity(), 8) .test(0) .assertFailure(MissingBackpressureException.class); } @@ -323,12 +267,7 @@ protected void subscribeActual(Subscriber s) { @Test public void errorResubscribe() { Flowable.error(new TestException()) - .publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable f) throws Exception { - return f.onErrorResumeWith(f); - } - }) + .publish(f -> f.onErrorResumeWith(f)) .test() .assertFailure(TestException.class); } @@ -336,21 +275,18 @@ public Publisher apply(Flowable f) throws Exception { @Test public void fusedInputCrash() { Flowable.just(1) - .map(new Function() { - @Override - public Integer apply(Integer v) throws Exception { - throw new TestException(); - } + .map(v -> { + throw new TestException(); }) - .publish(Functions.>identity()) + .publish(Functions.identity()) .test() .assertFailure(TestException.class); } @Test public void error() { - new FlowablePublishMulticast<>(Flowable.just(1).concatWith(Flowable.error(new TestException())), - Functions.>identity(), 16, true) + new FlowablePublishMulticast<>(Flowable.just(1).concatWith(Flowable.error(new TestException())), + Functions.identity(), 16, true) .test() .assertFailure(TestException.class, 1); } @@ -358,7 +294,7 @@ public void error() { @Test public void backpressuredEmpty() { Flowable.empty() - .publish(Functions.>identity()) + .publish(Functions.identity()) .test(0L) .assertResult(); } @@ -366,7 +302,7 @@ public void backpressuredEmpty() { @Test public void oneByOne() { Flowable.range(1, 10) - .publish(Functions.>identity()) + .publish(Functions.identity()) .rebatchRequests(1) .test() .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); @@ -387,7 +323,7 @@ public void onNext(Integer t) { } }; - pp.publish(Functions.>identity()).subscribe(ts); + pp.publish(Functions.identity()).subscribe(ts); pp.onNext(1); @@ -399,12 +335,7 @@ public void onNext(Integer t) { @Test public void inputOutputSubscribeRace() { Flowable source = Flowable.just(1) - .publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable f) throws Exception { - return f.subscribeOn(Schedulers.single()); - } - }); + .publish(f -> f.subscribeOn(Schedulers.single())); for (int i = 0; i < 500; i++) { source.test() @@ -416,7 +347,7 @@ public Publisher apply(Flowable f) throws Exception { @Test public void inputOutputSubscribeRace2() { Flowable source = Flowable.just(1).subscribeOn(Schedulers.single()) - .publish(Functions.>identity()); + .publish(Functions.identity()); for (int i = 0; i < 500; i++) { source.test() @@ -431,30 +362,19 @@ public void sourceSubscriptionDelayed() { final TestSubscriber ts1 = new TestSubscriber<>(0L); Flowable.just(1) - .publish(new Function, Publisher>() { - @Override - public Publisher apply(final Flowable f) throws Exception { - Runnable r1 = new Runnable() { - @Override - public void run() { - f.subscribe(ts1); - } - }; - - Runnable r2 = new Runnable() { - @Override - public void run() { + .publish(f -> { + Runnable r1 = () -> f.subscribe(ts1); + + Runnable r2 = () -> { for (int j = 0; j < 100; j++) { ts1.request(1); } - } - }; + }; - TestHelper.race(r1, r2); - return f; - } - }).test() - .assertResult(1); + TestHelper.race(r1, r2); + return f; + }).test() + .assertResult(1); ts1.assertResult(1); } @@ -463,24 +383,9 @@ public void run() { @Test public void longFlow() { Flowable.range(1, 1000000) - .publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable v) throws Exception { - return Flowable.mergeArray( - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 == 0; - } - }), - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 != 0; - } - })); - } - }) + .publish(v -> Flowable.mergeArray( + v.filter(w -> w % 2 == 0), + v.filter(w -> w % 2 != 0))) .takeLast(1) .test() .assertResult(1000000); @@ -489,24 +394,9 @@ public boolean test(Integer w) throws Exception { @Test public void longFlow2() { Flowable.range(1, 100000) - .publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable v) throws Exception { - return Flowable.mergeArray( - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 == 0; - } - }), - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 != 0; - } - })); - } - }) + .publish(v -> Flowable.mergeArray( + v.filter(w -> w % 2 == 0), + v.filter(w -> w % 2 != 0))) .test() .assertValueCount(100000) .assertNoErrors() @@ -516,26 +406,45 @@ public boolean test(Integer w) throws Exception { @Test public void longFlowHidden() { Flowable.range(1, 1000000).hide() - .publish(new Function, Publisher>() { - @Override - public Publisher apply(Flowable v) throws Exception { - return Flowable.mergeArray( - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 == 0; - } - }), - v.filter(new Predicate() { - @Override - public boolean test(Integer w) throws Exception { - return w % 2 != 0; - } - })); - } - }) + .publish(v -> Flowable.mergeArray( + v.filter(w -> w % 2 == 0), + v.filter(w -> w % 2 != 0))) .takeLast(1) .test() .assertResult(1000000); } + + @Test + public void noUpstreamCancelOnCasualChainClose() { + AtomicBoolean parentUpstreamCancelled = new AtomicBoolean(false); + Flowable.range(1, 10) + .doOnCancel(() -> parentUpstreamCancelled.set(true)) + .publish(Functions.identity()) + .test() + .awaitDone(1, TimeUnit.SECONDS); + assertFalse("Unnecessary upstream .cancel() call in FlowablePublishMulticast", parentUpstreamCancelled.get()); + } + + @Test + public void noUpstreamCancelOnCasualChainCloseWithInnerCancels() { + AtomicBoolean parentUpstreamCancelled = new AtomicBoolean(false); + Flowable.range(1, 10) + .doOnCancel(() -> parentUpstreamCancelled.set(true)) + .publish(v -> Flowable.concat(v.take(1), v.skip(5))) + .test() + .awaitDone(1, TimeUnit.SECONDS); + assertFalse("Unnecessary upstream .cancel() call in FlowablePublishMulticast", parentUpstreamCancelled.get()); + } + + @Test + public void upstreamCancelOnDownstreamCancel() { + AtomicBoolean parentUpstreamCancelled = new AtomicBoolean(false); + Flowable.range(1, 10) + .doOnCancel(() -> parentUpstreamCancelled.set(true)) + .publish(Functions.identity()) + .take(1) + .test() + .awaitDone(1, TimeUnit.SECONDS); + assertTrue("Upstream .cancel() not called in FlowablePublishMulticast", parentUpstreamCancelled.get()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticastTest.java index 0fb61a84c52..0e1bdbbdc02 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishMulticastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,9 +20,9 @@ import org.junit.Test; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; import io.reactivex.rxjava3.internal.operators.flowable.FlowablePublishMulticast.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.UnicastProcessor; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishTest.java index 0dffd13798b..c3355e9a38f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowablePublishTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -905,9 +905,9 @@ public void subscribe(FlowableEmitter s) throws Exception { .test(0L) // 3.x emits errors last, even the full queue errors .requestMore(10) - .assertFailure(MissingBackpressureException.class, 0, 1, 2, 3, 4, 5, 6, 7); + .assertFailure(QueueOverflowException.class, 0, 1, 2, 3, 4, 5, 6, 7); - TestHelper.assertError(errors, 0, MissingBackpressureException.class); + TestHelper.assertError(errors, 0, QueueOverflowException.class); } finally { RxJavaPlugins.reset(); } @@ -1596,7 +1596,7 @@ protected void subscribeActual(Subscriber s) { .refCount() .test(0) .requestMore(1) - .assertFailure(MissingBackpressureException.class, 1); + .assertFailure(QueueOverflowException.class, 1); } @Test @@ -1697,4 +1697,110 @@ public void disposeResets() { ts.assertValuesOnly(1); } + + @Test(expected = TestException.class) + public void connectDisposeCrash() { + ConnectableFlowable cf = Flowable.never().publish(); + + cf.connect(); + + cf.connect(d -> { throw new TestException(); }); + } + + @Test + public void resetWhileNotConnectedIsNoOp() { + ConnectableFlowable cf = Flowable.never().publish(); + + cf.reset(); + } + + @Test + public void resetWhileActiveIsNoOp() { + ConnectableFlowable cf = Flowable.never().publish(); + + cf.connect(); + + cf.reset(); + } + + @Test + public void crossCancelOnComplete() { + TestSubscriber ts1 = new TestSubscriber<>(); + TestSubscriber ts2 = new TestSubscriber() { + @Override + public void onComplete() { + super.onComplete(); + ts1.cancel(); + } + }; + + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.publish(); + + cf.subscribe(ts2); + cf.subscribe(ts1); + + cf.connect(); + + pp.onComplete(); + + ts2.assertResult(); + + ts1.assertEmpty(); + } + + @Test + public void crossCancelOnError() { + TestSubscriber ts1 = new TestSubscriber<>(); + TestSubscriber ts2 = new TestSubscriber() { + @Override + public void onError(Throwable t) { + super.onError(t); + ts1.cancel(); + } + }; + + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.publish(); + + cf.subscribe(ts2); + cf.subscribe(ts1); + + cf.connect(); + + pp.onError(new TestException()); + + ts2.assertFailure(TestException.class); + + ts1.assertEmpty(); + } + + @Test + public void disposeNoNeedForReset() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.publish(); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLongTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLongTest.java index 96401918ef2..bc24ab787c9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLongTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeLongTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subscribers.*; import io.reactivex.rxjava3.testsupport.*; @@ -539,4 +539,44 @@ public boolean test(Long v) throws Exception { ts.assertResult(2L, 4L); } + + @Test + public void slowPathCancelBeforeComplete() { + Flowable.rangeLong(1, 2) + .take(2) + .test() + .assertResult(1L, 2L); + } + + @Test + public void conditionalFastPathCancelBeforeComplete() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.rangeLong(1, 2) + .compose(TestHelper.conditional()) + .doOnNext(v -> { + if (v == 2L) { + ts.cancel(); + } + }) + .subscribe(ts); + + ts.assertValuesOnly(1L, 2L); + } + + @Test + public void conditionalSlowPathTake() { + TestSubscriber ts = new TestSubscriber<>(4); + + Flowable.rangeLong(1, 3) + .compose(TestHelper.conditional()) + .doOnNext(v -> { + if (v == 2L) { + ts.cancel(); + } + }) + .subscribe(ts); + + ts.assertValuesOnly(1L, 2L); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeTest.java index 39ab84ad63d..53264bddc08 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRangeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subscribers.*; import io.reactivex.rxjava3.testsupport.*; @@ -590,4 +590,28 @@ public void onNext(Integer t) { ts.assertResult(1, 2); } + + @Test + public void slowPathCancelBeforeComplete() { + Flowable.range(1, 2) + .take(2) + .test() + .assertResult(1, 2); + } + + @Test + public void conditionalFastPatchCancelBeforeComplete() { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.range(1, 2) + .compose(TestHelper.conditional()) + .doOnNext(v -> { + if (v == 2) { + ts.cancel(); + } + }) + .subscribe(ts); + + ts.assertValuesOnly(1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceTest.java index bc7d1e8ecea..16b491a352e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -530,4 +530,9 @@ public Integer apply(Integer a, Integer b) throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribeFlowable() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.reduce((a, b) -> a).toFlowable()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingleTest.java index d3da48ffe54..3de991aa2ed 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReduceWithSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCountTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCountTest.java index 169409ed1b4..48fbb633ae9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCountTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRefCountTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,7 +45,25 @@ public class FlowableRefCountTest extends RxJavaTest { @Test - public void refCountAsync() { + public void refCountAsync() throws InterruptedException { + // Flaky + for (int i = 0; i < 10; i++) { + try { + refCountAsyncActual(); + return; + } catch (AssertionError ex) { + if (i == 9) { + throw ex; + } + Thread.sleep((int)(200 * (Math.random() * 10 + 1))); + } + } + } + + /** + * Tries to coordinate async counting but it is flaky due to the low 10s of milliseconds. + */ + void refCountAsyncActual() { final AtomicInteger subscribeCount = new AtomicInteger(); final AtomicInteger nextCount = new AtomicInteger(); Flowable r = Flowable.interval(0, 20, TimeUnit.MILLISECONDS) diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatTest.java index 29959688ad2..9086c32a87a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRepeatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayEagerTruncateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayEagerTruncateTest.java index f263b98f669..d2a4ba56da2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayEagerTruncateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayEagerTruncateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -732,7 +732,14 @@ public boolean isDisposed() { @Test public void boundedReplayBuffer() { - BoundedReplayBuffer buf = new BoundedReplayBuffer<>(true); + BoundedReplayBuffer buf = new BoundedReplayBuffer(true) { + private static final long serialVersionUID = -9081211580719235896L; + + @Override + void truncate() { + } + }; + buf.addLast(new Node(1, 0)); buf.addLast(new Node(2, 1)); buf.addLast(new Node(3, 2)); @@ -1916,19 +1923,6 @@ public ReplayBuffer get() throws Exception { .assertFailure(TestException.class); } - @Test - public void currentDisposedWhenConnecting() { - FlowableReplay fr = (FlowableReplay)FlowableReplay.create(Flowable.never(), 16, true); - fr.connect(); - - fr.current.get().dispose(); - assertTrue(fr.current.get().isDisposed()); - - fr.connect(); - - assertFalse(fr.current.get().isDisposed()); - } - @Test public void noBoundedRetentionViaThreadLocal() throws Exception { Flowable source = Flowable.range(1, 200) @@ -2268,4 +2262,85 @@ public void timeAndSizeNoTerminalTruncationOnTimechange() { .assertComplete() .assertNoErrors(); } + + @Test + public void disposeNoNeedForResetSizeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10, true); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10, TimeUnit.MINUTES, Schedulers.single(), true); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeAndSIzeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10, 10, TimeUnit.MINUTES, Schedulers.single(), true); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayTest.java index 67763fce0b9..b644629a6de 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableReplayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.io.IOException; import java.lang.management.*; import java.util.*; import java.util.concurrent.*; @@ -37,6 +38,7 @@ import io.reactivex.rxjava3.internal.fuseable.HasUpstreamPublisher; import io.reactivex.rxjava3.internal.operators.flowable.FlowableReplay.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.internal.util.BackpressureHelper; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.*; @@ -44,6 +46,7 @@ import io.reactivex.rxjava3.testsupport.*; public class FlowableReplayTest extends RxJavaTest { + @Test public void bufferedReplay() { PublishProcessor source = PublishProcessor.create(); @@ -732,7 +735,14 @@ public boolean isDisposed() { @Test public void boundedReplayBuffer() { - BoundedReplayBuffer buf = new BoundedReplayBuffer<>(false); + BoundedReplayBuffer buf = new BoundedReplayBuffer(false) { + private static final long serialVersionUID = -9081211580719235896L; + + @Override + void truncate() { + } + }; + buf.addLast(new Node(1, 0)); buf.addLast(new Node(2, 1)); buf.addLast(new Node(3, 2)); @@ -760,6 +770,19 @@ public void boundedReplayBuffer() { } + @Test(expected = IllegalStateException.class) + public void boundedRemoveFirstOneItemOnly() { + BoundedReplayBuffer buf = new BoundedReplayBuffer(false) { + private static final long serialVersionUID = -9081211580719235896L; + + @Override + void truncate() { + } + }; + + buf.removeFirst(); + } + @Test public void timedAndSizedTruncation() { TestScheduler test = new TestScheduler(); @@ -965,7 +988,9 @@ public void take() { TestSubscriberEx ts = new TestSubscriberEx<>(); Flowable cached = Flowable.range(1, 100).replay().autoConnect(); - cached.take(10).subscribe(ts); + cached + .take(10) + .subscribe(ts); ts.assertNoErrors(); ts.assertTerminated(); @@ -1079,7 +1104,7 @@ public void valuesAndThenError() { } @Test - public void unsafeChildThrows() { + public void unsafeChildOnNextThrows() { final AtomicInteger count = new AtomicInteger(); Flowable source = Flowable.range(1, 100) @@ -1107,6 +1132,52 @@ public void onNext(Integer t) { ts.assertError(TestException.class); } + @Test + public void unsafeChildOnErrorThrows() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable source = Flowable.error(new IOException()) + .replay() + .autoConnect(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onError(Throwable t) { + super.onError(t); + throw new TestException(); + } + }; + + source.subscribe(ts); + + ts.assertFailure(IOException.class); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void unsafeChildOnCompleteThrows() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable source = Flowable.empty() + .replay() + .autoConnect(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onComplete() { + super.onComplete(); + throw new TestException(); + } + }; + + source.subscribe(ts); + + ts.assertResult(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + @Test public void unboundedLeavesEarly() { PublishProcessor source = PublishProcessor.create(); @@ -1917,19 +1988,6 @@ public ReplayBuffer get() throws Exception { .assertFailure(TestException.class); } - @Test - public void currentDisposedWhenConnecting() { - FlowableReplay fr = (FlowableReplay)FlowableReplay.create(Flowable.never(), 16, false); - fr.connect(); - - fr.current.get().dispose(); - assertTrue(fr.current.get().isDisposed()); - - fr.connect(); - - assertFalse(fr.current.get().isDisposed()); - } - @Test public void noBoundedRetentionViaThreadLocal() throws Exception { Flowable source = Flowable.range(1, 200) @@ -1992,4 +2050,240 @@ public void accept(byte[] v) throws Exception { + " -> " + after.get() / 1024.0 / 1024.0); } } + + @Test + public void unsafeChildOnNextThrowsSizeBound() { + final AtomicInteger count = new AtomicInteger(); + + Flowable source = Flowable.range(1, 100) + .doOnNext(new Consumer() { + @Override + public void accept(Integer t) { + count.getAndIncrement(); + } + }) + .replay(1000).autoConnect(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(Integer t) { + throw new TestException(); + } + }; + + source.subscribe(ts); + + Assert.assertEquals(100, count.get()); + + ts.assertNoValues(); + ts.assertNotComplete(); + ts.assertError(TestException.class); + } + + @Test + public void unsafeChildOnErrorThrowsSizeBound() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable source = Flowable.error(new IOException()) + .replay(1000) + .autoConnect(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onError(Throwable t) { + super.onError(t); + throw new TestException(); + } + }; + + source.subscribe(ts); + + ts.assertFailure(IOException.class); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void unsafeChildOnCompleteThrowsSizeBound() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable source = Flowable.empty() + .replay(1000) + .autoConnect(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onComplete() { + super.onComplete(); + throw new TestException(); + } + }; + + source.subscribe(ts); + + ts.assertResult(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test(expected = TestException.class) + public void connectDisposeCrash() { + ConnectableFlowable cf = Flowable.never().replay(); + + cf.connect(); + + cf.connect(d -> { throw new TestException(); }); + } + + @Test + public void resetWhileNotConnectedIsNoOp() { + ConnectableFlowable cf = Flowable.never().replay(); + + cf.reset(); + } + + @Test + public void resetWhileActiveIsNoOp() { + ConnectableFlowable cf = Flowable.never().replay(); + + cf.connect(); + + cf.reset(); + } + + @Test + public void delayedUpstreamSubscription() { + AtomicReference> ref = new AtomicReference<>(); + Flowable f = Flowable.unsafeCreate(ref::set); + + TestSubscriber ts = f.replay() + .autoConnect() + .test(); + + AtomicLong requested = new AtomicLong(); + + ref.get().onSubscribe(new Subscription() { + @Override + public void request(long n) { + BackpressureHelper.add(requested, n); + } + + @Override + public void cancel() { + } + }); + + assertEquals(Long.MAX_VALUE, requested.get()); + ref.get().onComplete(); + + ts.assertResult(); + } + + @Test + public void disposeNoNeedForReset() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetSizeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10, TimeUnit.MINUTES); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeAndSIzeBound() { + PublishProcessor pp = PublishProcessor.create(); + + ConnectableFlowable cf = pp.replay(10, 10, TimeUnit.MINUTES); + + TestSubscriber ts = cf.test(); + + Disposable d = cf.connect(); + + pp.onNext(1); + + d.dispose(); + + ts = cf.test(); + + ts.assertEmpty(); + + cf.connect(); + + ts.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryTest.java index 607801bd195..224ae32d405 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -621,7 +621,7 @@ public void run() { } } - /** Observer for listener on seperate thread. */ + /** Observer for listener on separate thread. */ static final class AsyncSubscriber extends DefaultSubscriber { protected CountDownLatch latch = new CountDownLatch(1); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWithPredicateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWithPredicateTest.java index b70b7422018..2180ac88736 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWithPredicateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableRetryWithPredicateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTest.java index f9ed6509dbc..1bc6456695b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSampleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -481,4 +481,10 @@ public void badRequest() { TestHelper.assertBadRequestReported(PublishProcessor.create() .sample(PublishProcessor.create())); } + + @Test + public void badRequestTimed() { + TestHelper.assertBadRequestReported(PublishProcessor.create() + .sample(1, TimeUnit.MINUTES)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMapTest.java index a4abfce00c5..fab387470e7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScalarXMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -243,4 +243,12 @@ public void cancelled() { assertTrue(scalar.isCancelled()); } + + @Test + public void mapToNonScalar() { + Flowable.fromCallable(() -> 1) + .concatMap(v -> Flowable.range(1, 5)) + .test() + .assertResult(1, 2, 3, 4, 5); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanTest.java index 2988da75700..5c6e4fa9013 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableScanTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -676,4 +676,27 @@ public Integer apply(Integer a, Integer b) throws Exception { } } } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().scanWith(() -> 1, (a, b) -> a + b)); + } + + @Test + public void drainMoreWork() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.scanWith(() -> 0, (a, b) -> a + b) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(2); + pp.onComplete(); + } + }) + .test(); + + pp.onNext(1); + + ts.assertResult(0, 1, 3); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualTest.java index e5e74e8227a..c73b57777be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSequenceEqualTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -591,4 +591,26 @@ public Flowable apply(Flowable upstream) { } }); } + + @Test + public void fusionRejected() { + Flowable.sequenceEqual(TestHelper.rejectFlowableFusion(), Flowable.never()) + .test() + .assertEmpty(); + } + + @Test + public void fusionRejectedFlowable() { + Flowable.sequenceEqual(TestHelper.rejectFlowableFusion(), Flowable.never()) + .toFlowable() + .test() + .assertEmpty(); + } + + @Test + public void asyncSourceCompare() { + Flowable.sequenceEqual(Flowable.fromCallable(() -> 1), Flowable.just(1)) + .test() + .assertResult(true); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerializeTest.java index cd848e683d8..913c598126d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -79,7 +79,22 @@ public void multiThreadedBasic() { } @Test - public void multiThreadedWithNPE() { + public void multiThreadedWithNPEFlaky() throws InterruptedException { + int max = 9; + for (int i = 0; i <= max; i++) { + try { + multiThreadedWithNPE(); + return; + } catch (AssertionError ex) { + if (i == max) { + throw ex; + } + } + Thread.sleep((long)(1000 * Math.random() + 100)); + } + } + + void multiThreadedWithNPE() { TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable("one", "two", "three", null); Flowable w = Flowable.unsafeCreate(onSubscribe); @@ -108,7 +123,22 @@ public void multiThreadedWithNPE() { } @Test - public void multiThreadedWithNPEinMiddle() { + public void multiThreadedWithNPEinMiddleFlaky() throws InterruptedException { + int max = 9; + for (int i = 0; i <= max; i++) { + try { + multiThreadedWithNPEinMiddle(); + return; + } catch (AssertionError ex) { + if (i == max) { + throw ex; + } + } + Thread.sleep((long)(1000 * Math.random() + 100)); + } + } + + void multiThreadedWithNPEinMiddle() { boolean lessThan9 = false; for (int i = 0; i < 3; i++) { TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable("one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleTest.java index 099f63f0495..85fbfbc00d0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -805,4 +805,9 @@ public void singleOrError() { .test() .assertFailure(NoSuchElementException.class); } + + @Test + public void dispose() { + TestHelper.checkDisposed(PublishProcessor.create().single(1)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTest.java index 7b1fb2a45fe..69eac72c541 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimedTest.java index 87f4ddf881a..f2f1ff25981 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipLastTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -250,4 +250,27 @@ public void observeOn() { .assertComplete() .assertNoErrors(); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().skipLast(1, TimeUnit.MINUTES)); + } + + @Test + public void delayErrorMoreWork() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.skipLast(0, TimeUnit.MILLISECONDS, true) + .doOnNext(v -> { + if (v == 1) { + pp.onNext(1); + pp.onComplete(); + } + }) + .test(); + + pp.onNext(1); + + ts.assertComplete(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTest.java index cb902082c39..eac3c94df83 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTimedTest.java index 74532ad63ca..82012097e74 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntilTest.java index b579f0e5d6c..d5bbdf969a3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhileTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhileTest.java index 3ab4f9af640..3fd42350d21 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhileTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSkipWhileTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java index 68f4ee62727..6aa442c00b5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOnTest.java index a9f66d733eb..01ee614fd52 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,6 +27,7 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.operators.flowable.FlowableSubscribeOn.SubscribeOnSubscriber; +import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subscribers.*; @@ -201,7 +202,7 @@ public void onNext(Integer t) { System.out.println("First schedule: " + t); assertTrue(t.getName().startsWith("Rx")); ts.request(10); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(20, TimeUnit.SECONDS); System.out.println("After reschedule: " + ts.lastThread()); assertEquals(t, ts.lastThread()); } @@ -253,7 +254,7 @@ public void onNext(Integer t) { } }).subscribeOn(Schedulers.newThread()).subscribe(ts); - ts.awaitDone(5, TimeUnit.SECONDS); + ts.awaitDone(20, TimeUnit.SECONDS); ts.assertNoErrors(); } @@ -329,7 +330,7 @@ public void subscribe(FlowableEmitter s) throws Exception { .subscribeOn(Schedulers.single()) .observeOn(Schedulers.computation()) .test() - .awaitDone(5, TimeUnit.SECONDS) + .awaitDone(20, TimeUnit.SECONDS) .assertNoErrors() .assertComplete(); @@ -354,7 +355,7 @@ public void subscribe(FlowableEmitter s) throws Exception { .subscribeOn(Schedulers.single()) .observeOn(Schedulers.computation()) .test() - .awaitDone(5, TimeUnit.SECONDS) + .awaitDone(20, TimeUnit.SECONDS) .assertValueCount(Flowable.bufferSize()) .assertNoErrors() .assertComplete(); @@ -376,7 +377,7 @@ public void subscribe(FlowableEmitter s) throws Exception { .subscribeOn(Schedulers.single(), false) .observeOn(Schedulers.computation()) .test() - .awaitDone(5, TimeUnit.SECONDS) + .awaitDone(20, TimeUnit.SECONDS) .assertNoErrors() .assertComplete(); @@ -401,9 +402,14 @@ public void subscribe(FlowableEmitter s) throws Exception { .subscribeOn(Schedulers.single(), true) .observeOn(Schedulers.computation()) .test() - .awaitDone(5, TimeUnit.SECONDS) + .awaitDone(20, TimeUnit.SECONDS) .assertValueCount(Flowable.bufferSize()) .assertNoErrors() .assertComplete(); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().subscribeOn(ImmediateThinScheduler.INSTANCE)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmptyTest.java index de348ee6a0f..d38a657b992 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchIfEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchTest.java index fb571c11092..9f200e3c566 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableSwitchTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.*; import org.junit.*; import org.mockito.InOrder; @@ -32,7 +32,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ExceptionHelper; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subscribers.*; import io.reactivex.rxjava3.testsupport.*; @@ -1076,7 +1076,7 @@ protected void subscribeActual(Subscriber s) { } }), 8) .test(1L) - .assertFailure(MissingBackpressureException.class, 0); + .assertFailure(QueueOverflowException.class, 0); } @Test @@ -1229,4 +1229,167 @@ public Publisher apply(Integer v) .test() .assertResult(10, 20); } + + @Test + public void asyncFusedInner() { + Flowable.just(1) + .hide() + .switchMap(v -> Flowable.fromCallable(() -> 1)) + .test() + .assertResult(1); + } + + @Test + public void innerIgnoresCancelAndErrors() throws Throwable { + TestHelper.withErrorTracking(errors -> { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp + .switchMap(v -> { + if (v == 1) { + return Flowable.unsafeCreate(s -> { + s.onSubscribe(new BooleanSubscription()); + pp.onNext(2); + s.onError(new TestException()); + }); + } + return Flowable.never(); + }) + .test(); + + pp.onNext(1); + + ts.assertEmpty(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.switchMap(v -> Flowable.never())); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().switchMap(v -> Flowable.never())); + } + + @Test + public void innerFailed() { + BehaviorProcessor.createDefault(Flowable.error(new TestException())) + .switchMap(v -> v) + .test() + .assertFailure(TestException.class) + ; + } + + @Test + public void innerCompleted() { + BehaviorProcessor.createDefault(Flowable.empty().hide()) + .switchMap(v -> v) + .test() + .assertEmpty() + ; + } + + @Test + public void innerCompletedBackpressureBoundary() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = BehaviorProcessor.createDefault(pp) + .onBackpressureBuffer() + .switchMap(v -> v) + .test(1L) + ; + + ts.assertEmpty(); + + pp.onNext(1); + pp.onComplete(); + + ts.assertValuesOnly(1); + } + + @Test + public void innerCompletedDelayError() { + BehaviorProcessor.createDefault(Flowable.empty().hide()) + .switchMapDelayError(v -> v) + .test() + .assertEmpty() + ; + } + + @Test + public void innerCompletedBackpressureBoundaryDelayError() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = BehaviorProcessor.createDefault(pp) + .onBackpressureBuffer() + .switchMapDelayError(v -> v) + .test(1L) + ; + + ts.assertEmpty(); + + pp.onNext(1); + pp.onComplete(); + + ts.assertValuesOnly(1); + } + + @Test + public void cancellationShouldTriggerInnerCancellationRace() throws Throwable { + AtomicInteger outer = new AtomicInteger(); + AtomicInteger inner = new AtomicInteger(); + + int n = 10_000; + for (int i = 0; i < n; i++) { + Flowable.create(it -> { + it.onNext(0); + }, BackpressureStrategy.MISSING) + .switchMap(v -> createFlowable(inner)) + .observeOn(Schedulers.computation()) + .doFinally(() -> { + outer.incrementAndGet(); + }) + .take(1) + .blockingSubscribe(v -> { }, Throwable::printStackTrace); + } + + Thread.sleep(100); + assertEquals(inner.get(), outer.get()); + assertEquals(n, inner.get()); + } + + Flowable createFlowable(AtomicInteger inner) { + return Flowable.unsafeCreate(s -> { + SerializedSubscriber it = new SerializedSubscriber<>(s); + it.onSubscribe(new BooleanSubscription()); + Schedulers.io().scheduleDirect(() -> { + it.onNext(1); + }, 0, TimeUnit.MILLISECONDS); + Schedulers.io().scheduleDirect(() -> { + it.onNext(2); + }, 0, TimeUnit.MILLISECONDS); + }) + .doFinally(() -> { + inner.incrementAndGet(); + }); + } + + @Test + public void innerOnSubscribeOuterCancelRace() { + TestSubscriber ts = new TestSubscriber(); + + Flowable.just(1) + .hide() + .switchMap(v -> Flowable.just(1) + .doOnSubscribe(d -> ts.cancel()) + .scan(1, (a, b) -> a) + ) + .subscribe(ts); + + ts.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOneTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOneTest.java index 373fe4fbe47..1e51a402499 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOneTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastOneTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTest.java index de6a4318447..6008461ed5b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,8 +23,9 @@ import org.junit.Test; import org.mockito.InOrder; -import org.reactivestreams.Subscriber; +import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; @@ -340,4 +341,54 @@ public void takeLastTake() { .test() .assertResult(6, 7); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().takeLast(2)); + } + + @Test + public void cancelThenRequest() { + Flowable.never().takeLast(2) + .subscribe(new FlowableSubscriber() { + + @Override + public void onNext(@NonNull Object t) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + } + + @Override + public void onSubscribe(@NonNull Subscription s) { + s.cancel(); + s.request(1); + } + }); + } + + @Test + public void noRequestEmpty() { + Flowable.empty() + .takeLast(2) + .test(0L) + .assertResult(); + } + + @Test + public void moreValuesRemainingThanRequested() { + Flowable.range(1, 4) + .takeLast(3) + .test(0L) + .assertEmpty() + .requestMore(2) + .assertValuesOnly(2, 3) + .requestMore(2) + .assertResult(2, 3, 4); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimedTest.java index 836700d2aa0..83814dd797b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeLastTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest.java index fa9ea0725d8..50728f62064 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest2.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest2.java index 089c1480991..da2aa5657e7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest2.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTest2.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTimedTest.java index 34d39b125af..776236a7cd6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicateTest.java index 4019ec4fd90..f88b7e27ae6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilPredicateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilTest.java index 150143ba6fe..a1f7fe9d42b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhileTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhileTest.java index f2c964cf286..805420f094c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhileTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTakeWhileTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTest.java index d26d49019a0..68a559e3cdc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleFirstTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,6 +19,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import io.reactivex.rxjava3.functions.Action; import org.junit.*; import org.mockito.InOrder; import org.reactivestreams.*; @@ -44,6 +45,77 @@ public void before() { subscriber = TestHelper.mockSubscriber(); } + @Test + public void throttlingWithDropCallbackCrashes() throws Throwable { + Flowable source = Flowable.unsafeCreate(new Publisher() { + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + publishNext(subscriber, 100, "one"); // publish as it's first + publishNext(subscriber, 300, "two"); // skip as it's last within the first 400 + publishNext(subscriber, 900, "three"); // publish + publishNext(subscriber, 905, "four"); // skip + publishCompleted(subscriber, 1000); // Should be published as soon as the timeout expires. + } + }); + + Action whenDisposed = mock(Action.class); + + Flowable sampled = source + .doOnCancel(whenDisposed) + .throttleFirst(400, TimeUnit.MILLISECONDS, scheduler, e -> { + if ("two".equals(e)) { + throw new TestException("forced"); + } + }); + sampled.subscribe(subscriber); + + InOrder inOrder = inOrder(subscriber); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(subscriber, times(1)).onNext("one"); + inOrder.verify(subscriber, times(1)).onError(any(TestException.class)); + inOrder.verify(subscriber, times(0)).onNext("two"); + inOrder.verify(subscriber, times(0)).onNext("three"); + inOrder.verify(subscriber, times(0)).onNext("four"); + inOrder.verify(subscriber, times(0)).onComplete(); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void throttlingWithDropCallback() { + Flowable source = Flowable.unsafeCreate(new Publisher() { + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new BooleanSubscription()); + publishNext(subscriber, 100, "one"); // publish as it's first + publishNext(subscriber, 300, "two"); // skip as it's last within the first 400 + publishNext(subscriber, 900, "three"); // publish + publishNext(subscriber, 905, "four"); // skip + publishCompleted(subscriber, 1000); // Should be published as soon as the timeout expires. + } + }); + + Observer dropCallbackObserver = TestHelper.mockObserver(); + Flowable sampled = source.throttleFirst(400, TimeUnit.MILLISECONDS, scheduler, dropCallbackObserver::onNext); + sampled.subscribe(subscriber); + + InOrder inOrder = inOrder(subscriber); + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(subscriber, times(1)).onNext("one"); + inOrder.verify(subscriber, times(0)).onNext("two"); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("two"); + inOrder.verify(subscriber, times(1)).onNext("three"); + inOrder.verify(subscriber, times(0)).onNext("four"); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("four"); + inOrder.verify(subscriber, times(1)).onComplete(); + inOrder.verifyNoMoreInteractions(); + dropCallbackOrder.verifyNoMoreInteractions(); + } + @Test public void throttlingWithCompleted() { Flowable source = Flowable.unsafeCreate(new Publisher() { @@ -200,4 +272,14 @@ public void backpressureNoRequest() { .test(0L) .assertFailure(MissingBackpressureException.class); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().throttleFirst(1, TimeUnit.MINUTES)); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.throttleFirst(1, TimeUnit.MINUTES)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatestTest.java index 45457f55778..2b26ec98d41 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableThrottleLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,10 +23,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.subscriptions.EmptySubscription; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.TestScheduler; import io.reactivex.rxjava3.subscribers.TestSubscriber; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FlowableThrottleLatestTest extends RxJavaTest { @@ -278,4 +279,480 @@ public void onNext(Integer t) { ts.assertResult(1, 2); } + + /** Emit 1, 2, 3, then advance time by a second; 1 and 3 should end up in downstream, 2 should be dropped. */ + @Test + public void onDroppedBasicNoEmitLast() { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriber ts = pp.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(3); + + ts.assertValuesOnly(1); + drops.assertValuesOnly(2); + + sch.advanceTimeBy(1, TimeUnit.SECONDS); + + ts.assertValuesOnly(1, 3); + drops.assertValuesOnly(2); + + pp.onComplete(); + + ts.assertResult(1, 3); + + drops.assertValuesOnly(2); + } + + /** Emit 1, 2, 3; 1 should end up in downstream, 2, 3 should be dropped. */ + @Test + public void onDroppedBasicNoEmitLastDropLast() { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriber ts = pp.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(3); + + ts.assertValuesOnly(1); + drops.assertValuesOnly(2); + + pp.onComplete(); + + ts.assertResult(1); + + drops.assertValuesOnly(2, 3); + } + + /** Emit 1, 2, 3; 1 and 3 should end up in downstream, 2 should be dropped. */ + @Test + public void onDroppedBasicEmitLast() { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriber ts = pp.throttleLatest(1, TimeUnit.SECONDS, sch, true, drops::onNext) + .test(); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(2); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onNext(3); + + ts.assertValuesOnly(1); + drops.assertValuesOnly(2); + + pp.onComplete(); + + ts.assertResult(1, 3); + + drops.assertValuesOnly(2); + } + + /** Emit 1, 2, 3; 3 should trigger an error to the downstream because 2 is dropped and the callback crashes. */ + @Test + public void onDroppedBasicNoEmitLastFirstDropCrash() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriber ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { + if (d == 2) { + throw new TestException("forced"); + } + }) + .test(); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + pp.onNext(3); + + ts.assertFailure(TestException.class, 1); + + verify(whenDisposed).run(); + } + + /** + * Emit 1, 2, Error; the error should trigger the drop callback and crash it too, + * downstream gets 1, composite(source, drop-crash). + */ + @Test + public void onDroppedBasicNoEmitLastOnErrorDropCrash() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + pp.onError(new TestException("source")); + + ts.assertFailure(CompositeException.class, 1); + + TestHelper.assertCompositeExceptions(ts, TestException.class, "source", TestException.class, "forced 2"); + + verify(whenDisposed, never()).run(); + } + + /** + * Emit 1, 2, 3; 3 should trigger a drop-crash for 2, which then would trigger the error path and drop-crash for 3, + * the last item not delivered, downstream gets 1, composite(drop-crash 2, drop-crash 3). + */ + @Test + public void onDroppedBasicEmitLastOnErrorDropCrash() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, true, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + pp.onNext(3); + + ts.assertFailure(CompositeException.class, 1); + + TestHelper.assertCompositeExceptions(ts, TestException.class, "forced 2", TestException.class, "forced 3"); + + verify(whenDisposed).run(); + } + + /** Emit 1, complete; Downstream gets 1, complete, no drops. */ + @Test + public void onDroppedBasicNoEmitLastNoLastToDrop() { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriber ts = pp.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onComplete(); + + ts.assertResult(1); + drops.assertEmpty(); + } + + /** Emit 1, error; Downstream gets 1, error, no drops. */ + @Test + public void onDroppedErrorNoEmitLastNoLastToDrop() { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriber ts = pp.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + pp.onError(new TestException()); + + ts.assertFailure(TestException.class, 1); + drops.assertEmpty(); + } + + /** + * Emit 1, 2, complete; complete should crash drop, downstream gets 1, drop-crash 2. + */ + @Test + public void onDroppedHasLastNoEmitLastDropCrash() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + pp.onComplete(); + + ts.assertFailureAndMessage(TestException.class, "forced 2", 1); + + verify(whenDisposed, never()).run(); + } + + /** + * Emit 1, 2 then dispose the sequence; downstream gets 1, drop should get for 2. + */ + @Test + public void onDroppedDisposeDrops() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + ts.cancel(); + + ts.assertValuesOnly(1); + drops.assertValuesOnly(2); + + verify(whenDisposed).run(); + } + + /** + * Emit 1 then dispose the sequence; downstream gets 1, drop should not get called. + */ + @Test + public void onDroppedDisposeNoDrops() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + ts.cancel(); + + ts.assertValuesOnly(1); + drops.assertEmpty(); + + verify(whenDisposed).run(); + } + + /** + * Emit 1, 2 then dispose the sequence; downstream gets 1, global error handler should get drop-crash 2. + */ + @Test + public void onDroppedDisposeCrashesDrop() throws Throwable { + TestHelper.withErrorTracking(errors -> { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestSubscriberEx<>()); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertValuesOnly(1); + + pp.onNext(2); + + ts.assertValuesOnly(1); + + ts.cancel(); + + ts.assertValuesOnly(1); + + verify(whenDisposed).run(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "forced 2"); + }); + } + + /** Emit 1 but downstream is backpressured; downstream gets MBE, drops gets 1. */ + @Test + public void onDroppedBackpressured() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + TestSubscriber drops = new TestSubscriber<>(); + drops.onSubscribe(EmptySubscription.INSTANCE); + + Action whenDisposed = mock(Action.class); + + TestSubscriber ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(0L); + + ts.assertEmpty(); + drops.assertEmpty(); + + pp.onNext(1); + + ts.assertFailure(MissingBackpressureException.class); + + drops.assertValuesOnly(1); + + verify(whenDisposed).run(); + } + + /** Emit 1 but downstream is backpressured; drop crashes, downstream gets composite(MBE, drop-crash 1). */ + @Test + public void onDroppedBackpressuredDropCrash() throws Throwable { + PublishProcessor pp =PublishProcessor.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestSubscriberEx ts = pp + .doOnCancel(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestSubscriberEx<>(0L)); + + ts.assertEmpty(); + + pp.onNext(1); + + ts.assertFailure(CompositeException.class); + + TestHelper.assertCompositeExceptions(ts, + MissingBackpressureException.class, "Could not emit value due to lack of requests", + TestException.class, "forced 1"); + + verify(whenDisposed).run(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeIntervalTest.java index 4153c92a222..e2e9550388d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTests.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTests.java index 88a3bc22531..070bb620b01 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTests.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; -import io.reactivex.rxjava3.schedulers.TestScheduler; +import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -528,4 +528,9 @@ public void run() { } } } + + @Test + public void doubleOnSubscribeFallback() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.timeout(1, TimeUnit.MINUTES, Flowable.never())); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutWithSelectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutWithSelectorTest.java index 7e55fa0d773..538a8e566a4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutWithSelectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimeoutWithSelectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -32,6 +32,7 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableTimeout.TimeoutConsumer; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; @@ -894,4 +895,13 @@ protected void subscribeActual(Subscriber s) { RxJavaPlugins.reset(); } } + + @Test + public void timeoutConsumerIsDisposed() { + TimeoutConsumer consumer = new TimeoutConsumer(0, null); + + assertFalse(consumer.isDisposed()); + consumer.dispose(); + assertTrue(consumer.isDisposed()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimerTest.java index e23228f9433..4f0216e6121 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -352,7 +352,7 @@ public void timerDelayZero() { public void timerInterruptible() throws Exception { ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); try { - for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) { + for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec, true) }) { final AtomicBoolean interrupted = new AtomicBoolean(); TestSubscriber ts = Flowable.timer(1, TimeUnit.MILLISECONDS, s) .map(new Function() { @@ -380,4 +380,9 @@ public Long apply(Long v) throws Exception { exec.shutdown(); } } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.timer(1, TimeUnit.MINUTES)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimestampTest.java index 05274da6190..6d98c0c4140 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimestampTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableTimestampTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToCompletableTest.java index cac1fa61b7e..dff5a7462ba 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToCompletableTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.flowable; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToFutureTest.java index 4241dc8be91..8501a22e74a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToFutureTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListTest.java index cad29e3fc88..208f371bb77 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToListTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMapTest.java index 149a3f893c4..736cf4caa51 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMultimapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMultimapTest.java index 06e71d6beb3..63db446ee69 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMultimapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToMultimapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSingleTest.java index b88824b583a..d064589b1d8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSortedListTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSortedListTest.java index 5c7278da545..cadcb572b61 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSortedListTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableToSortedListTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOnTest.java index 1f37dbddce8..2a8efa4593c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUnsubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,6 +26,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Action; +import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -274,4 +275,9 @@ protected void subscribeActual(Subscriber subscriber) { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.unsubscribeOn(ImmediateThinScheduler.INSTANCE)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsingTest.java index f32b599df44..d744c327475 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableUsingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithFlowableTest.java index 66273656f94..5f5d97af1e0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -623,6 +623,7 @@ public void run() { } @Test + @SuppressUndeliverable public void disposeMainBoundaryErrorRace() { final TestException ex = new TestException(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithSizeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithSizeTest.java index fbefcc953e3..bd50a20a2a4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithSizeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithSizeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,6 +25,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; @@ -605,4 +606,210 @@ public void accept(Flowable v) throws Throwable { inner.get().test().assertResult(1); } + + @Test + public void badRequestExact() { + TestHelper.assertBadRequestReported(Flowable.never().window(1)); + } + + @Test + public void badRequestSkip() { + TestHelper.assertBadRequestReported(Flowable.never().window(1, 2)); + } + + @Test + public void badRequestOverlap() { + TestHelper.assertBadRequestReported(Flowable.never().window(2, 1)); + } + + @Test + public void skipEmpty() { + Flowable.empty() + .window(1, 2) + .test() + .assertResult(); + } + + @Test + public void exactEmpty() { + Flowable.empty() + .window(2) + .test() + .assertResult(); + } + + @Test + public void skipMultipleRequests() { + Flowable.range(1, 10) + .window(1, 2) + .doOnNext(w -> w.test()) + .rebatchRequests(1) + .test() + .assertComplete(); + } + + @Test + public void skipOne() { + Flowable.just(1) + .window(2, 3) + .flatMap(v -> v) + .test() + .assertResult(1); + } + + @Test + public void overlapMultipleRequests() { + Flowable.range(1, 10) + .window(2, 1) + .doOnNext(w -> w.test()) + .rebatchRequests(1) + .test() + .assertComplete(); + } + + @Test + public void overlapCancelAfterWindow() { + Flowable.range(1, 10) + .window(2, 1) + .takeUntil(v -> true) + .doOnNext(w -> w.test()) + .test(0L) + .requestMore(10) + .assertComplete(); + } + + @Test + public void overlapEmpty() { + Flowable.empty() + .window(2, 1) + .test() + .assertResult(); + } + + @Test + public void overlapEmptyNoRequest() { + Flowable.empty() + .window(2, 1) + .test(0L) + .assertResult(); + } + + @Test + public void overlapMoreWorkAfterOnNext() { + PublishProcessor pp = PublishProcessor.create(); + AtomicBoolean once = new AtomicBoolean(); + + TestSubscriber> ts = pp.window(2, 1) + .doOnNext(v -> { + v.test(); + if (once.compareAndSet(false, true)) { + pp.onNext(2); + pp.onComplete(); + } + }) + .test(); + + pp.onNext(1); + + ts.assertComplete(); + } + + @Test + public void moreQueuedClean() { + Flowable.range(1, 10) + .window(5, 1) + .doOnNext(w -> w.test()) + .test(3) + .cancel(); + } + + @Test + public void cancelWithoutWindowSize() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10) + .test(); + + assertTrue(pp.hasSubscribers()); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } + + @Test + public void cancelAfterAbandonmentSize() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10) + .test(); + + assertTrue(pp.hasSubscribers()); + + pp.onNext(1); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } + + @Test + public void cancelWithoutWindowSkip() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10, 15) + .test(); + + assertTrue(pp.hasSubscribers()); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } + + @Test + public void cancelAfterAbandonmentSkip() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10, 15) + .test(); + + assertTrue(pp.hasSubscribers()); + + pp.onNext(1); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } + + @Test + public void cancelWithoutWindowOverlap() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10, 5) + .test(); + + assertTrue(pp.hasSubscribers()); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } + + @Test + public void cancelAfterAbandonmentOverlap() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(10, 5) + .test(); + + assertTrue(pp.hasSubscribers()); + + pp.onNext(1); + + ts.cancel(); + + assertFalse("Subject still has subscribers!", pp.hasSubscribers()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithStartEndFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithStartEndFlowableTest.java index 023f6848d58..f2431eb8db9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithStartEndFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithStartEndFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,6 +15,7 @@ import static org.junit.Assert.*; +import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.*; @@ -31,7 +32,7 @@ import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.TestScheduler; import io.reactivex.rxjava3.subscribers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FlowableWindowWithStartEndFlowableTest extends RxJavaTest { @@ -233,20 +234,20 @@ public void dispose() { @Test public void reentrant() { - final FlowableProcessor ps = PublishProcessor.create(); + final FlowableProcessor pp = PublishProcessor.create(); TestSubscriber ts = new TestSubscriber() { @Override public void onNext(Integer t) { super.onNext(t); if (t == 1) { - ps.onNext(2); - ps.onComplete(); + pp.onNext(2); + pp.onComplete(); } } }; - ps.window(BehaviorProcessor.createDefault(1), Functions.justFunction(Flowable.never())) + pp.window(BehaviorProcessor.createDefault(1), Functions.justFunction(Flowable.never())) .flatMap(new Function, Flowable>() { @Override public Flowable apply(Flowable v) throws Exception { @@ -255,7 +256,7 @@ public Flowable apply(Flowable v) throws Exception { }) .subscribe(ts); - ps.onNext(1); + pp.onNext(1); ts .awaitDone(1, TimeUnit.SECONDS) @@ -323,6 +324,7 @@ public Flowable apply(Integer v) throws Exception { } @Test + @SuppressUndeliverable public void endError() { PublishProcessor source = PublishProcessor.create(); PublishProcessor start = PublishProcessor.create(); @@ -539,4 +541,179 @@ public Publisher apply(Integer end) throws Throwable { assertFalse(boundary.hasSubscribers()); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(o -> o.window(Flowable.never(), v -> Flowable.never())); + } + + @Test + public void openError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestException ex1 = new TestException(); + TestException ex2 = new TestException(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Flowable f1 = Flowable.fromPublisher(ref1::set); + Flowable f2 = Flowable.fromPublisher(ref2::set); + + TestSubscriber> ts = BehaviorProcessor.createDefault(1) + .window(f1, v -> f2) + .doOnNext(w -> w.test()) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + ref2.get().onSubscribe(new BooleanSubscription()); + + TestHelper.race( + () -> ref1.get().onError(ex1), + () -> ref2.get().onError(ex2) + ); + + ts.assertError(RuntimeException.class); + + if (!errors.isEmpty()) { + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } + + errors.clear(); + } + }); + } + + @Test + public void closeError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Flowable f1 = Flowable.unsafeCreate(ref1::set); + Flowable f2 = Flowable.unsafeCreate(ref2::set); + + TestSubscriber ts = BehaviorProcessor.createDefault(1) + .window(f1, v -> f2) + .flatMap(v -> v) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + ref2.get().onSubscribe(new BooleanSubscription()); + + ref2.get().onError(new TestException()); + ref2.get().onError(new TestException()); + + ts.assertFailure(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void upstreamFailsBeforeFirstWindow() { + Flowable.error(new TestException()) + .window(Flowable.never(), v -> Flowable.never()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void windowOpenMainCompletes() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishProcessor pp = PublishProcessor.create(); + Flowable f1 = Flowable.unsafeCreate(ref1::set); + + AtomicInteger counter = new AtomicInteger(); + + TestSubscriber> ts = pp + .window(f1, v -> Flowable.never()) + .doOnNext(w -> { + if (counter.getAndIncrement() == 0) { + ref1.get().onNext(2); + pp.onNext(1); + pp.onComplete(); + } + w.test(); + }) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + + ts.assertComplete(); + } + + @Test + public void windowOpenMainError() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishProcessor pp = PublishProcessor.create(); + Flowable f1 = Flowable.unsafeCreate(ref1::set); + + AtomicInteger counter = new AtomicInteger(); + + TestSubscriber> ts = pp + .window(f1, v -> Flowable.never()) + .doOnNext(w -> { + if (counter.getAndIncrement() == 0) { + ref1.get().onNext(2); + pp.onNext(1); + pp.onError(new TestException()); + } + w.test(); + }) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + + ts.assertError(TestException.class); + } + + @Test + public void windowOpenIgnoresDispose() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishProcessor pp = PublishProcessor.create(); + Flowable f1 = Flowable.unsafeCreate(ref1::set); + + TestSubscriber> ts = pp + .window(f1, v -> Flowable.never()) + .take(1) + .doOnNext(w -> { + w.test(); + }) + .test(); + + ref1.get().onSubscribe(new BooleanSubscription()); + ref1.get().onNext(1); + ref1.get().onNext(2); + + ts.assertValueCount(1); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().window(Flowable.never(), v -> Flowable.never())); + } + + @Test + public void mainIgnoresCancelBeforeOnError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable.fromPublisher(s -> { + s.onSubscribe(new BooleanSubscription()); + s.onNext(1); + s.onError(new IOException()); + }) + .window(BehaviorProcessor.createDefault(1), v -> Flowable.error(new TestException())) + .doOnNext(w -> w.test()) + .test() + .assertError(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithTimeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithTimeTest.java index e3d9466b3e6..6982b00ceac 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithTimeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWindowWithTimeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -31,7 +31,7 @@ import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subscribers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FlowableWindowWithTimeTest extends RxJavaTest { @@ -556,6 +556,7 @@ public void restartTimer() { } @Test + @SuppressUndeliverable public void exactBoundaryError() { Flowable.error(new TestException()) .window(1, TimeUnit.DAYS, Schedulers.single(), 2, true) @@ -973,6 +974,7 @@ public void accept(Flowable v) throws Exception { } @Test + @SuppressUndeliverable public void exactTimeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -1053,6 +1055,7 @@ public void accept(Flowable v) throws Exception { } @Test + @SuppressUndeliverable public void exactTimeAndSizeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -1133,6 +1136,7 @@ public void accept(Flowable v) throws Exception { } @Test + @SuppressUndeliverable public void skipTimeAndSizeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -1321,5 +1325,27 @@ public void accept(Flowable v) throws Throwable { inner.get().test().assertResult(); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Flowable.never().window(1, TimeUnit.SECONDS)); + } + + @Test + public void timedBoundarySignalAndDisposeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestScheduler scheduler = new TestScheduler(); + + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber> ts = pp.window(1, TimeUnit.MINUTES, scheduler, 1) + .test(); + + TestHelper.race( + () -> pp.onNext(1), + () -> ts.cancel() + ); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromTest.java index 655452057b1..df325cd2c81 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableWithLatestFromTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipCompletionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipCompletionTest.java index 3de4aa1e39f..fe69ea6be52 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipCompletionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipCompletionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterableTest.java index 871b603383b..aee49596d92 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipTest.java index 614dc28aaa6..8d3e10dbd27 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableZipTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,8 +30,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueSubscription; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -1870,7 +1870,7 @@ public Integer apply(Integer a, Integer b) throws Exception { public void firstErrorPreventsSecondSubscription() { final AtomicInteger counter = new AtomicInteger(); - List> flowableList = new ArrayList<>(); + List> flowableList = new ArrayList<>(); flowableList.add(Flowable.create(new FlowableOnSubscribe() { @Override public void subscribe(FlowableEmitter e) @@ -1914,4 +1914,30 @@ public Integer apply(Object[] t) throws Throwable { .test() .assertResult(2); } + + @Test + public void fusedInnerPollCrashDelayError() { + Flowable.zip( + Flowable.range(1, 5), + Flowable.just(1) + .map(v -> { throw new TestException(); }) + .compose(TestHelper.flowableStripBoundary()), + (a, b) -> a + b, true + ) + .test() + .assertFailure(TestException.class); + } + + @Test + public void fusedInnerPollCrashRequestBoundaryDelayError() { + Flowable.zip( + Flowable.range(1, 5), + Flowable.just(1) + .map(v -> { throw new TestException(); }) + .compose(TestHelper.flowableStripBoundary()), + (a, b) -> a + b, true + ) + .test(0L) + .assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/NotificationLiteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/NotificationLiteTest.java index 3a5ff0dc570..2c4b42aa9c4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/NotificationLiteTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/NotificationLiteTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstreamTest.java index 0e953b262f3..dca854d3c15 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/AbstractMaybeWithUpstreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmbTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmbTest.java index fb3a6aff5b5..54750101639 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmbTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeAmbTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java index 647d385eef4..e11548cdc99 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCacheTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCacheTest.java index a8d42ef6035..80f61f5931c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserverTest.java index e65b01e0702..1758a1116b0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCallbackObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java index 6608fbc4242..94e77bf55ad 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayTest.java index 301a8a35f5f..c2d6fcc0ae6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,12 +18,13 @@ import java.io.IOException; import java.util.List; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -188,4 +189,79 @@ public void subscribe(MaybeEmitter s) throws Exception { assertEquals(1, calls[0]); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Maybe.concatArray(MaybeSubject.create(), MaybeSubject.create())); + } + + @Test + public void badRequestDelayError() { + TestHelper.assertBadRequestReported(Maybe.concatArrayDelayError(MaybeSubject.create(), MaybeSubject.create())); + } + + @Test + public void mixed() { + Maybe.concatArray( + Maybe.just(1), + Maybe.empty(), + Maybe.just(2), + Maybe.empty(), + Maybe.empty() + ) + .test() + .assertResult(1, 2); + } + + @Test + public void requestBeforeSuccess() { + MaybeSubject ms = MaybeSubject.create(); + TestSubscriber ts = Maybe.concatArray(ms, ms) + .test(); + + ts.assertEmpty(); + + ms.onSuccess(1); + + ts.assertResult(1, 1); + } + + @Test + public void requestBeforeComplete() { + MaybeSubject ms = MaybeSubject.create(); + TestSubscriber ts = Maybe.concatArray(ms, ms) + .test(); + + ts.assertEmpty(); + + ms.onComplete(); + + ts.assertResult(); + } + + @Test + public void requestBeforeSuccessDelayError() { + MaybeSubject ms = MaybeSubject.create(); + TestSubscriber ts = Maybe.concatArrayDelayError(ms, ms) + .test(); + + ts.assertEmpty(); + + ms.onSuccess(1); + + ts.assertResult(1, 1); + } + + @Test + public void requestBeforeCompleteDelayError() { + MaybeSubject ms = MaybeSubject.create(); + TestSubscriber ts = Maybe.concatArrayDelayError(ms, ms) + .test(); + + ts.assertEmpty(); + + ms.onComplete(); + + ts.assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java index 5a1b42bb151..4c53fcddf3c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterableTest.java index 7450dc993bd..c8b90452636 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,6 +24,7 @@ import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.util.CrashingMappedIterable; import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -158,4 +159,12 @@ public void subscribe(MaybeEmitter s) throws Exception { assertEquals(1, calls[0]); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(Maybe.concat(Arrays.asList( + MaybeSubject.create(), + MaybeSubject.create() + ))); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java index e902bbf4df4..dedd03a02ee 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java index 2626b18e26e..93695b52937 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java index 7504117df4a..04e5abfafd0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatPublisherTest.java index 527de9734bf..ad334cac7b0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.maybe; import java.util.concurrent.Callable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContainsTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContainsTest.java index 07a7abc77ba..ca019517d80 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContainsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeContainsTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCountTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCountTest.java index 669cb4e28c8..b223358ef27 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCountTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCountTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreateTest.java index b0857c432fc..6bd42bce441 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherTest.java index 8ca50837ec6..f482834e297 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayOtherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionTest.java index bca4023f83d..dae5d6f68c7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelaySubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -141,4 +141,9 @@ protected void subscribeActual(Subscriber subscriber) { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribePublisher() { + TestHelper.checkDoubleOnSubscribeFlowableToMaybe(f -> Maybe.just(1).delaySubscription(f)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java index 14448c3f2c1..4485f58f5ed 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java index 5c75a92a100..4f78295f76f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetachTest.java index 2c96cbfe884..6498e98371e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDetachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccessTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccessTest.java index 045f23de64c..a961f0b11c2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccessTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoAfterSuccessTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinallyTest.java index fe54a5a2996..f98c3cf810a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEventTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEventTest.java index abe91714e78..37614ec7938 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEventTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnEventTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java index b8921b7eb91..39d71105ca5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminateTest.java index cfcb6a548f5..4471db0ee1d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnTerminateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmptyTest.java index c477416241e..a2197189364 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; public class MaybeEmptyTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualTest.java index 8a42f12d5b1..e7b6ea4302a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeEqualTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorTest.java index b75eea1906b..f67dc7884b9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingleTest.java index 2647f760ce3..52682cc208c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFilterSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelectorTest.java index f0db482a621..67227bb4227 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapBiSelectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletableTest.java index a76af597b28..053f1e3e401 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowableTest.java index 1c840a22951..e4bcaa9f77d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,10 +24,11 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -120,6 +121,20 @@ public Iterable apply(Integer v) throws Exception { .assertResult(1); } + @Test + public void take2() { + Maybe.just(1).flattenAsFlowable(new Function>() { + @Override + public Iterable apply(Integer v) throws Exception { + return Arrays.asList(v, v + 1); + } + }) + .doOnSubscribe(s -> s.request(Long.MAX_VALUE)) + .take(1) + .test() + .assertResult(1); + } + @Test public void fused() { TestSubscriberEx ts = new TestSubscriberEx().setInitialFusionMode(QueueFuseable.ANY); @@ -562,4 +577,33 @@ public void remove() { ts.request(Long.MAX_VALUE); ts.assertValues(1, 1).assertNoErrors().assertNotComplete(); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(MaybeSubject.create().flattenAsFlowable(v -> Arrays.asList(v))); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybeToFlowable(m -> m.flattenAsFlowable(v -> Arrays.asList(v))); + } + + @Test + public void onSuccessRequestRace() { + List list = Arrays.asList(1); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + MaybeSubject ms = MaybeSubject.create(); + + TestSubscriber ts = ms.flattenAsFlowable(v -> list) + .test(0L); + + TestHelper.race( + () -> ms.onSuccess(1), + () -> ts.request(1) + ); + + ts.assertResult(1); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservableTest.java index 601da820a79..d06f6261195 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapIterableObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,8 +25,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotificationTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotificationTest.java index 6faec2ab9a5..1d4d4f0d5ef 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java index cc92e023ab8..2f5cf424260 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java index 4904678a61a..cdf7f36f1f2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlattenTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlattenTest.java index bcdaa3f061a..30c0cfdeb80 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlattenTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlattenTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromActionTest.java index 4f1cc273555..32f37c1cd78 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromActionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromActionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallableTest.java index 70c432f5ae0..dec0d8e33e8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCallableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -213,4 +213,18 @@ public String answer(InvocationOnMock invocation) throws Throwable { verify(observer).onSubscribe(any(Disposable.class)); verifyNoMoreInteractions(observer); } + + @Test + public void disposeUpfront() { + Maybe.fromCallable(() -> 1) + .test(true) + .assertEmpty(); + } + + @Test + public void success() { + Maybe.fromCallable(() -> 1) + .test() + .assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletableTest.java index c891714b695..40f00e371ab 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFutureTest.java index 98ea62255e0..fb88c60a721 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromFutureTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java index de2039a4d00..311f33e4d42 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java index bcbef3dc9f5..c51c23bae41 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnableTest.java index 37325c69c83..5d1db4ad4d3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingleTest.java index 108c38d30fc..27c13626f6e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplierTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplierTest.java index 247021b12b0..bcbe0783ccf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplierTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromSupplierTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -214,4 +214,23 @@ public String answer(InvocationOnMock invocation) throws Throwable { verify(observer).onSubscribe(any(Disposable.class)); verifyNoMoreInteractions(observer); } + + @Test + public void success() { + Maybe.fromSupplier(() -> 1) + .test() + .assertResult(1); + } + + @Test + public void disposeUpfront() throws Throwable { + @SuppressWarnings("unchecked") + Supplier supplier = mock(Supplier.class); + + Maybe.fromSupplier(supplier) + .test(true) + .assertEmpty(); + + verify(supplier, never()).get(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHideTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHideTest.java index 4428b576999..11a1cbb1458 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHideTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeHideTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementTest.java index c41def19d3c..a7ab2f20240 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIgnoreElementTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingleTest.java index 5a6021a48bf..23ead596390 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptySingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptyTest.java index a7c208d2b58..a3a4a893c9f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeIsEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJustTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJustTest.java index 6e61427a155..a49ac11a41a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJustTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeJustTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; +import io.reactivex.rxjava3.operators.ScalarSupplier; public class MaybeJustTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMapTest.java index 52598869767..b58b78b26f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterializeTest.java index 57a478d112e..0c7f5704348 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArrayTest.java index 6b886fd8947..bf4f7313dc8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeArrayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,16 +17,17 @@ import java.util.*; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; import org.reactivestreams.Subscription; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.maybe.MaybeMergeArray.MergeMaybeObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -250,4 +251,25 @@ public void onComplete() { } }); } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported( + Maybe.mergeArray(MaybeSubject.create(), MaybeSubject.create()) + ); + } + + @Test + public void cancel2() { + TestHelper.checkDisposed(Maybe.mergeArray(MaybeSubject.create(), MaybeSubject.create())); + } + + @Test + public void take() { + Maybe.mergeArray(Maybe.just(1), Maybe.empty(), Maybe.just(2)) + .doOnSubscribe(s -> s.request(Long.MAX_VALUE)) + .take(1) + .test() + .assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeTest.java index 8ce37cb7bec..0bf38ccc0fe 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeWithTest.java index ab4a0b89553..dd4d0817a8c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMergeWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOfTypeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOfTypeTest.java index 0e459ffffbd..5d58b9ff906 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOfTypeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOfTypeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorXTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorXTest.java index 403d73db666..2cbc2fe427b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorXTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorXTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeekTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeekTest.java index cbf4d60b34b..ade9039ecaa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeekTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybePeekTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java index 5083c20f2c8..85919751d4c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java index 87969974d4f..31b03141580 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOnTest.java index 1043a848b8b..3f5a29bc239 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java index ceed4345d30..153b183287e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptyTest.java index 423d6ad1ac8..f15f5ae8be7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchIfEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchOnNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchOnNextTest.java index 6b217aa6809..7a502faa28c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchOnNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSwitchOnNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisherTest.java index e615c733e87..f5ce2495148 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilTest.java index 5c7d8f956d5..20ce1cfa417 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTakeUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java index 30b770aed4d..bd50202ae45 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisherTest.java index 188db935976..efa2ce6ff69 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,9 @@ import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.observers.TestObserver; @@ -231,4 +233,29 @@ public Object apply(Flowable f) throws Exception { } }, false, null, 1, 1); } + + @Test + public void mainSuccessAfterOtherSignal() { + PublishProcessor pp = PublishProcessor.create(); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + pp.onNext(2); + observer.onSuccess(1); + } + } + .timeout(pp) + .test() + .assertFailure(TimeoutException.class); + } + + @Test + public void mainSuccess() { + Maybe.just(1) + .timeout(Flowable.never()) + .test() + .assertResult(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutTest.java index 7e30ce6a49d..b5b61a6ffca 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeoutTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,12 +19,15 @@ import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.testsupport.*; public class MaybeTimeoutTest extends RxJavaTest { @@ -341,4 +344,21 @@ public void run() { } } } + + @Test + public void mainSuccessAfterOtherSignal() { + MaybeSubject ms = MaybeSubject.create(); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + ms.onSuccess(2); + observer.onSuccess(1); + } + } + .timeout(ms) + .test() + .assertFailure(TimeoutException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimerTest.java index 06a54ad90c2..05ffdf0562b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ public void dispose() { public void timerInterruptible() throws Exception { ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); try { - for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) { + for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec, true) }) { final AtomicBoolean interrupted = new AtomicBoolean(); TestObserver to = Maybe.timer(1, TimeUnit.MILLISECONDS, s) .map(new Function() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java index 1ce230f8d00..935147a9060 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToCompletableTest.java index 52b44e5f989..4bae2cc98f2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowableTest.java index 77d098c0ce7..66e94da8d0e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java index 37723dc6562..b36a299cd46 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservableTest.java index c201bf20f8c..67472037237 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingleTest.java index 9d641c9505b..1ee84470f2c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOnTest.java index 1e2d7001361..3159fb411e1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUnsubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsingTest.java index c9ff65e09ab..0f083c93d25 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeUsingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -481,6 +481,7 @@ public void run() { } @Test + @SuppressUndeliverable public void errorDisposeRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArrayTest.java index c685e79cae0..2cbf8e42633 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipArrayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,17 +15,21 @@ import static org.junit.Assert.*; -import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.testsupport.TestHelper; public class MaybeZipArrayTest extends RxJavaTest { @@ -168,4 +172,70 @@ public void singleSourceZipperReturnsNull() { .to(TestHelper.testConsumer()) .assertFailureAndMessage(NullPointerException.class, "The zipper returned a null value"); } + + @Test + public void dispose2() { + TestHelper.checkDisposed(Maybe.zipArray(v -> v, MaybeSubject.create(), MaybeSubject.create())); + } + + @Test + public void bothComplete() { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Maybe m1 = new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + ref1.set(observer); + } + }; + Maybe m2 = new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + ref2.set(observer); + } + }; + + TestObserver to = Maybe.zipArray(v -> v, m1, m2) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref2.get().onSubscribe(Disposable.empty()); + + ref1.get().onComplete(); + ref2.get().onComplete(); + + to.assertResult(); + } + + @Test + public void bothSucceed() { + Maybe.zipArray(v -> Arrays.asList(v), Maybe.just(1), Maybe.just(2)) + .test() + .assertResult(Arrays.asList(1, 2)); + } + + @Test + public void oneSourceOnly() { + Maybe.zipArray(v -> Arrays.asList(v), Maybe.just(1)) + .test() + .assertResult(Arrays.asList(1)); + } + + @Test + public void onSuccessAfterDispose() { + AtomicReference> emitter = new AtomicReference<>(); + + TestObserver> to = Maybe.zipArray(Arrays::asList, + (MaybeSource)o -> emitter.set(o), Maybe.never()) + .test(); + + emitter.get().onSubscribe(Disposable.empty()); + + to.dispose(); + + emitter.get().onSuccess(1); + + to.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterableTest.java index 4f6e07f00a8..2d60c22157c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeZipIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservableTest.java index 9c8dfa8754c..a1e087bdf2f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisherTest.java index 9c0a498db59..bd9c9aa2d9d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/CompletableAndThenPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletableTest.java index 28c90619bbb..44acad42b12 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.subjects.CompletableSubject; import io.reactivex.rxjava3.testsupport.*; @@ -66,6 +66,14 @@ public void simpleLongPrefetch() { .assertResult(); } + @Test + public void simpleLongPrefetchHidden() { + Flowable.range(1, 1024).hide() + .concatMapCompletable(Functions.justFunction(Completable.complete()), 32) + .test() + .assertResult(); + } + @Test public void mainError() { Flowable.error(new TestException()) @@ -277,7 +285,7 @@ protected void subscribeActual(Subscriber s) { Functions.justFunction(Completable.never()), 1 ) .test() - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); TestHelper.assertUndeliverable(errors, 0, TestException.class); } finally { @@ -431,4 +439,54 @@ public Completable apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Flowable.range(1, 5).hide() + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicSyncFused() { + Flowable.range(1, 5) + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicAsyncFused() { + UnicastProcessor up = UnicastProcessor.create(); + TestHelper.emit(up, 1, 2, 3, 4, 5); + + up + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectFlowableFusion() + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Flowable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.flowableStripBoundary()) + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybeTest.java index 8a60f6c367d..12b61a5e8cd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,11 +19,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; @@ -31,7 +31,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; @@ -54,15 +54,19 @@ public MaybeSource apply(Integer v) } @Test - public void simpleLong() { + public void simpleLongPrefetch() { Flowable.range(1, 1024) - .concatMapMaybe(new Function>() { - @Override - public MaybeSource apply(Integer v) - throws Exception { - return Maybe.just(v); - } - }, 32) + .concatMapMaybe(Maybe::just, 32) + .test() + .assertValueCount(1024) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void simpleLongPrefetchHidden() { + Flowable.range(1, 1024).hide() + .concatMapMaybe(Maybe::just, 32) .test() .assertValueCount(1024) .assertNoErrors() @@ -245,7 +249,7 @@ protected void subscribeActual(Subscriber s) { Functions.justFunction(Maybe.never()), 1 ) .test() - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); TestHelper.assertUndeliverable(errors, 0, TestException.class); } finally { @@ -464,4 +468,54 @@ public Maybe apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Flowable.range(1, 5).hide() + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicSyncFused() { + Flowable.range(1, 5) + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicAsyncFused() { + UnicastProcessor up = UnicastProcessor.create(); + TestHelper.emit(up, 1, 2, 3, 4, 5); + + up + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectFlowableFusion() + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Flowable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.flowableStripBoundary()) + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingleTest.java index a2e5d73c093..60cb2f5de0b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -52,15 +52,19 @@ public SingleSource apply(Integer v) } @Test - public void simpleLong() { + public void simpleLongPrefetch() { Flowable.range(1, 1024) - .concatMapSingle(new Function>() { - @Override - public SingleSource apply(Integer v) - throws Exception { - return Single.just(v); - } - }, 32) + .concatMapSingle(Single::just, 32) + .test() + .assertValueCount(1024) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void simpleLongPrefetchHidden() { + Flowable.range(1, 1024).hide() + .concatMapSingle(Single::just, 32) .test() .assertValueCount(1024) .assertNoErrors() @@ -163,7 +167,7 @@ protected void subscribeActual(Subscriber s) { Functions.justFunction(Single.never()), 1 ) .test() - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); TestHelper.assertUndeliverable(errors, 0, TestException.class); } finally { @@ -382,4 +386,54 @@ public Single apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Flowable.range(1, 5).hide() + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicSyncFused() { + Flowable.range(1, 5) + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicAsyncFused() { + UnicastProcessor up = UnicastProcessor.create(); + TestHelper.emit(up, 1, 2, 3, 4, 5); + + up + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectFlowableFusion() + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Flowable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.flowableStripBoundary()) + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletableTest.java index bf18f90b056..cf2065cc72b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybeTest.java index 8fd4b55d6f4..1ace07440fc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingleTest.java index a28413ab42f..cd4d64a9eb8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableSwitchMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservableTest.java index 0b268e8d882..f91b5c6582c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisherTest.java index b7853ccac01..96948b05dc4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletableTest.java index 540e0828afe..e69e3e0ee50 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -474,4 +474,54 @@ public Completable apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Observable.range(1, 5).hide() + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicSyncFused() { + Observable.range(1, 5) + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicAsyncFused() { + UnicastSubject us = UnicastSubject.create(); + TestHelper.emit(us, 1, 2, 3, 4, 5); + + us + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertResult(); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectObservableFusion() + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Observable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.observableStripBoundary()) + .concatMapCompletable(v -> Completable.complete().hide()) + .test() + .assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybeTest.java index 323cbc32701..0dcbd274080 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -485,4 +485,54 @@ public Maybe apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Observable.range(1, 5).hide() + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicSyncFused() { + Observable.range(1, 5) + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicAsyncFused() { + UnicastSubject us = UnicastSubject.create(); + TestHelper.emit(us, 1, 2, 3, 4, 5); + + us + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectObservableFusion() + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Observable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.observableStripBoundary()) + .concatMapMaybe(v -> Maybe.just(v).hide()) + .test() + .assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingleTest.java index 90f15ac2509..9f70b4addf7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -425,4 +425,54 @@ public Single apply(Integer v) throws Throwable { } }); } + + @Test + public void basicNonFused() { + Observable.range(1, 5).hide() + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicSyncFused() { + Observable.range(1, 5) + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicAsyncFused() { + UnicastSubject us = UnicastSubject.create(); + TestHelper.emit(us, 1, 2, 3, 4, 5); + + us + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertResult(1, 2, 3, 4, 5); + } + + @Test + public void basicFusionRejected() { + TestHelper.rejectObservableFusion() + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertEmpty(); + } + + @Test + public void fusedPollCrash() { + Observable.range(1, 5) + .map(v -> { + if (v == 3) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.observableStripBoundary()) + .concatMapSingle(v -> Single.just(v).hide()) + .test() + .assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletableTest.java index 33ce7c27dac..0efeb6f676a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybeTest.java index 865544b22a6..b2eabdd96fe 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingleTest.java index d5de085a1e1..a98afae4de9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableSwitchMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelperTest.java index 8a8e745c8bf..2ac6eed7d3b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/ScalarXMapZHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservableTest.java index 3f9fcb74dee..a002620b6aa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstreamTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstreamTest.java index b578dcb8f6c..5d49cd8b66a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstreamTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/AbstractObservableWithUpstreamTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatestTest.java index ef8e23ba215..feac576be73 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java index cc04638ee7c..ccf611bbd4a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNextTest.java index 357d512e9b4..8274e9f9e31 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -227,8 +227,8 @@ public void nextWithCallingHasNextMultipleTimes() { /** * Confirm that no buffering or blocking of the Observable onNext calls occurs and it just grabs the next emitted value. - *

- * This results in output such as => a: 1 b: 2 c: 89 + *

+ * This results in output such as {@code => a: 1 b: 2 c: 89} * * @throws Throwable some method call is declared throws */ diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToFutureTest.java index bca24503c1a..dacf9715961 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToFutureTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToIteratorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToIteratorTest.java index 4b6e2bc5cd6..684eefbf615 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToIteratorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableToIteratorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.operators.observable.BlockingObservableIterable.BlockingObservableIterator; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -131,4 +131,13 @@ public void run() { assertFalse(it.hasNext()); } + + @Test(expected = TestException.class) + public void errorAfterDispose() { + Iterator it = Observable.error(new TestException()).blockingIterable().iterator(); + + ((Disposable)it).dispose(); + + it.hasNext(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/Burst.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/Burst.java index 2bed4358792..46b5df42f32 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/Burst.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/Burst.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.util.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllTest.java index 293607d66bc..fba37cb9f9b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAllTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -364,4 +364,14 @@ public boolean test(Integer v) throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservableToSingle(o -> o.all(v -> true)); + } + + @Test + public void doubleOnSubscribeObservable() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.all(v -> true).toObservable()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmbTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmbTest.java index 4948f1a13d1..5ec9129d9f7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmbTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAmbTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -235,7 +235,8 @@ public void ambArraySingleElement() { @Test public void manySources() { - Observable[] a = new Observable[32]; + @SuppressWarnings("unchecked") + Observable[] a = new Observable[32]; Arrays.fill(a, Observable.never()); a[31] = Observable.just(1); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnyTest.java index 35faf30c196..cb85603fa18 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAnyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnectTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnectTest.java index 5ed5b3124e6..16128ff1954 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnectTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableAutoConnectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingTest.java index a2d98545695..05fbb5a94ca 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBlockingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTest.java index af4e7a94150..7085720f013 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ import io.reactivex.rxjava3.observers.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.*; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.TestHelper; public class ObservableBufferTest extends RxJavaTest { @@ -1278,9 +1278,9 @@ public Integer apply(Integer integer, Long aLong) { } }) .buffer(Observable.interval(0, 200, TimeUnit.MILLISECONDS), - new Function>() { + new Function>() { @Override - public Observable apply(Long a) { + public Observable apply(Long a) { return Observable.just(a).delay(100, TimeUnit.MILLISECONDS); } }) @@ -1301,9 +1301,9 @@ public Integer apply(Integer integer, Long aLong) { } }) .buffer(Observable.interval(0, 100, TimeUnit.MILLISECONDS), - new Function>() { + new Function>() { @Override - public Observable apply(Long a) { + public Observable apply(Long a) { return Observable.just(a).delay(200, TimeUnit.MILLISECONDS); } }) @@ -1788,4 +1788,31 @@ public List get() throws Exception { .assertFailure(TestException.class) ; } + + @Test + public void timedUnboundedCancelUpfront() { + Observable.never() + .buffer(1, TimeUnit.SECONDS) + .test(true) + .assertEmpty(); + } + + @Test + public void boundaryCloseCompleteRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + BehaviorSubject bs = BehaviorSubject.createDefault(1); + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = bs + .buffer(BehaviorSubject.createDefault(0), v -> ps) + .test(); + + TestHelper.race( + () -> bs.onComplete(), + () -> ps.onComplete() + ); + + to.assertResult(Arrays.asList(1)); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferUntilSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferUntilSubscriberTest.java index 6d49272de26..eb67fee441c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferUntilSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableBufferUntilSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCacheTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCacheTest.java index 8f4440e41b9..74d17c062b2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,16 +16,21 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryUsage; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.observables.ConnectableObservable; import org.junit.Test; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.observers.TestObserver; @@ -341,4 +346,66 @@ public Object call() throws Exception { assertEquals(1, call.get()); } + + @Test + public void addRemoveRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + Observable o = Observable.never().cache(); + + TestObserver to = o.test(); + + TestHelper.race( + () -> to.dispose(), + () -> o.test() + ); + } + } + + @Test + public void valuesAreReclaimable() throws Exception { + ConnectableObservable source = + Observable.range(0, 200) + .map($ -> new byte[1024 * 1024]) + .publish(); + + System.out.println("Bounded Replay Leak check: Wait before GC"); + Thread.sleep(1000); + + System.out.println("Bounded Replay Leak check: GC"); + System.gc(); + + Thread.sleep(500); + + final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + MemoryUsage memHeap = memoryMXBean.getHeapMemoryUsage(); + long initial = memHeap.getUsed(); + + System.out.printf("Bounded Replay Leak check: Starting: %.3f MB%n", initial / 1024.0 / 1024.0); + + final AtomicLong after = new AtomicLong(); + + source.cache().lastElement().subscribe(new Consumer() { + @Override + public void accept(byte[] v) throws Exception { + System.out.println("Bounded Replay Leak check: Wait before GC 2"); + Thread.sleep(1000); + + System.out.println("Bounded Replay Leak check: GC 2"); + System.gc(); + + Thread.sleep(500); + + after.set(memoryMXBean.getHeapMemoryUsage().getUsed()); + } + }); + + source.connect(); + + System.out.printf("Bounded Replay Leak check: After: %.3f MB%n", after.get() / 1024.0 / 1024.0); + + if (initial + 100 * 1024 * 1024 < after.get()) { + fail("Bounded Replay Leak check: Memory leak detected: " + (initial / 1024.0 / 1024.0) + + " -> " + after.get() / 1024.0 / 1024.0); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCastTest.java index 52576fb9b9f..83fdb4b1e53 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectTest.java index 0568b0d4749..92867c2d795 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCollectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatestTest.java index e304a27a33e..2b966ec29ca 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCombineLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.*; import org.junit.Test; import org.mockito.*; @@ -1226,4 +1226,76 @@ public Integer apply(Object[] t) throws Throwable { .test() .assertResult(2); } + + @Test + public void onCompleteDisposeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + TestObserver to = new TestObserver<>(); + PublishSubject ps = PublishSubject.create(); + + Observable.combineLatest(ps, Observable.never(), (a, b) -> a) + .subscribe(to); + + TestHelper.race(() -> ps.onComplete(), () -> to.dispose()); + } + } + + @Test + public void onErrorDisposeDelayErrorRace() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestException ex = new TestException(); + + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + TestObserverEx to = new TestObserverEx<>(); + AtomicReference> ref = new AtomicReference<>(); + Observable o = new Observable() { + @Override + public void subscribeActual(Observer observer) { + ref.set(observer); + } + }; + + Observable.combineLatestDelayError(Arrays.asList(o, Observable.never()), (a) -> a) + .subscribe(to); + + ref.get().onSubscribe(Disposable.empty()); + + TestHelper.race(() -> ref.get().onError(ex), () -> to.dispose()); + + if (to.errors().isEmpty()) { + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } + } + }); + } + + @Test + public void doneButNotEmpty() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = Observable.combineLatest(ps1, ps2, (a, b) -> a + b) + .doOnNext(v -> { + if (v == 2) { + ps2.onNext(3); + ps2.onComplete(); + ps1.onComplete(); + } + }) + .test(); + + ps1.onNext(1); + ps2.onNext(1); + + to.assertResult(2, 4); + } + + @Test + public void iterableNullPublisher() { + Observable.combineLatest(Arrays.asList(Observable.never(), null), (a) -> a) + .test() + .assertFailure(NullPointerException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapCompletableTest.java index 55b880a9f99..931fcd403f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapCompletableTest.java @@ -1,15 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at - *

+ * * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java index 054ab91d8fc..1e75ff9aef8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -1078,4 +1078,13 @@ public void observerDelayErrorMaxConcurrency() { .test() .assertFailure(TestException.class, 1, 2, 3, 4, 5); } + + @Test + public void innerFusionRejected() { + Observable.just(1) + .hide() + .concatMapEager(v -> TestHelper.rejectObservableFusion()) + .test() + .assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapSchedulerTest.java index a82553b9a4e..f2a6ede3144 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,14 +20,16 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.observers.*; @@ -305,7 +307,7 @@ public Observable apply(Integer t) throws Throwable { } @Test - public void issue2890NoStackoverflow() throws InterruptedException { + public void issue2890NoStackoverflow() throws InterruptedException, TimeoutException { final ExecutorService executor = Executors.newFixedThreadPool(2); final Scheduler sch = Schedulers.from(executor); @@ -350,7 +352,11 @@ public void onError(Throwable e) { } }); - executor.awaitTermination(20000, TimeUnit.MILLISECONDS); + long awaitTerminationTimeout = 100_000; + if (!executor.awaitTermination(awaitTerminationTimeout, TimeUnit.MILLISECONDS)) { + throw new TimeoutException("Completed " + counter.get() + "/" + n + " before timed out after " + + awaitTerminationTimeout + " milliseconds."); + } assertEquals(n, counter.get()); } @@ -1049,4 +1055,70 @@ public Observable apply(Integer v) throws Throwable { } }); } + + @Test + public void fusionRejected() { + TestObserverEx to = new TestObserverEx<>(); + + TestHelper.rejectObservableFusion() + .concatMap(v -> Observable.never(), 2, ImmediateThinScheduler.INSTANCE) + .subscribe(to); + } + + @Test + public void fusionRejectedDelayErrorr() { + TestObserverEx to = new TestObserverEx<>(); + + TestHelper.rejectObservableFusion() + .concatMapDelayError(v -> Observable.never(), true, 2, ImmediateThinScheduler.INSTANCE) + .subscribe(to); + } + + @Test + public void scalarInnerJustDisposeDelayError() { + TestObserver to = new TestObserver<>(); + + Observable.just(1) + .hide() + .concatMapDelayError(v -> Observable.fromCallable(() -> { + to.dispose(); + return 1; + }), true, 2, ImmediateThinScheduler.INSTANCE) + .subscribe(to); + + to.assertEmpty(); + } + + static final class EmptyDisposingObservable extends Observable + implements Supplier { + final TestObserver to; + EmptyDisposingObservable(TestObserver to) { + this.to = to; + } + + @Override + protected void subscribeActual(@NonNull Observer observer) { + EmptyDisposable.complete(observer); + } + + @Override + public @NonNull Object get() throws Throwable { + to.dispose(); + return null; + } + } + + @Test + public void scalarInnerEmptyDisposeDelayError() { + TestObserver to = new TestObserver<>(); + + Observable.just(1) + .hide() + .concatMapDelayError(v -> new EmptyDisposingObservable(to), + true, 2, ImmediateThinScheduler.INSTANCE + ) + .subscribe(to); + + to.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapTest.java index a5d2a6aa4cc..8fb29f2eb49 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,11 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.operators.observable.ObservableConcatMapSchedulerTest.EmptyDisposingObservable; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.*; @@ -565,4 +566,108 @@ public Observable apply(Integer v) throws Throwable { } }); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.concatMap(v -> Observable.never())); + } + + @Test + public void doubleOnSubscribeDelayError() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.concatMapDelayError(v -> Observable.never())); + } + + @Test + public void scalarXMap() { + Observable.fromCallable(() -> 1) + .concatMap(v -> Observable.just(2).hide()) + .test() + .assertResult(2); + } + + @Test + public void rejectedFusion() { + TestHelper.rejectObservableFusion() + .concatMap(v -> Observable.never()) + .test(); + } + + @Test + public void rejectedFusionDelayError() { + TestHelper.rejectObservableFusion() + .concatMapDelayError(v -> Observable.never()) + .test(); + } + + @Test + public void asyncFusedDelayError() { + UnicastSubject uc = UnicastSubject.create(); + + TestObserver to = uc.concatMapDelayError(v -> Observable.just(v).hide()) + .test(); + + uc.onNext(1); + uc.onComplete(); + + to.assertResult(1); + } + + @Test + public void scalarInnerJustDelayError() { + Observable.just(1) + .hide() + .concatMapDelayError(v -> Observable.just(v)) + .test() + .assertResult(1); + } + + @Test + public void scalarInnerEmptyDelayError() { + Observable.just(1) + .hide() + .concatMapDelayError(v -> Observable.empty()) + .test() + .assertResult(); + } + + @Test + public void scalarInnerJustDisposeDelayError() { + TestObserver to = new TestObserver<>(); + + Observable.just(1) + .hide() + .concatMapDelayError(v -> Observable.fromCallable(() -> { + to.dispose(); + return 1; + })) + .subscribe(to); + + to.assertEmpty(); + } + + @Test + public void scalarInnerEmptyDisposeDelayError() { + TestObserver to = new TestObserver<>(); + + Observable.just(1) + .hide() + .concatMapDelayError(v -> new EmptyDisposingObservable(to)) + .subscribe(to); + + to.assertEmpty(); + } + + @Test + public void delayErrorInnerActive() { + PublishSubject ps = PublishSubject.create(); + + TestObserver to = Observable.range(1, 5) + .hide() + .concatMapDelayError(v -> ps) + .test(); + + ps.onComplete(); + + to.assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatTest.java index 90e3dc112b2..d14f803ee9c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -683,7 +683,7 @@ public void subscribe(Observer observer) { } @Test - public void issue2890NoStackoverflow() throws InterruptedException { + public void issue2890NoStackoverflow() throws InterruptedException, TimeoutException { final ExecutorService executor = Executors.newFixedThreadPool(2); final Scheduler sch = Schedulers.from(executor); @@ -728,7 +728,11 @@ public void onError(Throwable e) { } }); - executor.awaitTermination(20000, TimeUnit.MILLISECONDS); + long awaitTerminationTimeout = 100_000; + if (!executor.awaitTermination(awaitTerminationTimeout, TimeUnit.MILLISECONDS)) { + throw new TimeoutException("Completed " + counter.get() + "/" + n + " before timed out after " + + awaitTerminationTimeout + " milliseconds."); + } assertEquals(n, counter.get()); } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletableTest.java index fc2a8b8531c..5e0d878a345 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybeTest.java index 16ba059b8b6..6c70e75a9d0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingleTest.java index 2d05b58c2d6..8ac2519c3c6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatWithSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountTest.java index 4207fee66f0..13905028165 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCountTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreateTest.java index a0faf3179b0..0b96fae6aaf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,19 +17,23 @@ import java.io.IOException; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Cancellable; +import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.testsupport.*; public class ObservableCreateTest extends RxJavaTest { @Test + @SuppressUndeliverable public void basic() { final Disposable d = Disposable.empty(); @@ -55,6 +59,7 @@ public void subscribe(ObservableEmitter e) throws Exception { } @Test + @SuppressUndeliverable public void basicWithCancellable() { final Disposable d1 = Disposable.empty(); final Disposable d2 = Disposable.empty(); @@ -88,6 +93,7 @@ public void cancel() throws Exception { } @Test + @SuppressUndeliverable public void basicWithError() { final Disposable d = Disposable.empty(); @@ -112,6 +118,7 @@ public void subscribe(ObservableEmitter e) throws Exception { } @Test + @SuppressUndeliverable public void basicSerialized() { final Disposable d = Disposable.empty(); @@ -139,6 +146,7 @@ public void subscribe(ObservableEmitter e) throws Exception { } @Test + @SuppressUndeliverable public void basicWithErrorSerialized() { final Disposable d = Disposable.empty(); @@ -206,6 +214,7 @@ public void unsafeWithObservable() { } @Test + @SuppressUndeliverable public void createNullValue() { final Throwable[] error = { null }; @@ -229,6 +238,7 @@ public void subscribe(ObservableEmitter e) throws Exception { } @Test + @SuppressUndeliverable public void createNullValueSerialized() { final Throwable[] error = { null }; @@ -654,4 +664,96 @@ public void subscribe(ObservableEmitter emitter) throws Exception { } }).test().assertEmpty(); } + + @Test + public void emptySerialized() { + Observable.create(emitter -> emitter.serialize().onComplete()) + .test() + .assertResult(); + } + + @Test + public void serializedDisposedBeforeOnNext() { + TestObserver to = new TestObserver<>(); + + Observable.create(emitter -> { + to.dispose(); + emitter.serialize().onNext(1); + }) + .subscribe(to); + + to.assertEmpty(); + } + + @Test + public void serializedOnNextAfterComplete() { + TestObserver to = new TestObserver<>(); + + Observable.create(emitter -> { + emitter = emitter.serialize(); + + emitter.onComplete(); + emitter.onNext(1); + }) + .subscribe(to); + + to.assertResult(); + } + + @Test + public void serializedEnqueueAndDrainRace() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestObserver to = new TestObserver<>(); + AtomicReference> ref = new AtomicReference<>(); + + CountDownLatch cdl = new CountDownLatch(1); + + Observable.create(emitter -> { + emitter = emitter.serialize(); + ref.set(emitter); + emitter.onNext(1); + }) + .doOnNext(v -> { + if (v == 1) { + TestHelper.raceOther(() -> { + ref.get().onNext(2); + }, cdl); + ref.get().onNext(3); + } + }) + .subscribe(to); + + cdl.await(); + + to.assertValueCount(3); + } + } + + @Test + public void serializedDrainDoneButNotEmpty() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestObserver to = new TestObserver<>(); + AtomicReference> ref = new AtomicReference<>(); + + CountDownLatch cdl = new CountDownLatch(1); + + Observable.create(emitter -> { + emitter = emitter.serialize(); + ref.set(emitter); + emitter.onNext(1); + }) + .doOnNext(v -> { + if (v == 1) { + TestHelper.raceOther(() -> { + ref.get().onNext(2); + ref.get().onComplete(); + }, cdl); + ref.get().onNext(3); + } + }) + .subscribe(to); + + cdl.await(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTest.java index d59431a6775..fc4e7d8478d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDebounceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import io.reactivex.rxjava3.functions.Action; import org.junit.*; import org.mockito.InOrder; import org.reactivestreams.Publisher; @@ -50,6 +51,76 @@ public void before() { innerScheduler = scheduler.createWorker(); } + @Test + public void debounceWithOnDroppedCallbackWithEx() throws Throwable { + Observable source = Observable.unsafeCreate(new ObservableSource() { + @Override + public void subscribe(Observer observer) { + observer.onSubscribe(Disposable.empty()); + publishNext(observer, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. + publishNext(observer, 400, "two"); // Should be published since "three" will arrive after the timeout expires. + publishNext(observer, 900, "three"); // Should be skipped since onComplete will arrive before the timeout expires. + publishNext(observer, 999, "four"); // Should be skipped since onComplete will arrive before the timeout expires. + publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. + } + }); + + Action whenDisposed = mock(Action.class); + Observable sampled = source + .doOnDispose(whenDisposed) + .debounce(400, TimeUnit.MILLISECONDS, scheduler, e -> { + if ("three".equals(e)) { + throw new TestException("forced"); + } + }); + sampled.subscribe(observer); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(observer); + // must go to 800 since it must be 400 after when two is sent, which is at 400 + scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("two"); + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onError(any(TestException.class)); + inOrder.verify(observer, never()).onNext("three"); + inOrder.verify(observer, never()).onNext("four"); + inOrder.verify(observer, never()).onComplete(); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void debounceWithOnDroppedCallback() { + Observable source = Observable.unsafeCreate(new ObservableSource() { + @Override + public void subscribe(Observer observer) { + observer.onSubscribe(Disposable.empty()); + publishNext(observer, 100, "one"); // Should be skipped since "two" will arrive before the timeout expires. + publishNext(observer, 400, "two"); // Should be published since "three" will arrive after the timeout expires. + publishNext(observer, 900, "three"); // Should be skipped since onComplete will arrive before the timeout expires. + publishNext(observer, 999, "four"); // Should be skipped since onComplete will arrive before the timeout expires. + publishCompleted(observer, 1000); // Should be published as soon as the timeout expires. + } + }); + + Observer drops = TestHelper.mockObserver(); + InOrder inOrderDrops = inOrder(drops); + Observable sampled = source.debounce(400, TimeUnit.MILLISECONDS, scheduler, drops::onNext); + sampled.subscribe(observer); + + scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); + InOrder inOrder = inOrder(observer); + // must go to 800 since it must be 400 after when two is sent, which is at 400 + scheduler.advanceTimeTo(800, TimeUnit.MILLISECONDS); + inOrderDrops.verify(drops, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onNext("two"); + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrderDrops.verify(drops, times(1)).onNext("three"); + inOrder.verify(observer, times(1)).onComplete(); + inOrder.verifyNoMoreInteractions(); + inOrderDrops.verifyNoMoreInteractions(); + } + @Test public void debounceWithCompleted() { Observable source = Observable.unsafeCreate(new ObservableSource() { @@ -489,7 +560,7 @@ protected void subscribeActual( public void timedLateEmit() { TestObserver to = new TestObserver<>(); DebounceTimedObserver sub = new DebounceTimedObserver<>( - to, 1, TimeUnit.SECONDS, new TestScheduler().createWorker()); + to, 1, TimeUnit.SECONDS, new TestScheduler().createWorker(), null); sub.onSubscribe(Disposable.empty()); @@ -517,4 +588,9 @@ public ObservableSource apply(Object o) { } }).subscribe(); } + + @Test + public void doubleOnSubscribeTime() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.debounce(1, TimeUnit.SECONDS)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefaultIfEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefaultIfEmptyTest.java index 1ca00cf1b4c..7a1d66e908c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefaultIfEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDefaultIfEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDeferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDeferTest.java index 50ded2e55a9..cb919f02ff5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDeferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDeferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOtherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOtherTest.java index 93b09456ddf..02d988c2e8a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOtherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOtherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelayTest.java index 82b60d4701d..778d2d4e64d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,6 +20,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.LockSupport; import org.junit.*; import org.mockito.InOrder; @@ -29,6 +30,7 @@ import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.SequentialDisposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.*; import io.reactivex.rxjava3.schedulers.*; @@ -978,4 +980,37 @@ public Observable apply(Integer t) throws Exception { .to(TestHelper.testConsumer()) .assertFailureAndMessage(NullPointerException.class, "The itemDelay returned a null ObservableSource"); } -} + + @Test + public void cancelShouldPreventRandomSubsequentEmissions() { + for (int attempt = 1; attempt < 100; attempt ++) { + + SequentialDisposable disposable = new SequentialDisposable(); + ConcurrentLinkedQueue sink = new ConcurrentLinkedQueue<>(); + + disposable.replace( + Observable.range(1, 10) + .delay(1, TimeUnit.MICROSECONDS, Schedulers.computation(), true) + .doOnNext(v -> { + if (v == 1) { + Schedulers.computation().scheduleDirect(disposable::dispose); + } + sink.offer(v); + }) + .subscribe()); + + LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1)); + + Integer last = null; + + while (!sink.isEmpty()) { + Integer current = sink.poll(); + + if (last != null && last + 1 != current) { + fail("Emission hole: " + last + " -> " + current); + } + + last = current; + } + } + }} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerializeTest.java index 8c7b6017ab4..e28b71a6299 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDematerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -221,16 +221,17 @@ protected void subscribeActual(Observer> observer) } @Test + @SuppressWarnings("unchecked") public void nonNotificationInstanceAfterDispose() { - new Observable>() { + new Observable() { @Override - protected void subscribeActual(Observer> observer) { + protected void subscribeActual(Observer observer) { observer.onSubscribe(Disposable.empty()); observer.onNext(Notification.createOnComplete()); - observer.onNext(Notification.createOnNext(1)); + observer.onNext(1); } } - .dematerialize(Functions.>identity()) + .dematerialize(v -> (Notification)v) .test() .assertResult(); } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetachTest.java index 95cbf96f765..5e4e3d5fce0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDetachTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import java.lang.ref.WeakReference; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctTest.java index 1f2614f2843..178f700db59 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -29,8 +29,9 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChangedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChangedTest.java index 190506aed2d..7f58ab2f892 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChangedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDistinctUntilChangedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,8 +26,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNextTest.java index 9c750bba882..8338d2c9ec5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoAfterNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,8 +24,8 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinallyTest.java index 6328a1ba4f2..3753b411275 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,8 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; @@ -519,4 +520,16 @@ public void run() throws Exception { assertEquals(Arrays.asList("onNext", "onComplete", "finally"), list); } + @Test + public void fusionRejected() { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ANY); + + TestHelper.rejectObservableFusion() + .doFinally(() -> { }) + .subscribeWith(to); + + to.assertFuseable() + .assertFusionMode(QueueFuseable.NONE); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEachTest.java index 6b8627b02bc..1f71d2b0a39 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnEachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,8 +28,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnSubscribeTest.java index 5a16beda68c..f001d28ac0c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnUnsubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnUnsubscribeTest.java index a95f372d183..5ac217725b3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnUnsubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDoOnUnsubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtTest.java index 679915dc510..8ce5cb047c2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableElementAtTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilterTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilterTest.java index 6bbb838da5d..71585b1c337 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilterTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFilterTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,7 +23,7 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFinallyTest.java index 7767ddb9fc5..9f20203ed29 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFirstTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFirstTest.java index e022144ce23..9129f1d0cd2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFirstTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFirstTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableTest.java index 95baba14484..facfb084d13 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,7 +16,7 @@ import static org.junit.Assert.*; import java.util.List; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import org.junit.Test; @@ -24,8 +24,9 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.testsupport.*; @@ -506,4 +507,59 @@ public Completable apply(Integer v) throws Throwable { } }); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.flatMapCompletable(v -> Completable.never()).toObservable()); + } + + @Test + public void doubleOnSubscribeCompletable() { + TestHelper.checkDoubleOnSubscribeObservableToCompletable(o -> o.flatMapCompletable(v -> Completable.never())); + } + + @Test + public void cancelWhileMapping() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishSubject ps1 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + + ps1.flatMapCompletable(v -> { + TestHelper.raceOther(() -> { + to.dispose(); + }, cdl); + return Completable.complete(); + }) + .toObservable() + .subscribe(to); + + ps1.onNext(1); + + cdl.await(); + } + } + + @Test + public void cancelWhileMappingCompletable() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishSubject ps1 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + + ps1.flatMapCompletable(v -> { + TestHelper.raceOther(() -> { + to.dispose(); + }, cdl); + return Completable.complete(); + }) + .subscribe(to); + + ps1.onNext(1); + + cdl.await(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybeTest.java index a1540dcfcae..0c0d29c8e7e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,14 +21,14 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.*; public class ObservableFlatMapMaybeTest extends RxJavaTest { @@ -483,4 +483,64 @@ public Maybe apply(Integer v) throws Throwable { } }); } + + @Test + public void cancelWhileMapping() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishSubject ps1 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + + ps1.flatMapMaybe(v -> { + TestHelper.raceOther(() -> { + to.dispose(); + }, cdl); + return Maybe.just(1); + }) + .subscribe(to); + + ps1.onNext(1); + + cdl.await(); + } + } + + @Test + public void successCompleteRace() { + for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { + MaybeSubject ms1 = MaybeSubject.create(); + MaybeSubject ms2 = MaybeSubject.create(); + + TestObserver to = Observable.just(1, 2) + .flatMapMaybe(v -> v == 1 ? ms1 : ms2) + .test(); + + TestHelper.race( + () -> ms1.onComplete(), + () -> ms2.onSuccess(1) + ); + + to.assertResult(1); + } + } + + @Test + public void successCompleteRace2() { + for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { + MaybeSubject ms1 = MaybeSubject.create(); + MaybeSubject ms2 = MaybeSubject.create(); + + TestObserver to = Observable.just(1, 2) + .flatMapMaybe(v -> v == 1 ? ms1 : ms2) + .test(); + + TestHelper.race( + () -> ms2.onSuccess(1), + () -> ms1.onComplete() + ); + + to.assertResult(1); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingleTest.java index b990bd407cf..1fa219111be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,14 +21,14 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.*; public class ObservableFlatMapSingleTest extends RxJavaTest { @@ -398,4 +398,69 @@ public Single apply(Integer v) throws Throwable { } }); } + + @Test + public void innerErrorOuterCompleteRace() { + TestException ex = new TestException(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishSubject ps1 = PublishSubject.create(); + SingleSubject ps2 = SingleSubject.create(); + + TestObserver to = ps1.flatMapSingle(v -> ps2) + .test(); + + ps1.onNext(1); + + TestHelper.race( + () -> ps1.onComplete(), + () -> ps2.onError(ex) + ); + + to.assertFailure(TestException.class); + } + } + + @Test + public void cancelWhileMapping() throws Throwable { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + PublishSubject ps1 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + + ps1.flatMapSingle(v -> { + TestHelper.raceOther(() -> { + to.dispose(); + }, cdl); + return Single.just(1); + }) + .subscribe(to); + + ps1.onNext(1); + + cdl.await(); + } + } + + @Test + public void onNextDrainCancel() { + SingleSubject ss1 = SingleSubject.create(); + SingleSubject ss2 = SingleSubject.create(); + + TestObserver to = new TestObserver<>(); + + Observable.just(1, 2) + .flatMapSingle(v -> v == 1 ? ss1 : ss2) + .doOnNext(v -> { + if (v == 1) { + ss2.onSuccess(2); + to.dispose(); + } + }) + .subscribe(to); + + ss1.onSuccess(1); + + to.assertValuesOnly(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapTest.java index 8dca948c815..4622888628e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,12 +17,14 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +import java.io.IOException; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import org.junit.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; @@ -1113,4 +1115,153 @@ public void innerErrorsMainCancelled() { assertFalse("Has subscribers?", ps1.hasObservers()); } + + @Test + public void signalsAfterMapperCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + observer.onSubscribe(Disposable.empty()); + observer.onNext(1); + observer.onNext(2); + observer.onComplete(); + observer.onError(new IOException()); + } + } + .flatMap(v -> { + throw new TestException(); + }) + .test() + .assertFailure(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + }); + } + + @Test + public void scalarQueueTerminate() { + PublishSubject ps = PublishSubject.create(); + TestObserver to = new TestObserver<>(); + + ps + .flatMap(v -> Observable.just(v)) + .doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + ps.onNext(3); + } + }) + .take(2) + .subscribe(to); + + ps.onNext(1); + + to.assertResult(1, 2); + } + + @Test + public void scalarQueueCompleteMain() throws Exception { + PublishSubject ps = PublishSubject.create(); + TestObserver to = new TestObserver<>(); + CountDownLatch cdl = new CountDownLatch(1); + ps + .flatMap(v -> Observable.just(v)) + .doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + TestHelper.raceOther(() -> ps.onComplete(), cdl); + } + }) + .subscribe(to); + + ps.onNext(1); + + cdl.await(); + to.assertResult(1, 2); + } + + @Test + public void fusedInnerCrash() { + UnicastSubject us = UnicastSubject.create(); + PublishSubject ps = PublishSubject.create(); + + TestObserver to = Observable.just( + ps, + us.map(v -> { + if (v == 10) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.observableStripBoundary()) + ) + .flatMap(v -> v, true) + .doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + us.onNext(10); + } + }) + .test(); + + ps.onNext(1); + ps.onComplete(); + + to.assertFailure(TestException.class, 1, 2); + } + + @Test + public void fusedInnerCrash2() { + UnicastSubject us = UnicastSubject.create(); + PublishSubject ps = PublishSubject.create(); + + TestObserver to = Observable.just( + us.map(v -> { + if (v == 10) { + throw new TestException(); + } + return v; + }) + .compose(TestHelper.observableStripBoundary()) + , ps + ) + .flatMap(v -> v, true) + .doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + us.onNext(10); + } + }) + .test(); + + ps.onNext(1); + ps.onComplete(); + + to.assertFailure(TestException.class, 1, 2); + } + + @Test(timeout = 5000) + public void mixedScalarAsync() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + Observable + .range(0, 20) + .flatMap( + integer -> { + if (integer % 5 != 0) { + return Observable + .just(integer); + } + + return Observable + .just(-integer) + .observeOn(Schedulers.computation()); + }, + false, + 1 + ) + .ignoreElements() + .blockingAwait(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterableTest.java index 2fdf6b24f3c..15d6aae37bd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFlattenIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -96,4 +96,9 @@ public void remove() { assertEquals(1, counter.get()); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.flatMapIterable(v -> Collections.singletonList(v))); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableForEachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableForEachTest.java index 677b78414fd..ac8312a8935 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableForEachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableForEachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java index 2b6d80896aa..eb201665074 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,8 +24,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallableTest.java index 43b1d96fefa..c701f60c476 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCallableTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.observable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java index 6cdc0108d6b..6cfd2eb0ada 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,8 +24,9 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; @@ -192,4 +193,16 @@ public void syncFusedRejected() throws Throwable { verify(action).run(); } + + @Test + public void disposed() { + TestHelper.checkDisposed(Observable.fromCompletable(Completable.never())); + } + + @Test + public void upstream() { + Observable o = Observable.fromCompletable(Completable.never()); + assertTrue(o instanceof HasUpstreamCompletableSource); + assertSame(Completable.never(), ((HasUpstreamCompletableSource)o).source()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterableTest.java index a3c546933a3..b816baf4b08 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -29,9 +29,10 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; import io.reactivex.rxjava3.observers.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.*; public class ObservableFromIterableTest extends RxJavaTest { @@ -345,4 +346,28 @@ public void onComplete() { } }); } + + @Test + public void disposeAfterHasNext() { + TestObserver to = new TestObserver<>(); + + Observable.fromIterable(() -> new Iterator() { + int count; + @Override + public boolean hasNext() { + if (count++ == 2) { + to.dispose(); + return false; + } + return true; + } + + @Override + public Integer next() { + return 1; + } + }) + .subscribeWith(to) + .assertValuesOnly(1, 1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java index 185b363d572..e0175b4a595 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.MaybeSubject; import io.reactivex.rxjava3.testsupport.TestObserverEx; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java index 834abbd978d..b566f66775f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,8 +25,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Supplier; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java index d77498cea8f..aaabb513b34 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,8 +19,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.testsupport.TestObserverEx; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplierTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplierTest.java index 2b181a56fe9..56e31ddfb78 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplierTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSupplierTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.operators.observable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromTest.java index e3f6f919542..639d3c4d14d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,7 +21,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.ScalarSupplier; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerateTest.java index 19735a3ad4b..90a3d60eaf1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGenerateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -194,4 +194,17 @@ public void accept(Emitter e) throws Exception { .test() .assertResult(); } + + @Test + public void onNextAfterOnComplete() { + Observable.generate(new Consumer>() { + @Override + public void accept(Emitter e) throws Exception { + e.onComplete(); + e.onNext(1); + } + }) + .test() + .assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupByTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupByTest.java index 28d3f2d6432..32c1abc2e2f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupByTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupByTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,14 +27,14 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observables.GroupedObservable; import io.reactivex.rxjava3.observers.*; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.*; public class ObservableGroupByTest extends RxJavaTest { @@ -96,6 +96,7 @@ public void empty() { } @Test + @SuppressUndeliverable public void error() { Observable sourceStrings = Observable.just("one", "two", "three", "four", "five", "six"); Observable errorSource = Observable.error(new RuntimeException("forced failure")); @@ -1178,6 +1179,7 @@ public void keySelectorThrows() { } @Test + @SuppressUndeliverable public void valueSelectorThrows() { Observable source = Observable.just(0, 1, 2, 3, 4, 5, 6); @@ -1233,6 +1235,7 @@ public void accept(GroupedObservable t1) { } @Test + @SuppressUndeliverable public void error2() { Observable source = Observable.concat(Observable.just(0), Observable. error(new TestException("Forced failure"))); @@ -1446,6 +1449,7 @@ public Integer apply(Integer i) { } @Test + @SuppressUndeliverable public void keySelectorAndDelayError() { Observable.just(1).concatWith(Observable.error(new TestException())) .groupBy(Functions.identity(), true) @@ -1460,6 +1464,7 @@ public ObservableSource apply(GroupedObservable g) th } @Test + @SuppressUndeliverable public void keyAndValueSelectorAndDelayError() { Observable.just(1).concatWith(Observable.error(new TestException())) .groupBy(Functions.identity(), Functions.identity(), true) @@ -1672,4 +1677,68 @@ public void accept(GroupedObservable g) throws Throwable { to2.assertFailure(TestException.class, 1); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.groupBy(v -> v)); + } + + @Test + public void nullKeyDisposeGroup() { + Observable.just(1) + .groupBy(v -> null) + .flatMap(v -> v.take(1)) + .test() + .assertResult(1); + } + + @Test + public void groupSubscribeOnNextRace() throws Throwable { + for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { + BehaviorSubject bs = BehaviorSubject.createDefault(1); + CountDownLatch cdl = new CountDownLatch(1); + + bs.groupBy(v -> 1) + .doOnNext(g -> { + TestHelper.raceOther(() -> { + g.test(); + }, cdl); + }) + .test(); + + cdl.await(); + } + } + + @Test + public void abandonedGroupDispose() { + AtomicReference> ref = new AtomicReference<>(); + + Observable.just(1) + .groupBy(v -> 1) + .doOnNext(ref::set) + .test(); + + ref.get().take(1).test().assertResult(1); + } + + @Test + public void delayErrorCompleteMoreWorkInGroup() { + PublishSubject ps = PublishSubject.create(); + + TestObserver to = ps.groupBy(v -> 1, true) + .flatMap(g -> g.doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + ps.onComplete(); + } + }) + ) + .test() + ; + + ps.onNext(1); + + to.assertResult(1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoinTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoinTest.java index 5998e37a646..7959f90a055 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableGroupJoinTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import static org.junit.Assert.*; @@ -81,7 +79,7 @@ public Integer apply(Integer rightValue) throws Throwable { @Before public void before() { - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); } @Test @@ -479,6 +477,7 @@ public Observable apply(Integer r, Observable l) throws Except } @Test + @SuppressUndeliverable public void innerErrorRight() { Observable.just(1) .groupJoin( @@ -726,4 +725,42 @@ public void leftRightEndState() { verify(js).innerClose(false, o); } + + @Test + public void disposeAfterOnNext() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + + ps1.groupJoin(ps2, v -> Observable.never(), v -> Observable.never(), (a, b) -> a) + .doOnNext(v -> { + to.dispose(); + }) + .subscribe(to); + + ps2.onNext(1); + ps1.onNext(1); + } + + @Test + public void completeWithMoreWork() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = new TestObserver<>(); + + ps1.groupJoin(ps2, v -> Observable.never(), v -> Observable.never(), (a, b) -> a) + .doOnNext(v -> { + if (v == 1) { + ps2.onNext(2); + ps1.onComplete(); + ps2.onComplete(); + } + }) + .subscribe(to); + + ps2.onNext(1); + ps1.onNext(1); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHideTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHideTest.java index 45361b1aedb..0b624621ec8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHideTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableHideTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsTest.java index 43af8631e9e..c7597c3a9f7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIgnoreElementsTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelperTest.java index 9c02f95ebb7..87fc866f74e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableInternalHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import static org.junit.Assert.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRangeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRangeTest.java index 95f26637bf5..637d9164be9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRangeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalRangeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -85,4 +85,12 @@ public void cancel() { .test() .assertResult(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L); } + + @Test + public void takeSameAsRange() { + Observable.intervalRange(0, 2, 1, 1, TimeUnit.MILLISECONDS, Schedulers.trampoline()) + .take(2) + .test() + .assertResult(0L, 1L); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalTest.java index 4f188093c54..e8126962deb 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoinTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoinTest.java index aa173610264..c6f439cdcb4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableJoinTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.observable; import static org.mockito.ArgumentMatchers.any; @@ -54,7 +52,7 @@ public Observable apply(Integer t1) { @Before public void before() { - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); } @Test @@ -446,4 +444,27 @@ public Integer apply(Integer a, Integer b) throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void bothTerminateWithWorkRemaining() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = ps1.join( + ps2, + v -> Observable.never(), + v -> Observable.never(), + (a, b) -> a + b) + .doOnNext(v -> { + ps1.onComplete(); + ps2.onNext(2); + ps2.onComplete(); + }) + .test(); + + ps1.onNext(0); + ps2.onNext(1); + + to.assertComplete(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastTest.java index 0bd5868332b..cabed665f41 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLiftTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLiftTest.java index 325fc504ae9..b761a6ad021 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLiftTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableLiftTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,10 +19,12 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverable; public class ObservableLiftTest extends RxJavaTest { @Test + @SuppressUndeliverable public void callbackCrash() { try { Observable.just(1) diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotificationTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotificationTest.java index 81b470ff99e..0672f528c98 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapNotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapTest.java index 538feaaa7fd..4919a74f0db 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.UnicastSubject; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterializeTest.java index 0e1df287bce..02b16ad6cea 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMaterializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeDelayErrorTest.java index fefce528674..da92bc03380 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeMaxConcurrentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeMaxConcurrentTest.java index 9ab92edc123..e1388f39ad4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeMaxConcurrentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeMaxConcurrentTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeTest.java index d5b9a45a6f8..02ddf09fd0b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletableTest.java index e561eaac1eb..4b9ee5a9d2d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybeTest.java index 43f0a7fff79..3140c5c118e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingleTest.java index c6b083f41d2..9d6171ba06f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableMergeWithSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOnTest.java index 2b8c2e02741..5f41470db05 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableObserveOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -31,11 +31,13 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.flowable.FlowableObserveOnTest.DisposeTrackingScheduler; import io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn.ObserveOnObserver; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.observers.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subjects.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java index 4c377458341..a4671dd5351 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeNextTest.java index 386b6c96a19..ed3e8dc5710 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeWithTest.java index f60ea43a256..7b659c94447 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorResumeWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturnTest.java index 69c6c6889cc..da7acf2b478 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorReturnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishTest.java index 16cb03d00e7..edec6a517dd 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservablePublishTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -866,4 +866,31 @@ public void disposeResets() { to.assertValuesOnly(1); } + + @Test + public void disposeNoNeedForReset() { + PublishSubject ps = PublishSubject.create(); + + ConnectableObservable co = ps.publish(); + + TestObserver to = co.test(); + + Disposable d = co.connect(); + + ps.onNext(1); + + d.dispose(); + + to = co.test(); + + to.assertEmpty(); + + co.connect(); + + to.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLongTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLongTest.java index 7a58572d2f0..c19219cdea1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLongTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeLongTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,8 +24,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.*; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.*; public class ObservableRangeLongTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeTest.java index e789b55093c..0f461a71546 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRangeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,8 +24,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.*; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.*; public class ObservableRangeTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRedoTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRedoTest.java index 2dc15f230e0..adb2caf4a38 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRedoTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRedoTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceTest.java index d997e9899f1..0feab233d3f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReduceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCountTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCountTest.java index d9b98de8f9a..638f694a880 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCountTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRefCountTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -45,7 +45,25 @@ public class ObservableRefCountTest extends RxJavaTest { @Test - public void refCountAsync() { + public void refCountAsync() throws InterruptedException { + // Flaky + for (int i = 0; i < 10; i++) { + try { + refCountAsyncActual(); + return; + } catch (AssertionError ex) { + if (i == 9) { + throw ex; + } + Thread.sleep((int)(200 * (Math.random() * 10 + 1))); + } + } + } + + /** + * Tries to coordinate async counting but it is flaky due to the low 10s of milliseconds. + */ + void refCountAsyncActual() { final AtomicInteger subscribeCount = new AtomicInteger(); final AtomicInteger nextCount = new AtomicInteger(); Observable r = Observable.interval(0, 25, TimeUnit.MILLISECONDS) @@ -837,6 +855,7 @@ protected void subscribeActual(Observer observer) { } @Test + @SuppressUndeliverable public void badSourceSubscribe() { BadObservableSubscribe bo = new BadObservableSubscribe(); @@ -863,6 +882,7 @@ public void badSourceDispose() { } @Test + @SuppressUndeliverable public void badSourceConnect() { BadObservableConnect bo = new BadObservableConnect(); @@ -904,6 +924,7 @@ protected void subscribeActual(Observer observer) { } @Test + @SuppressUndeliverable public void badSourceSubscribe2() { BadObservableSubscribe2 bo = new BadObservableSubscribe2(); @@ -941,6 +962,7 @@ protected void subscribeActual(Observer observer) { } @Test + @SuppressUndeliverable public void badSourceCompleteDisconnect() { BadObservableConnect2 bo = new BadObservableConnect2(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatTest.java index 78c793f1b45..8f3287e7e02 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRepeatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayEagerTruncateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayEagerTruncateTest.java index fe2c59d088b..aa1bcb43592 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayEagerTruncateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayEagerTruncateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.core.Scheduler.Worker; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; @@ -1976,4 +1976,85 @@ public void timeAndSizeNoTerminalTruncationOnTimechange() { .assertComplete() .assertNoErrors(); } + + @Test + public void disposeNoNeedForResetSizeBound() { + PublishSubject ps = PublishSubject.create(); + + ConnectableObservable co = ps.replay(10, true); + + TestObserver to = co.test(); + + Disposable d = co.connect(); + + ps.onNext(1); + + d.dispose(); + + to = co.test(); + + to.assertEmpty(); + + co.connect(); + + to.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeBound() { + PublishSubject ps = PublishSubject.create(); + + ConnectableObservable co = ps.replay(10, TimeUnit.MINUTES, Schedulers.single(), true); + + TestObserver to = co.test(); + + Disposable d = co.connect(); + + ps.onNext(1); + + d.dispose(); + + to = co.test(); + + to.assertEmpty(); + + co.connect(); + + to.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(2); + } + + @Test + public void disposeNoNeedForResetTimeAndSIzeBound() { + PublishSubject ps = PublishSubject.create(); + + ConnectableObservable co = ps.replay(10, 10, TimeUnit.MINUTES, Schedulers.single(), true); + + TestObserver to = co.test(); + + Disposable d = co.connect(); + + ps.onNext(1); + + d.dispose(); + + to = co.test(); + + to.assertEmpty(); + + co.connect(); + + to.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayTest.java index 9b31f51e8d3..8b4ef97d029 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableReplayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -1698,4 +1698,57 @@ public void accept(byte[] v) throws Exception { Assert.fail("Bounded Replay Leak check: Memory leak detected: " + (initial / 1024.0 / 1024.0) + " -> " + after.get() / 1024.0 / 1024.0); } - }} + } + + @Test(expected = TestException.class) + public void connectDisposeCrash() { + ConnectableObservable co = Observable.never().replay(); + + co.connect(); + + co.connect(d -> { throw new TestException(); }); + } + + @Test + public void resetWhileNotConnectedIsNoOp() { + ConnectableObservable co = Observable.never().replay(); + + co.reset(); + } + + @Test + public void resetWhileActiveIsNoOp() { + ConnectableObservable co = Observable.never().replay(); + + co.connect(); + + co.reset(); + } + + @Test + public void disposeNoNeedForReset() { + PublishSubject ps = PublishSubject.create(); + + ConnectableObservable co = ps.replay(); + + TestObserver to = co.test(); + + Disposable d = co.connect(); + + ps.onNext(1); + + d.dispose(); + + to = co.test(); + + to.assertEmpty(); + + co.connect(); + + to.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(2); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableResourceWrapperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableResourceWrapperTest.java index 228725c0a0c..42d557e091f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableResourceWrapperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableResourceWrapperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryTest.java index 94009c5b86a..13f19fb547c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -572,7 +572,7 @@ public void run() { } } - /** Observer for listener on seperate thread. */ + /** Observer for listener on separate thread. */ static final class AsyncObserver extends DefaultObserver { protected CountDownLatch latch = new CountDownLatch(1); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWithPredicateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWithPredicateTest.java index 3b57f6c2e12..bce6e9f6599 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWithPredicateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableRetryWithPredicateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -37,6 +37,7 @@ import io.reactivex.rxjava3.testsupport.*; public class ObservableRetryWithPredicateTest extends RxJavaTest { + BiPredicate retryTwice = new BiPredicate() { @Override public boolean test(Integer t1, Throwable t2) { @@ -390,6 +391,7 @@ public void dontRetry() { } @Test + @SuppressUndeliverable public void retryDisposeRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final PublishSubject ps = PublishSubject.create(); @@ -438,6 +440,7 @@ public boolean test(Integer n, Throwable e) throws Exception { } @Test + @SuppressUndeliverable public void retryBiPredicateDisposeRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final PublishSubject ps = PublishSubject.create(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTest.java index 0861fc2596f..7da1bfcbda3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSampleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -439,4 +439,8 @@ public Observable apply(Observable o) }); } + @Test + public void doubleOnSubscribeObservable() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.sample(Observable.never())); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMapTest.java index bffd568b70c..c27b2e17c04 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScalarXMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,6 +23,7 @@ import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; import io.reactivex.rxjava3.internal.operators.observable.ObservableScalarXMap.ScalarDisposable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.TestHelper; public class ObservableScalarXMapTest extends RxJavaTest { @@ -234,4 +235,13 @@ public void run() { TestHelper.race(r1, r2); } } + + @Test + public void scalarDisposbleWrongFusion() { + TestObserver to = new TestObserver<>(); + final ScalarDisposable sd = new ScalarDisposable<>(to, 1); + to.onSubscribe(sd); + + assertEquals(QueueFuseable.NONE, sd.requestFusion(QueueFuseable.ASYNC)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanTest.java index c482d121be7..9a1765ceb3e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableScanTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualTest.java index 3d805ec79a0..645fafbb625 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSequenceEqualTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -336,4 +336,77 @@ public void run() { to.assertEmpty(); } } + + @Test + public void firstCompletesBeforeSecond() { + Observable.sequenceEqual(Observable.just(1), Observable.empty()) + .test() + .assertResult(false); + } + + @Test + public void secondCompletesBeforeFirst() { + Observable.sequenceEqual(Observable.empty(), Observable.just(1)) + .test() + .assertResult(false); + } + + @Test + public void bothEmpty() { + Observable.sequenceEqual(Observable.empty(), Observable.empty()) + .test() + .assertResult(true); + } + + @Test + public void bothJust() { + Observable.sequenceEqual(Observable.just(1), Observable.just(1)) + .test() + .assertResult(true); + } + + @Test + public void bothCompleteWhileComparing() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = Observable.sequenceEqual(ps1, ps2, (a, b) -> { + ps1.onNext(1); + ps1.onComplete(); + + ps2.onNext(1); + ps2.onComplete(); + return a.equals(b); + }) + .test() + ; + + ps1.onNext(0); + ps2.onNext(0); + + to.assertResult(true); + } + + @Test + public void bothCompleteWhileComparingAsObservable() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = Observable.sequenceEqual(ps1, ps2, (a, b) -> { + ps1.onNext(1); + ps1.onComplete(); + + ps2.onNext(1); + ps2.onComplete(); + return a.equals(b); + }) + .toObservable() + .test() + ; + + ps1.onNext(0); + ps2.onNext(0); + + to.assertResult(true); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerializeTest.java index 2a2b7dff0dd..9aa31211b5f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -78,7 +78,22 @@ public void multiThreadedBasic() { } @Test - public void multiThreadedWithNPE() { + public void multiThreadedWithNPEFlaky() throws InterruptedException { + int max = 9; + for (int i = 0; i <= max; i++) { + try { + multiThreadedWithNPE(); + return; + } catch (AssertionError ex) { + if (i == max) { + throw ex; + } + } + Thread.sleep((long)(1000 * Math.random() + 100)); + } + } + + void multiThreadedWithNPE() { TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable("one", "two", "three", null); Observable w = Observable.unsafeCreate(onSubscribe); @@ -107,7 +122,22 @@ public void multiThreadedWithNPE() { } @Test - public void multiThreadedWithNPEinMiddle() { + public void multiThreadedWithNPEinMiddleFlaky() throws InterruptedException { + int max = 9; + for (int i = 0; i <= max; i++) { + try { + multiThreadedWithNPEinMiddle(); + return; + } catch (AssertionError ex) { + if (i == max) { + throw ex; + } + } + Thread.sleep((long)(1000 * Math.random() + 100)); + } + } + + void multiThreadedWithNPEinMiddle() { boolean lessThan9 = false; for (int i = 0; i < 3; i++) { TestMultiThreadedObservable onSubscribe = new TestMultiThreadedObservable("one", "two", "three", null, "four", "five", "six", "seven", "eight", "nine"); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleTest.java index 2290c645ca7..c511f28baf1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTest.java index 712da24ea99..1a10af31d2f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimedTest.java index d0a1b24fa2d..a4171ea2dfa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipLastTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -194,7 +194,7 @@ public ObservableSource apply(Observable o) throws Exception { } @Test - public void onNextDisposeRace() { + public void onCompleteDisposeRace() { TestScheduler scheduler = new TestScheduler(); for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final PublishSubject ps = PublishSubject.create(); @@ -219,6 +219,32 @@ public void run() { } } + @Test + public void onCompleteDisposeDelayErrorRace() { + TestScheduler scheduler = new TestScheduler(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + final PublishSubject ps = PublishSubject.create(); + + final TestObserver to = ps.skipLast(1, TimeUnit.DAYS, scheduler, true).test(); + + Runnable r1 = new Runnable() { + @Override + public void run() { + ps.onComplete(); + } + }; + + Runnable r2 = new Runnable() { + @Override + public void run() { + to.dispose(); + } + }; + + TestHelper.race(r1, r2); + } + } + @Test public void errorDelayed() { Observable.error(new TestException()) @@ -236,4 +262,177 @@ public void take() { .awaitDone(5, TimeUnit.SECONDS) .assertResult(1); } + + @Test + public void onNextDisposeRace() { + TestScheduler scheduler = new TestScheduler(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + final PublishSubject ps = PublishSubject.create(); + + final TestObserver to = ps.skipLast(1, TimeUnit.DAYS, scheduler).test(); + + Runnable r1 = new Runnable() { + @Override + public void run() { + ps.onNext(1); + } + }; + + Runnable r2 = new Runnable() { + @Override + public void run() { + to.dispose(); + } + }; + + TestHelper.race(r1, r2); + } + } + + @Test + public void onNextOnCompleteDisposeDelayErrorRace() { + TestScheduler scheduler = new TestScheduler(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + final PublishSubject ps = PublishSubject.create(); + + final TestObserver to = ps.skipLast(1, TimeUnit.DAYS, scheduler, true).test(); + + Runnable r1 = new Runnable() { + @Override + public void run() { + ps.onNext(1); + ps.onComplete(); + } + }; + + Runnable r2 = new Runnable() { + @Override + public void run() { + to.dispose(); + } + }; + + TestHelper.race(r1, r2); + } + } + + @Test + public void skipLastTimedDelayError() { + TestScheduler scheduler = new TestScheduler(); + + PublishSubject source = PublishSubject.create(); + + // FIXME the timeunit now matters due to rounding + Observable result = source.skipLast(1000, TimeUnit.MILLISECONDS, scheduler, true); + + Observer o = TestHelper.mockObserver(); + + result.subscribe(o); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + scheduler.advanceTimeBy(500, TimeUnit.MILLISECONDS); + + source.onNext(4); + source.onNext(5); + source.onNext(6); + + scheduler.advanceTimeBy(950, TimeUnit.MILLISECONDS); + source.onComplete(); + + InOrder inOrder = inOrder(o); + inOrder.verify(o).onNext(1); + inOrder.verify(o).onNext(2); + inOrder.verify(o).onNext(3); + inOrder.verify(o, never()).onNext(4); + inOrder.verify(o, never()).onNext(5); + inOrder.verify(o, never()).onNext(6); + inOrder.verify(o).onComplete(); + inOrder.verifyNoMoreInteractions(); + + verify(o, never()).onError(any(Throwable.class)); + } + + @Test + public void skipLastTimedErrorBeforeTimeDelayError() { + TestScheduler scheduler = new TestScheduler(); + + PublishSubject source = PublishSubject.create(); + + Observable result = source.skipLast(1, TimeUnit.SECONDS, scheduler, true); + + Observer o = TestHelper.mockObserver(); + + result.subscribe(o); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + source.onError(new TestException()); + + scheduler.advanceTimeBy(1050, TimeUnit.MILLISECONDS); + + verify(o).onError(any(TestException.class)); + + verify(o, never()).onComplete(); + verify(o, never()).onNext(any()); + } + + @Test + public void skipLastTimedCompleteBeforeTimeDelayError() { + TestScheduler scheduler = new TestScheduler(); + + PublishSubject source = PublishSubject.create(); + + Observable result = source.skipLast(1, TimeUnit.SECONDS, scheduler, true); + + Observer o = TestHelper.mockObserver(); + + result.subscribe(o); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + scheduler.advanceTimeBy(500, TimeUnit.MILLISECONDS); + + source.onComplete(); + + InOrder inOrder = inOrder(o); + inOrder.verify(o).onComplete(); + inOrder.verifyNoMoreInteractions(); + + verify(o, never()).onNext(any()); + verify(o, never()).onError(any(Throwable.class)); + } + + @Test + public void skipLastTimedWhenAllElementsAreValidDelayError() { + TestScheduler scheduler = new TestScheduler(); + + PublishSubject source = PublishSubject.create(); + + Observable result = source.skipLast(1, TimeUnit.MILLISECONDS, scheduler, true); + + Observer o = TestHelper.mockObserver(); + + result.subscribe(o); + + source.onNext(1); + source.onNext(2); + source.onNext(3); + + scheduler.advanceTimeBy(500, TimeUnit.MILLISECONDS); + + source.onComplete(); + + InOrder inOrder = inOrder(o); + inOrder.verify(o).onNext(1); + inOrder.verify(o).onNext(2); + inOrder.verify(o).onNext(3); + inOrder.verify(o).onComplete(); + inOrder.verifyNoMoreInteractions(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTest.java index 93c46946165..c1fe2bf2bcb 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTimedTest.java index 1c3fc30e147..83edc3201be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntilTest.java index 290fc2c1f0d..bb2c3ef127e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhileTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhileTest.java index ab1abdfa49d..b6a0749088d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhileTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSkipWhileTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java index 47cf4dc9623..267f5be42a4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOnTest.java index 53ccf2b3a69..ab3890dcc6c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmptyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmptyTest.java index 34e24d81cb3..5dd3703c674 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmptyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchIfEmptyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchTest.java index 2a1b1dad6e0..72e6c93bb85 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableSwitchTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,16 +24,17 @@ import org.junit.*; import org.mockito.InOrder; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.util.ExceptionHelper; -import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.observers.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subjects.PublishSubject; @@ -1250,4 +1251,206 @@ public Observable apply(Integer v) .test() .assertResult(10, 20); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(f -> f.switchMap(v -> Observable.never())); + } + + @Test + public void mainCompleteCancelRace() { + for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { + AtomicReference> ref = new AtomicReference<>(); + Observable o = new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + ref.set(observer); + } + }; + + TestObserver to = o.switchMap(v -> Observable.never()) + .test(); + + ref.get().onSubscribe(Disposable.empty()); + + TestHelper.race( + () -> ref.get().onComplete(), + () -> to.dispose() + ); + } + } + + @Test + public void mainCompleteInnerErrorRace() { + TestException ex = new TestException(); + + for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) { + AtomicReference> ref1 = new AtomicReference<>(); + Observable o1 = new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + ref1.set(observer); + } + }; + AtomicReference> ref2 = new AtomicReference<>(); + Observable o2 = new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + ref2.set(observer); + } + }; + + o1.switchMap(v -> o2) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + ref2.get().onSubscribe(Disposable.empty()); + + TestHelper.race( + () -> ref1.get().onComplete(), + () -> ref2.get().onError(ex) + ); + } + } + + @Test + public void innerNoSubscriptionYet() { + AtomicReference> ref1 = new AtomicReference<>(); + Observable o1 = new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + ref1.set(observer); + } + }; + AtomicReference> ref2 = new AtomicReference<>(); + Observable o2 = new Observable() { + @Override + protected void subscribeActual(@NonNull Observer observer) { + ref2.set(observer); + } + }; + + o1.switchMap(v -> o2) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + ref1.get().onComplete(); + } + + @Test + public void switchDuringOnNext() { + PublishSubject ps = PublishSubject.create(); + + TestObserver to = ps.switchMap(v -> Observable.range(v, 5)) + .doOnNext(v -> { + if (v == 1) { + ps.onNext(2); + } + }) + .test(); + + ps.onNext(1); + + to + .assertValuesOnly(1, 2, 3, 4, 5, 6); + } + + @Test + public void mainCompleteWhileInnerActive() { + PublishSubject ps1 = PublishSubject.create(); + PublishSubject ps2 = PublishSubject.create(); + + TestObserver to = ps1.switchMapDelayError(v -> ps2) + .test(); + + ps1.onNext(1); + ps1.onComplete(); + + ps2.onComplete(); + + to.assertResult(); + } + + @Test + public void innerIgnoresCancelAndErrors() throws Throwable { + TestHelper.withErrorTracking(errors -> { + PublishSubject ps = PublishSubject.create(); + + TestObserver to = ps + .switchMap(v -> { + if (v == 1) { + return Observable.unsafeCreate(s -> { + s.onSubscribe(Disposable.empty()); + ps.onNext(2); + s.onError(new TestException()); + }); + } + return Observable.never(); + }) + .test(); + + ps.onNext(1); + + to.assertEmpty(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void cancellationShouldTriggerInnerCancellationRace() throws Throwable { + AtomicInteger outer = new AtomicInteger(); + AtomicInteger inner = new AtomicInteger(); + + int n = 10_000; + for (int i = 0; i < n; i++) { + Observable.create(it -> { + it.onNext(0); + }) + .switchMap(v -> createObservable(inner)) + .observeOn(Schedulers.computation()) + .doFinally(() -> { + outer.incrementAndGet(); + }) + .take(1) + .blockingSubscribe(v -> { }, Throwable::printStackTrace); + } + + Thread.sleep(100); + assertEquals(inner.get(), outer.get()); + assertEquals(n, inner.get()); + } + + Observable createObservable(AtomicInteger inner) { + return Observable.unsafeCreate(s -> { + SerializedObserver it = new SerializedObserver<>(s); + it.onSubscribe(Disposable.empty()); + Schedulers.io().scheduleDirect(() -> { + it.onNext(1); + }, 0, TimeUnit.MILLISECONDS); + Schedulers.io().scheduleDirect(() -> { + it.onNext(2); + }, 0, TimeUnit.MILLISECONDS); + }) + .doFinally(() -> { + inner.incrementAndGet(); + }); + } + + @Test + public void innerOnSubscribeOuterCancelRace() { + TestObserver to = new TestObserver(); + + Observable.just(1) + .hide() + .switchMap(v -> Observable.just(1) + .doOnSubscribe(d -> to.dispose()) + .scan(1, (a, b) -> a) + ) + .subscribe(to); + + to.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOneTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOneTest.java index 92536eb95e8..1bd19d6bc9a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOneTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastOneTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTest.java index b9ed3923811..f0a342e2e18 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimedTest.java index f8d17474c25..4e2bd6a5c06 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeLastTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -300,4 +300,9 @@ public void lastWindowIsFixedInTime() { to.assertResult(1, 2, 3, 4); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.takeLast(1, TimeUnit.SECONDS)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTest.java index f83fb8595d3..0ecff804460 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -34,7 +34,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class ObservableTakeTest extends RxJavaTest { @@ -111,6 +111,7 @@ public Integer apply(Integer t1) { } @Test + @SuppressUndeliverable public void takeDoesntLeakErrors() { Observable source = Observable.unsafeCreate(new ObservableSource() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTimedTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTimedTest.java index 32f6049afbc..7edbfbcf20d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeTimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicateTest.java index 143fe9d3cac..04d0ab55377 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilPredicateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilTest.java index 5e831b03b3b..4bbf042acc4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhileTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhileTest.java index 134e1f93f63..0a9fc271368 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhileTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTakeWhileTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -100,6 +100,7 @@ public boolean test(String input) { } @Test + @SuppressUndeliverable public void takeWhileDoesntLeakErrors() { Observable source = Observable.unsafeCreate(new ObservableSource() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTest.java index c8eedc72bda..fe296d572bc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleFirstTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,16 +16,15 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; -import java.util.List; import java.util.concurrent.TimeUnit; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Action; import org.junit.*; import org.mockito.InOrder; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.TestScheduler; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -43,6 +42,76 @@ public void before() { observer = TestHelper.mockObserver(); } + @Test + public void throttlingWithDropCallbackCrashes() throws Throwable { + Observable source = Observable.unsafeCreate(new ObservableSource() { + @Override + public void subscribe(Observer innerObserver) { + innerObserver.onSubscribe(Disposable.empty()); + publishNext(innerObserver, 100, "one"); // publish as it's first + publishNext(innerObserver, 300, "two"); // skip as it's last within the first 400 + publishNext(innerObserver, 900, "three"); // publish + publishNext(innerObserver, 905, "four"); // skip + publishCompleted(innerObserver, 1000); // Should be published as soon as the timeout expires. + } + }); + + Action whenDisposed = mock(Action.class); + Observable sampled = source + .doOnDispose(whenDisposed) + .throttleFirst(400, TimeUnit.MILLISECONDS, scheduler, e -> { + if ("two".equals(e)) { + throw new TestException("forced"); + } + }); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(1)).onError(any(TestException.class)); + inOrder.verify(observer, times(0)).onNext("two"); + inOrder.verify(observer, times(0)).onNext("three"); + inOrder.verify(observer, times(0)).onNext("four"); + inOrder.verify(observer, times(0)).onComplete(); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void throttlingWithDropCallback() { + Observable source = Observable.unsafeCreate(new ObservableSource() { + @Override + public void subscribe(Observer innerObserver) { + innerObserver.onSubscribe(Disposable.empty()); + publishNext(innerObserver, 100, "one"); // publish as it's first + publishNext(innerObserver, 300, "two"); // skip as it's last within the first 400 + publishNext(innerObserver, 900, "three"); // publish + publishNext(innerObserver, 905, "four"); // skip + publishCompleted(innerObserver, 1000); // Should be published as soon as the timeout expires. + } + }); + + Observer dropCallbackObserver = TestHelper.mockObserver(); + Observable sampled = source.throttleFirst(400, TimeUnit.MILLISECONDS, scheduler, dropCallbackObserver::onNext); + sampled.subscribe(observer); + + InOrder inOrder = inOrder(observer); + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + + scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); + inOrder.verify(observer, times(1)).onNext("one"); + inOrder.verify(observer, times(0)).onNext("two"); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("two"); + inOrder.verify(observer, times(1)).onNext("three"); + inOrder.verify(observer, times(0)).onNext("four"); + dropCallbackOrder.verify(dropCallbackObserver, times(1)).onNext("four"); + inOrder.verify(observer, times(1)).onComplete(); + inOrder.verifyNoMoreInteractions(); + dropCallbackOrder.verifyNoMoreInteractions(); + } + @Test public void throttlingWithCompleted() { Observable source = Observable.unsafeCreate(new ObservableSource() { @@ -167,28 +236,7 @@ public void dispose() { } @Test - public void badSource() { - List errors = TestHelper.trackPluginErrors(); - try { - new Observable() { - @Override - protected void subscribeActual(Observer observer) { - observer.onSubscribe(Disposable.empty()); - observer.onNext(1); - observer.onNext(2); - observer.onComplete(); - observer.onNext(3); - observer.onError(new TestException()); - observer.onComplete(); - } - } - .throttleFirst(1, TimeUnit.DAYS) - .test() - .assertResult(1); - - TestHelper.assertUndeliverable(errors, 0, TestException.class); - } finally { - RxJavaPlugins.reset(); - } + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.throttleFirst(1, TimeUnit.SECONDS)); } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatestTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatestTest.java index 5399f63fce4..e1c15f3b1a1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatestTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableThrottleLatestTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,12 +20,13 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.schedulers.TestScheduler; import io.reactivex.rxjava3.subjects.PublishSubject; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class ObservableThrottleLatestTest extends RxJavaTest { @@ -221,4 +222,424 @@ public void onNext(Integer t) { to.assertResult(1, 2); } + + /** Emit 1, 2, 3, then advance time by a second; 1 and 3 should end up in downstream, 2 should be dropped. */ + @Test + public void onDroppedBasicNoEmitLast() { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserver to = ps.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + to.assertEmpty(); + drops.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(3); + + to.assertValuesOnly(1); + drops.assertValuesOnly(2); + + sch.advanceTimeBy(1, TimeUnit.SECONDS); + + to.assertValuesOnly(1, 3); + drops.assertValuesOnly(2); + + ps.onComplete(); + + to.assertResult(1, 3); + + drops.assertValuesOnly(2); + } + + /** Emit 1, 2, 3; 1 should end up in downstream, 2, 3 should be dropped. */ + @Test + public void onDroppedBasicNoEmitLastDropLast() { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserver to = ps.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + to.assertEmpty(); + drops.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(3); + + to.assertValuesOnly(1); + drops.assertValuesOnly(2); + + ps.onComplete(); + + to.assertResult(1); + + drops.assertValuesOnly(2, 3); + } + + /** Emit 1, 2, 3; 1 and 3 should end up in downstream, 2 should be dropped. */ + @Test + public void onDroppedBasicEmitLast() { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserver to = ps.throttleLatest(1, TimeUnit.SECONDS, sch, true, drops::onNext) + .test(); + + to.assertEmpty(); + drops.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(2); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onNext(3); + + to.assertValuesOnly(1); + drops.assertValuesOnly(2); + + ps.onComplete(); + + to.assertResult(1, 3); + + drops.assertValuesOnly(2); + } + + /** Emit 1, 2, 3; 3 should trigger an error to the downstream because 2 is dropped and the callback crashes. */ + @Test + public void onDroppedBasicNoEmitLastFirstDropCrash() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserver to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { + if (d == 2) { + throw new TestException("forced"); + } + }) + .test(); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + ps.onNext(3); + + to.assertFailure(TestException.class, 1); + + verify(whenDisposed).run(); + } + + /** + * Emit 1, 2, Error; the error should trigger the drop callback and crash it too, + * downstream gets 1, composite(source, drop-crash). + */ + @Test + public void onDroppedBasicNoEmitLastOnErrorDropCrash() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + ps.onError(new TestException("source")); + + to.assertFailure(CompositeException.class, 1); + + TestHelper.assertCompositeExceptions(to, TestException.class, "source", TestException.class, "forced 2"); + + verify(whenDisposed, never()).run(); + } + + /** + * Emit 1, 2, 3; 3 should trigger a drop-crash for 2, which then would trigger the error path and drop-crash for 3, + * the last item not delivered, downstream gets 1, composite(drop-crash 2, drop-crash 3). + */ + @Test + public void onDroppedBasicEmitLastOnErrorDropCrash() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, true, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + ps.onNext(3); + + to.assertFailure(CompositeException.class, 1); + + TestHelper.assertCompositeExceptions(to, TestException.class, "forced 2", TestException.class, "forced 3"); + + verify(whenDisposed).run(); + } + + /** Emit 1, complete; Downstream gets 1, complete, no drops. */ + @Test + public void onDroppedBasicNoEmitLastNoLastToDrop() { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserver to = ps.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + to.assertEmpty(); + drops.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onComplete(); + + to.assertResult(1); + drops.assertEmpty(); + } + + /** Emit 1, error; Downstream gets 1, error, no drops. */ + @Test + public void onDroppedErrorNoEmitLastNoLastToDrop() { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserver to = ps.throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .test(); + + to.assertEmpty(); + drops.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + ps.onError(new TestException()); + + to.assertFailure(TestException.class, 1); + drops.assertEmpty(); + } + + /** + * Emit 1, 2, complete; complete should crash drop, downstream gets 1, drop-crash 2. + */ + @Test + public void onDroppedHasLastNoEmitLastDropCrash() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + ps.onComplete(); + + to.assertFailureAndMessage(TestException.class, "forced 2", 1); + + verify(whenDisposed, never()).run(); + } + + /** + * Emit 1, 2 then dispose the sequence; downstream gets 1, drop should get for 2. + */ + @Test + public void onDroppedDisposeDrops() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + to.dispose(); + + to.assertValuesOnly(1); + drops.assertValuesOnly(2); + + verify(whenDisposed).run(); + } + + /** + * Emit 1 then dispose the sequence; downstream gets 1, drop should not get called. + */ + @Test + public void onDroppedDisposeNoDrops() throws Throwable { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserver drops = new TestObserver<>(); + drops.onSubscribe(Disposable.empty()); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, drops::onNext) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + to.dispose(); + + to.assertValuesOnly(1); + drops.assertEmpty(); + + verify(whenDisposed).run(); + } + + /** + * Emit 1, 2 then dispose the sequence; downstream gets 1, global error handler should get drop-crash 2. + */ + @Test + public void onDroppedDisposeCrashesDrop() throws Throwable { + TestHelper.withErrorTracking(errors -> { + PublishSubject ps = PublishSubject.create(); + + TestScheduler sch = new TestScheduler(); + + Action whenDisposed = mock(Action.class); + + TestObserverEx to = ps + .doOnDispose(whenDisposed) + .throttleLatest(1, TimeUnit.SECONDS, sch, false, d -> { throw new TestException("forced " + d); }) + .subscribeWith(new TestObserverEx<>()); + + to.assertEmpty(); + + ps.onNext(1); + + to.assertValuesOnly(1); + + ps.onNext(2); + + to.assertValuesOnly(1); + + to.dispose(); + + to.assertValuesOnly(1); + + verify(whenDisposed).run(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "forced 2"); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeIntervalTest.java index 5f935791b1c..ce418200d8e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTests.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTests.java index fe7b2cd3707..570eb3de5e0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTests.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutWithSelectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutWithSelectorTest.java index 60cb5a8b927..2c6710cc896 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutWithSelectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimeoutWithSelectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -40,6 +40,7 @@ import io.reactivex.rxjava3.testsupport.*; public class ObservableTimeoutWithSelectorTest extends RxJavaTest { + @Test public void timeoutSelectorNormal1() { PublishSubject source = PublishSubject.create(); @@ -493,6 +494,7 @@ public void withOtherMainError() { } @Test + @SuppressUndeliverable public void badSourceTimeout() { new Observable() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimerTest.java index 8eddbce491d..9229d24fe3b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -317,7 +317,7 @@ public void timerDelayZero() { public void timerInterruptible() throws Exception { ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); try { - for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) { + for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec, true) }) { final AtomicBoolean interrupted = new AtomicBoolean(); TestObserver to = Observable.timer(1, TimeUnit.MILLISECONDS, s) .map(new Function() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimestampTest.java index 597333ea66b..084db674738 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimestampTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableTimestampTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToFutureTest.java index 2631dfac4ea..0ac13be46ab 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToFutureTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToFutureTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListTest.java index 020183f9fac..2d4185407da 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToListTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMapTest.java index 8838ff4b5a5..72b39d0025c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMultimapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMultimapTest.java index 0853b0acadd..10bda16080f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMultimapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToMultimapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToSortedListTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToSortedListTest.java index 19c10c6622b..0ea0be21b9e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToSortedListTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToSortedListTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToXTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToXTest.java index 1afbba02254..c7cc6f31515 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToXTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableToXTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOnTest.java index da58ffdb2a3..23f6d7256bf 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUnsubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,6 +26,7 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Action; +import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; @@ -265,4 +266,9 @@ protected void subscribeActual(Observer observer) { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.unsubscribeOn(ImmediateThinScheduler.INSTANCE)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsingTest.java index 143524319d1..de8d73fa36d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableUsingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithObservableTest.java index bfb972626bc..edfca3989d9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -586,6 +586,7 @@ public void run() { } @Test + @SuppressUndeliverable public void disposeMainBoundaryErrorRace() { final TestException ex = new TestException(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithSizeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithSizeTest.java index 04099c31cba..81d076e718a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithSizeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithSizeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -535,4 +535,94 @@ public void accept(Observable v) throws Throwable { inner.get().test().assertResult(1); } + + @Test + public void cancelWithoutWindowSize() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10) + .test(); + + assertTrue(ps.hasObservers()); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } + + @Test + public void cancelAfterAbandonmentSize() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10) + .test(); + + assertTrue(ps.hasObservers()); + + ps.onNext(1); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } + + @Test + public void cancelWithoutWindowSkip() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10, 15) + .test(); + + assertTrue(ps.hasObservers()); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } + + @Test + public void cancelAfterAbandonmentSkip() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10, 15) + .test(); + + assertTrue(ps.hasObservers()); + + ps.onNext(1); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } + + @Test + public void cancelWithoutWindowOverlap() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10, 5) + .test(); + + assertTrue(ps.hasObservers()); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } + + @Test + public void cancelAfterAbandonmentOverlap() { + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(10, 5) + .test(); + + assertTrue(ps.hasObservers()); + + ps.onNext(1); + + to.dispose(); + + assertFalse("Subject still has observers!", ps.hasObservers()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithStartEndObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithStartEndObservableTest.java index af67c36bf2e..659daaf7d1e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithStartEndObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithStartEndObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,16 +15,17 @@ import static org.junit.Assert.*; +import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.*; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.*; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; @@ -32,7 +33,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.TestScheduler; import io.reactivex.rxjava3.subjects.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class ObservableWindowWithStartEndObservableTest extends RxJavaTest { @@ -289,6 +290,7 @@ public ObservableSource apply(Integer v) throws Exception { } @Test + @SuppressUndeliverable public void endError() { PublishSubject source = PublishSubject.create(); PublishSubject start = PublishSubject.create(); @@ -530,4 +532,174 @@ public void mainError() { .test() .assertFailure(TestException.class); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.window(Observable.never(), v -> Observable.never())); + } + + @Test + public void openError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestException ex1 = new TestException(); + TestException ex2 = new TestException(); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Observable o1 = Observable.unsafeCreate(ref1::set); + Observable o2 = Observable.unsafeCreate(ref2::set); + + TestObserver> to = BehaviorSubject.createDefault(1) + .window(o1, v -> o2) + .doOnNext(w -> w.test()) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + ref2.get().onSubscribe(Disposable.empty()); + + TestHelper.race( + () -> ref1.get().onError(ex1), + () -> ref2.get().onError(ex2) + ); + + to.assertError(RuntimeException.class); + + if (!errors.isEmpty()) { + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } + + errors.clear(); + } + }); + } + + @Test + public void closeError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Observable o1 = Observable.unsafeCreate(ref1::set); + Observable o2 = Observable.unsafeCreate(ref2::set); + + TestObserver to = BehaviorSubject.createDefault(1) + .window(o1, v -> o2) + .flatMap(v -> v) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + ref2.get().onSubscribe(Disposable.empty()); + + ref2.get().onError(new TestException()); + ref2.get().onError(new TestException()); + + to.assertFailure(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void upstreamFailsBeforeFirstWindow() { + Observable.error(new TestException()) + .window(Observable.never(), v -> Observable.never()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void windowOpenMainCompletes() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishSubject ps = PublishSubject.create(); + Observable o1 = Observable.unsafeCreate(ref1::set); + + AtomicInteger counter = new AtomicInteger(); + + TestObserver> to = ps + .window(o1, v -> Observable.never()) + .doOnNext(w -> { + if (counter.getAndIncrement() == 0) { + ref1.get().onNext(2); + ps.onNext(1); + ps.onComplete(); + } + w.test(); + }) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + + to.assertComplete(); + } + + @Test + public void windowOpenMainError() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishSubject ps = PublishSubject.create(); + Observable o1 = Observable.unsafeCreate(ref1::set); + + AtomicInteger counter = new AtomicInteger(); + + TestObserver> to = ps + .window(o1, v -> Observable.never()) + .doOnNext(w -> { + if (counter.getAndIncrement() == 0) { + ref1.get().onNext(2); + ps.onNext(1); + ps.onError(new TestException()); + } + w.test(); + }) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + + to.assertError(TestException.class); + } + + @Test + public void windowOpenIgnoresDispose() { + AtomicReference> ref1 = new AtomicReference<>(); + + PublishSubject ps = PublishSubject.create(); + Observable o1 = Observable.unsafeCreate(ref1::set); + + TestObserver> to = ps + .window(o1, v -> Observable.never()) + .take(1) + .doOnNext(w -> { + w.test(); + }) + .test(); + + ref1.get().onSubscribe(Disposable.empty()); + ref1.get().onNext(1); + ref1.get().onNext(2); + + to.assertValueCount(1); + } + + @Test + public void mainIgnoresCancelBeforeOnError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Observable.unsafeCreate(s -> { + s.onSubscribe(Disposable.empty()); + s.onNext(1); + s.onError(new IOException()); + }) + .window(BehaviorSubject.createDefault(1), v -> Observable.error(new TestException())) + .doOnNext(w -> w.test()) + .test() + .assertError(TestException.class); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithTimeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithTimeTest.java index 13f662c88ee..ca8f90d04fa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithTimeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWindowWithTimeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,19 +19,19 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.*; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.*; import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subjects.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class ObservableWindowWithTimeTest extends RxJavaTest { @@ -368,6 +368,7 @@ public void timeskipOverlapping() { } @Test + @SuppressUndeliverable public void exactOnError() { TestScheduler scheduler = new TestScheduler(); @@ -383,6 +384,7 @@ public void exactOnError() { } @Test + @SuppressUndeliverable public void overlappingOnError() { TestScheduler scheduler = new TestScheduler(); @@ -398,6 +400,7 @@ public void overlappingOnError() { } @Test + @SuppressUndeliverable public void skipOnError() { TestScheduler scheduler = new TestScheduler(); @@ -434,6 +437,7 @@ public void restartTimer() { } @Test + @SuppressUndeliverable public void exactBoundaryError() { Observable.error(new TestException()) .window(1, TimeUnit.DAYS, Schedulers.single(), 2, true) @@ -751,6 +755,7 @@ public void accept(Observable v) throws Exception { } @Test + @SuppressUndeliverable public void exactTimeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -831,6 +836,7 @@ public void accept(Observable v) throws Exception { } @Test + @SuppressUndeliverable public void exactTimeAndSizeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -911,6 +917,7 @@ public void accept(Observable v) throws Exception { } @Test + @SuppressUndeliverable public void skipTimeAndSizeBoundNoInterruptWindowOutputOnError() throws Exception { final AtomicBoolean isInterrupted = new AtomicBoolean(); @@ -1099,4 +1106,26 @@ public void accept(Observable v) throws Throwable { inner.get().test().assertResult(); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(o -> o.window(1, TimeUnit.SECONDS)); + } + + @Test + public void timedBoundarySignalAndDisposeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestScheduler scheduler = new TestScheduler(); + + PublishSubject ps = PublishSubject.create(); + + TestObserver> to = ps.window(1, TimeUnit.MINUTES, scheduler, 1) + .test(); + + TestHelper.race( + () -> ps.onNext(1), + () -> to.dispose() + ); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromTest.java index c23c41fde1e..cfe093ed6b5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableWithLatestFromTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipCompletionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipCompletionTest.java index 76d14495db9..89dde2cdc52 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipCompletionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipCompletionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterableTest.java index a4ce20c33cf..ce4ee90939f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipTest.java index d481c16662d..faebee3fa55 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableZipTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -1403,7 +1403,7 @@ public Integer apply(Integer t1, Integer t2) throws Exception { public void firstErrorPreventsSecondSubscription() { final AtomicInteger counter = new AtomicInteger(); - List> observableList = new ArrayList<>(); + List> observableList = new ArrayList<>(); observableList.add(Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(ObservableEmitter e) diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleAmbTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleAmbTest.java index acfa6528a6d..8086aa7c1ca 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleAmbTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleAmbTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -249,7 +249,8 @@ public void run() { @Test public void manySources() { - Single[] sources = new Single[32]; + @SuppressWarnings("unchecked") + Single[] sources = new Single[32]; Arrays.fill(sources, Single.never()); sources[31] = Single.just(31); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java index 50eceede5cc..a29c10975f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCacheTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCacheTest.java index 28eb94110b9..ca46a92f123 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java index 10fec20410a..00ff0d5ad13 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java index ce0df373bb3..bfd96ad3a97 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java index 83ae9cbf9eb..18dc2c83d2a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java index c21c5347d43..892ed8dd4d3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java index 1a160f64659..3c603b26b9f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java index dd25e7a53f2..24710d824ad 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java index b0b5af17a64..1fa2ebaf0b4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatPublisherTest.java index bd31e284308..883903e1d9c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.operators.single; import java.util.concurrent.Callable; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatTest.java index bf8c534f46c..fb94277e43a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleContainstTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleContainstTest.java index 4a991c4cbf2..2f5baa4ed0a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleContainstTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleContainstTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCreateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCreateTest.java index 79cb58c63b3..862757560a6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,11 +25,12 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Cancellable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class SingleCreateTest extends RxJavaTest { @Test + @SuppressUndeliverable public void basic() { final Disposable d = Disposable.empty(); @@ -51,6 +52,7 @@ public void subscribe(SingleEmitter e) throws Exception { } @Test + @SuppressUndeliverable public void basicWithCancellable() { final Disposable d1 = Disposable.empty(); final Disposable d2 = Disposable.empty(); @@ -80,6 +82,7 @@ public void cancel() throws Exception { } @Test + @SuppressUndeliverable public void basicWithError() { final Disposable d = Disposable.empty(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDeferTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDeferTest.java index 962a3694c2b..7fed907ab48 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDeferTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDeferTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayTest.java index 555b53e30ac..bc137d16120 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDelayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -19,18 +19,18 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.*; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.TestHelper; public class SingleDelayTest extends RxJavaTest { @@ -270,4 +270,16 @@ public Single apply(Single s) throws Exception { }); } + + @Test + public void withPublisherDoubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowableToSingle( + f -> SingleSubject.create().delaySubscription(f)); + } + + @Test + public void withObservableDoubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeObservableToSingle( + o -> SingleSubject.create().delaySubscription(o)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerializeTest.java index 5bf14094980..6cd05b71284 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDematerializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDetachTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDetachTest.java index ae13a0d9c04..17812c8957f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDetachTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDetachTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccessTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccessTest.java index 8c2070f736a..de83cecb1a8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccessTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterSuccessTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminateTest.java index f4c3adb7201..6b98da8c666 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoAfterTerminateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinallyTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinallyTest.java index 365b34f1859..64afc620ac3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinallyTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoFinallyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java index 9208ab2be8a..f14d03cc8d9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminateTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminateTest.java index 584c976d41b..814a38bded9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminateTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTerminateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTest.java index cf672026414..92ce91b65ab 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java index 6c1bf14f30f..95262992310 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,6 +24,34 @@ public class SingleEqualsTest extends RxJavaTest { + @Test + public void bothSucceedEqual() { + Single.sequenceEqual(Single.just(1), Single.just(1)) + .test() + .assertResult(true); + } + + @Test + public void bothSucceedNotEqual() { + Single.sequenceEqual(Single.just(1), Single.just(2)) + .test() + .assertResult(false); + } + + @Test + public void firstSucceedOtherError() { + Single.sequenceEqual(Single.just(1), Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + } + + @Test + public void firstErrorOtherSucceed() { + Single.sequenceEqual(Single.error(new TestException()), Single.just(1)) + .test() + .assertFailure(TestException.class); + } + @Test public void bothError() { List errors = TestHelper.trackPluginErrors(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleErrorTest.java index b3619b59923..835ad2ad09c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleErrorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleErrorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java index 84a2a650c41..78705fe166c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletableTest.java index 6e663394e5c..c4af049aec9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapCompletableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowableTest.java index 4643d613038..277b9aa13b9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,13 +21,15 @@ import org.junit.Test; import org.reactivestreams.Subscription; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -585,4 +587,51 @@ public void run() { TestHelper.race(r1, r2); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingleToFlowable(s -> s.flattenAsFlowable(v -> Collections.emptyList())); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(SingleSubject.create().flattenAsFlowable(v -> Collections.emptyList())); + } + + @Test + public void slowPatchCancelAfterOnNext() { + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + cancel(); + onComplete(); + } + }; + + Single.just(1) + .flattenAsFlowable(v -> Arrays.asList(1, 2)) + .subscribe(ts); + + ts.assertResult(1); + } + + @Test + public void onSuccessRequestRace() { + List list = Arrays.asList(1); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + SingleSubject ss = SingleSubject.create(); + + TestSubscriber ts = ss.flattenAsFlowable(v -> list) + .test(0L); + + TestHelper.race( + () -> ss.onSuccess(1), + () -> ts.request(1) + ); + + ts.assertResult(1); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservableTest.java index 5d2bafc9c98..82448746b83 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapIterableObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,8 +25,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.util.CrashingIterable; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybeTest.java index c11780324fb..6081a621e88 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java index 266acc93f23..00f1337b2cc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapTest.java index ea02529556f..08d3d24c5a0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallableTest.java index 8a97b8a2d6f..33520299899 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromCallableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java index 50eed426a7d..293cedf574c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisherTest.java index 74261bc7ddd..080870b228c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplierTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplierTest.java index dd259f209b0..927ec7f8378 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplierTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromSupplierTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromTest.java index 5c7bdfd5d23..a322d8852e7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleHideTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleHideTest.java index 9c5609b571e..d13218bc84a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleHideTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleHideTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java index 5d5e152c1b4..478a03d9ff6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -31,8 +31,8 @@ public void utilityClass() { @Test public void noSuchElementCallableEnum() { - assertEquals(1, SingleInternalHelper.NoSuchElementCallable.values().length); - assertNotNull(SingleInternalHelper.NoSuchElementCallable.valueOf("INSTANCE")); + assertEquals(1, SingleInternalHelper.NoSuchElementSupplier.values().length); + assertNotNull(SingleInternalHelper.NoSuchElementSupplier.valueOf("INSTANCE")); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleLiftTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleLiftTest.java index 1638cb993fd..6fdd626bd3b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleLiftTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleLiftTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMapTest.java index 625c4f1f5b4..eb220e0580b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterializeTest.java index 4bc05ea67d5..46625b80ab4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterializeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMaterializeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java index 9434a4fcc1c..b2bda3a7d79 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeTest.java index 7aba476c86e..dd4844da5b0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java index dad1322b22c..93eebfe7ec6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOnTest.java index afb4494befe..4abc87e51f8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleObserveOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java index 3ce3a0d15e2..9569e9a35dc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java index 189759d6c6b..9b184ae7f8d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorXTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorXTest.java index 990a0fdec67..42e36eaba86 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorXTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorXTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java index 80abb4cb1a0..d9711c67c01 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java index a3f7e7225a0..3d01226d9aa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOnTest.java index 0c22190691d..bec9782b0ef 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSwitchOnNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSwitchOnNextTest.java index 63c97f14ec3..f3c119222d8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSwitchOnNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSwitchOnNextTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntilTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntilTest.java index 0a2d27340ac..c5389b0bbd0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTakeUntilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java index 09dd26eeba0..ade198db50f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeoutTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeoutTest.java index 7c51e8be913..e54fc112077 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeoutTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeoutTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,12 +21,14 @@ import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Action; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.schedulers.TestScheduler; +import io.reactivex.rxjava3.schedulers.*; import io.reactivex.rxjava3.subjects.*; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -216,9 +218,61 @@ public void run() { public void mainTimedOut() { Single .never() - .timeout(1, TimeUnit.NANOSECONDS) + .timeout(1, TimeUnit.MILLISECONDS) .to(TestHelper.testConsumer()) .awaitDone(5, TimeUnit.SECONDS) - .assertFailureAndMessage(TimeoutException.class, timeoutMessage(1, TimeUnit.NANOSECONDS)); + .assertFailureAndMessage(TimeoutException.class, timeoutMessage(1, TimeUnit.MILLISECONDS)); + } + + @Test + public void mainTimeoutFallbackSuccess() { + Single.never() + .timeout(1, TimeUnit.MILLISECONDS, Single.just(1)) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(1); + } + + @Test + public void timeoutBeforeOnSubscribeFromMain() { + Disposable d = Disposable.empty(); + + new Single() { + @Override + protected void subscribeActual(@NonNull SingleObserver observer) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + observer.onSubscribe(d); + } + } + .timeout(1, TimeUnit.MILLISECONDS, Single.just(1)) + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(1); + + assertTrue(d.isDisposed()); + } + + @Test + public void timeoutWithZero() throws InterruptedException { + int n = 10_000; + Scheduler sch = Schedulers.single(); + for (int i = 0; i < n; i++) { + final int y = i; + final CountDownLatch latch = new CountDownLatch(1); + Disposable d = Single.never() + .timeout(0, TimeUnit.NANOSECONDS, sch) + .subscribe(v -> {}, e -> { + //System.out.println("timeout " + y); + latch.countDown(); + }); + if (!latch.await(2, TimeUnit.SECONDS)) { + System.out.println(d + " " + sch); + throw new IllegalStateException("Timeout did not work at y = " + y); + } + } } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimerTest.java index 2924364459e..3b5797f498d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ public void disposed() { public void timerInterruptible() throws Exception { ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); try { - for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) { + for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec, true) }) { final AtomicBoolean interrupted = new AtomicBoolean(); TestObserver to = Single.timer(1, TimeUnit.MILLISECONDS, s) .map(new Function() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java index a282c0345e7..206da8f428a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowableTest.java index f4c344c8011..1c9cf06385d 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservableTest.java index 35d38d49c74..f72bd4ac603 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleToObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOnTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOnTest.java index d28c47ad084..fa07de729c7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUnsubscribeOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUsingTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUsingTest.java index 28f268f423c..28c6b34ef75 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUsingTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleUsingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -293,6 +293,7 @@ protected void subscribeActual(SingleObserver observer) { } @Test + @SuppressUndeliverable public void errorDisposeRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final PublishProcessor pp = PublishProcessor.create(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArrayTest.java index 50989db3ecc..df41235e38b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArrayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipArrayTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,16 +16,19 @@ import static org.junit.Assert.*; import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.subjects.SingleSubject; import io.reactivex.rxjava3.testsupport.TestHelper; public class SingleZipArrayTest extends RxJavaTest { @@ -193,4 +196,40 @@ public void singleSourceZipperReturnsNull() { .to(TestHelper.testConsumer()) .assertFailureAndMessage(NullPointerException.class, "The zipper returned a null value"); } + + @Test + public void singleSourceZipperReturnsNull2() { + Single.zipArray(Functions.justFunction(null), Single.just(1), Single.just(2)) + .to(TestHelper.testConsumer()) + .assertFailureAndMessage(NullPointerException.class, "The zipper returned a null value"); + } + + @Test + public void dispose2() { + TestHelper.checkDisposed(Single.zipArray(Functions.justFunction(1), SingleSubject.create(), SingleSubject.create())); + } + + @Test + public void bothSucceed() { + Single.zipArray(a -> Arrays.asList(a), Single.just(1), Single.just(2)) + .test() + .assertResult(Arrays.asList(1, 2)); + } + + @Test + public void onSuccessAfterDispose() { + AtomicReference> emitter = new AtomicReference<>(); + + TestObserver> to = Single.zipArray(Arrays::asList, + (SingleSource)o -> emitter.set(o), Single.never()) + .test(); + + emitter.get().onSubscribe(Disposable.empty()); + + to.dispose(); + + emitter.get().onSuccess(1); + + to.assertEmpty(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterableTest.java index 6fd67444791..c2293a2b890 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipTest.java index 79380cfa5fb..14f2e682674 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleZipTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTaskTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTaskTest.java index 85507fb7f14..cd10a10443b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTaskTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTaskTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,7 +27,7 @@ public class AbstractDirectTaskTest extends RxJavaTest { @Test public void cancelSetFuture() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -58,7 +58,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void cancelSetFutureCurrentThread() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -91,7 +91,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void setFutureCancel() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -119,7 +119,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void setFutureCancelSameThread() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -148,7 +148,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void finished() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -177,7 +177,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void finishedCancel() { - AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; final Boolean[] interrupted = { null }; @@ -211,7 +211,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { @Test public void disposeSetFutureRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { - final AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE) { + final AbstractDirectTask task = new AbstractDirectTask(Functions.EMPTY_RUNNABLE, true) { private static final long serialVersionUID = 208585707945686116L; }; @@ -241,4 +241,31 @@ public void run() { TestHelper.race(r1, r2); } } + + static class TestDirectTask extends AbstractDirectTask { + private static final long serialVersionUID = 587679821055711738L; + + TestDirectTask() { + super(Functions.EMPTY_RUNNABLE, true); + } + } + + @Test + public void toStringStates() { + TestDirectTask task = new TestDirectTask(); + + assertEquals("TestDirectTask[Waiting]", task.toString()); + + task.runner = Thread.currentThread(); + + assertEquals("TestDirectTask[Running on " + Thread.currentThread() + "]", task.toString()); + + task.dispose(); + + assertEquals("TestDirectTask[Disposed]", task.toString()); + + task.set(AbstractDirectTask.FINISHED); + + assertEquals("TestDirectTask[Finished]", task.toString()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/BooleanRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/BooleanRunnableTest.java new file mode 100644 index 00000000000..237bb233eb2 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/BooleanRunnableTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.schedulers; + +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.schedulers.ExecutorScheduler.ExecutorWorker.BooleanRunnable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class BooleanRunnableTest extends RxJavaTest { + + @Test + public void runnableThrows() { + List errors = TestHelper.trackPluginErrors(); + try { + BooleanRunnable task = new BooleanRunnable(() -> { + throw new TestException(); + }); + + try { + task.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ComputationSchedulerInternalTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ComputationSchedulerInternalTest.java index 59ad5d1dfc4..5c8aa1a65f6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ComputationSchedulerInternalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ComputationSchedulerInternalTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.schedulers; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancelTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancelTest.java index 8018806a377..224e33ae7d2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancelTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/DisposeOnCancelTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerDelayedRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerDelayedRunnableTest.java index 08e06b189ef..31c31122551 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerDelayedRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerDelayedRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,10 +22,12 @@ import io.reactivex.rxjava3.core.RxJavaTest; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.schedulers.ExecutorScheduler.DelayedRunnable; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverable; public class ExecutorSchedulerDelayedRunnableTest extends RxJavaTest { @Test(expected = TestException.class) + @SuppressUndeliverable public void delayedRunnableCrash() { DelayedRunnable dl = new DelayedRunnable(new Runnable() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerInternalTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerInternalTest.java new file mode 100644 index 00000000000..64d4d1861cc --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ExecutorSchedulerInternalTest.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.schedulers; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +public class ExecutorSchedulerInternalTest { + + @Test + public void helperHolder() { + assertNotNull(new ExecutorScheduler.SingleHolder()); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinSchedulerTest.java index cacb8fabeb8..75710644d90 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ImmediateThinSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTaskTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTaskTest.java index 7b7299f309e..4a57e867813 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTaskTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/InstantPeriodicTaskTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -44,7 +41,12 @@ public void run() { } }, exec); - assertNull(task.call()); + try { + task.call(); + fail("Should have thrown!"); + } catch (TestException excepted) { + // excepted + } TestHelper.assertUndeliverable(errors, 0, TestException.class); } finally { diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/InterruptibleRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/InterruptibleRunnableTest.java new file mode 100644 index 00000000000..e040b374195 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/InterruptibleRunnableTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.schedulers; + +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.schedulers.ExecutorScheduler.ExecutorWorker.InterruptibleRunnable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class InterruptibleRunnableTest extends RxJavaTest { + + @Test + public void runnableThrows() { + List errors = TestHelper.trackPluginErrors(); + try { + InterruptibleRunnable task = new InterruptibleRunnable(() -> { + throw new TestException(); + }, null); + + try { + task.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoScheduledReleaseTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoScheduledReleaseTest.java new file mode 100644 index 00000000000..e3f55b75fb4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoScheduledReleaseTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.schedulers; + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.schedulers.Schedulers; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +public class IoScheduledReleaseTest extends RxJavaTest { + + /* This test will be stuck in a deadlock if IoScheduler.USE_SCHEDULED_RELEASE is not set */ + @Test + public void scheduledRelease() { + boolean savedScheduledRelease = IoScheduler.USE_SCHEDULED_RELEASE; + IoScheduler.USE_SCHEDULED_RELEASE = true; + try { + Flowable.just("item") + .observeOn(Schedulers.io()) + .firstOrError() + .map(item -> { + for (int i = 0; i < 50; i++) { + Completable.complete() + .observeOn(Schedulers.io()) + .blockingAwait(); + } + return "Done"; + }) + .ignoreElement() + .test() + .awaitDone(5, TimeUnit.SECONDS) + .assertComplete(); + } finally { + IoScheduler.USE_SCHEDULED_RELEASE = savedScheduledRelease; + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoSchedulerInternalTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoSchedulerInternalTest.java new file mode 100644 index 00000000000..9a4b6f3be0c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/IoSchedulerInternalTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.schedulers; + +import static org.junit.Assert.*; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.internal.schedulers.IoScheduler.*; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class IoSchedulerInternalTest extends RxJavaTest { + + @Test + public void expiredQueueEmpty() { + ConcurrentLinkedQueue expire = new ConcurrentLinkedQueue<>(); + CompositeDisposable cd = new CompositeDisposable(); + + CachedWorkerPool.evictExpiredWorkers(expire, cd); + } + + @Test + public void expiredWorkerRemoved() { + ConcurrentLinkedQueue expire = new ConcurrentLinkedQueue<>(); + CompositeDisposable cd = new CompositeDisposable(); + + ThreadWorker tw = new ThreadWorker(new RxThreadFactory("IoExpiryTest")); + + try { + expire.add(tw); + cd.add(tw); + + CachedWorkerPool.evictExpiredWorkers(expire, cd); + + assertTrue(tw.isDisposed()); + assertTrue(expire.isEmpty()); + } finally { + tw.dispose(); + } + } + + @Test + public void noExpiredWorker() { + ConcurrentLinkedQueue expire = new ConcurrentLinkedQueue<>(); + CompositeDisposable cd = new CompositeDisposable(); + + ThreadWorker tw = new ThreadWorker(new RxThreadFactory("IoExpiryTest")); + tw.setExpirationTime(System.nanoTime() + 10_000_000_000L); + + try { + expire.add(tw); + cd.add(tw); + + CachedWorkerPool.evictExpiredWorkers(expire, cd); + + assertFalse(tw.isDisposed()); + assertFalse(expire.isEmpty()); + } finally { + tw.dispose(); + } + } + + @Test + public void expireReuseRace() { + ConcurrentLinkedQueue expire = new ConcurrentLinkedQueue<>(); + CompositeDisposable cd = new CompositeDisposable(); + + ThreadWorker tw = new ThreadWorker(new RxThreadFactory("IoExpiryTest")); + tw.dispose(); + + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + expire.add(tw); + cd.add(tw); + + TestHelper.race( + () -> CachedWorkerPool.evictExpiredWorkers(expire, cd), + () -> expire.remove(tw) + ); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactoryTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactoryTest.java index 83a65e65ac9..d0cbb6a476a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactoryTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/RxThreadFactoryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTaskTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTaskTest.java index 23afeca2ce0..d41906b13a2 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTaskTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTaskTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,6 +13,8 @@ package io.reactivex.rxjava3.internal.schedulers; +import static org.junit.Assert.fail; + import java.util.List; import org.junit.Test; @@ -33,9 +35,14 @@ public void runnableThrows() { public void run() { throw new TestException(); } - }); - - task.run(); + }, true); + + try { + task.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } TestHelper.assertUndeliverable(errors, 0, TestException.class); } finally { diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnableTest.java index a8920fbd933..8d2fc1f7cce 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -208,7 +208,12 @@ public void run() { }, set); set.add(run); - run.run(); + try { + run.run(); + fail("Should have thrown!"); + } catch (TestException expected) { + // expected + } assertTrue(run.isDisposed()); @@ -394,4 +399,29 @@ public void withParentIsDisposed() { assertFalse(set.remove(run)); } + + @Test + public void toStringStates() { + CompositeDisposable set = new CompositeDisposable(); + ScheduledRunnable task = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); + + assertEquals("ScheduledRunnable[Waiting]", task.toString()); + + task.set(ScheduledRunnable.THREAD_INDEX, Thread.currentThread()); + + assertEquals("ScheduledRunnable[Running on " + Thread.currentThread() + "]", task.toString()); + + task.dispose(); + + assertEquals("ScheduledRunnable[Disposed(Sync)]", task.toString()); + + task.set(ScheduledRunnable.FUTURE_INDEX, ScheduledRunnable.DONE); + + assertEquals("ScheduledRunnable[Finished]", task.toString()); + + task = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); + task.dispose(); + + assertEquals("ScheduledRunnable[Disposed(Async)]", task.toString()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupportTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupportTest.java index 21b4514be1b..3d16867a1a3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupportTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerMultiWorkerSupportTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactoryTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactoryTest.java index 1fcbf105b4e..12afa708c45 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactoryTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerPoolFactoryTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -23,7 +20,6 @@ import io.reactivex.rxjava3.core.RxJavaTest; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.TestHelper; public class SchedulerPoolFactoryTest extends RxJavaTest { @@ -33,50 +29,6 @@ public void utilityClass() { TestHelper.checkUtilityClass(SchedulerPoolFactory.class); } - @Test - public void multiStartStop() { - SchedulerPoolFactory.shutdown(); - - SchedulerPoolFactory.shutdown(); - - SchedulerPoolFactory.tryStart(false); - - assertNull(SchedulerPoolFactory.PURGE_THREAD.get()); - - SchedulerPoolFactory.start(); - - // restart schedulers - Schedulers.shutdown(); - - Schedulers.start(); - } - - @Test - public void startRace() throws InterruptedException { - try { - for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { - SchedulerPoolFactory.shutdown(); - - Runnable r1 = new Runnable() { - @Override - public void run() { - SchedulerPoolFactory.start(); - } - }; - - TestHelper.race(r1, r1); - } - - } finally { - // restart schedulers - Schedulers.shutdown(); - - Thread.sleep(200); - - Schedulers.start(); - } - } - @Test public void boolPropertiesDisabledReturnsDefaultDisabled() throws Throwable { assertTrue(SchedulerPoolFactory.getBooleanProperty(false, "key", false, true, failingPropertiesAccessor)); @@ -101,30 +53,6 @@ public void boolPropertiesReturnsValue() throws Throwable { assertFalse(SchedulerPoolFactory.getBooleanProperty(true, "false", false, true, Functions.identity())); } - @Test - public void intPropertiesDisabledReturnsDefaultDisabled() throws Throwable { - assertEquals(-1, SchedulerPoolFactory.getIntProperty(false, "key", 0, -1, failingPropertiesAccessor)); - assertEquals(-1, SchedulerPoolFactory.getIntProperty(false, "key", 1, -1, failingPropertiesAccessor)); - } - - @Test - public void intPropertiesEnabledMissingReturnsDefaultMissing() throws Throwable { - assertEquals(-1, SchedulerPoolFactory.getIntProperty(true, "key", -1, 0, missingPropertiesAccessor)); - assertEquals(-1, SchedulerPoolFactory.getIntProperty(true, "key", -1, 1, missingPropertiesAccessor)); - } - - @Test - public void intPropertiesFailureReturnsDefaultMissing() throws Throwable { - assertEquals(-1, SchedulerPoolFactory.getIntProperty(true, "key", -1, 0, failingPropertiesAccessor)); - assertEquals(-1, SchedulerPoolFactory.getIntProperty(true, "key", -1, 1, failingPropertiesAccessor)); - } - - @Test - public void intPropertiesReturnsValue() throws Throwable { - assertEquals(1, SchedulerPoolFactory.getIntProperty(true, "1", 0, 4, Functions.identity())); - assertEquals(2, SchedulerPoolFactory.getIntProperty(true, "2", 3, 5, Functions.identity())); - } - static final Function failingPropertiesAccessor = new Function() { @Override public String apply(String v) throws Throwable { @@ -138,22 +66,4 @@ public String apply(String v) throws Throwable { return null; } }; - - @Test - public void putIntoPoolNoPurge() { - int s = SchedulerPoolFactory.POOLS.size(); - - SchedulerPoolFactory.tryPutIntoPool(false, null); - - assertEquals(s, SchedulerPoolFactory.POOLS.size()); - } - - @Test - public void putIntoPoolNonThreadPool() { - int s = SchedulerPoolFactory.POOLS.size(); - - SchedulerPoolFactory.tryPutIntoPool(true, null); - - assertEquals(s, SchedulerPoolFactory.POOLS.size()); - } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhenTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhenTest.java index d48228d20cc..03e6a9300f5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhenTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SchedulerWhenTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SingleSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SingleSchedulerTest.java index f6dfe5e455f..c9f9cc54765 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/SingleSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/SingleSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,22 +14,25 @@ package io.reactivex.rxjava3.internal.schedulers; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import org.junit.Test; import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Scheduler.Worker; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.SingleScheduler.ScheduledWorker; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class SingleSchedulerTest extends AbstractSchedulerTests { @Test + @SuppressUndeliverable public void shutdownRejects() { final int[] calls = { 0 }; @@ -123,4 +126,20 @@ public void runnableDisposedAsyncTimed() throws Exception { return Schedulers.single(); } + @Test + public void zeroPeriodRejectedExecution() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Scheduler s = RxJavaPlugins.createSingleScheduler(new RxThreadFactory("Test")); + s.shutdown(); + Runnable run = mock(Runnable.class); + + s.schedulePeriodicallyDirect(run, 1, 0, TimeUnit.MILLISECONDS); + + Thread.sleep(100); + + verify(run, never()).run(); + + TestHelper.assertUndeliverable(errors, 0, RejectedExecutionException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/schedulers/TrampolineSchedulerInternalTest.java b/src/test/java/io/reactivex/rxjava3/internal/schedulers/TrampolineSchedulerInternalTest.java index e30400214c1..b25620e2bfa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/schedulers/TrampolineSchedulerInternalTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/schedulers/TrampolineSchedulerInternalTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.schedulers; @@ -20,19 +17,23 @@ import static org.mockito.Mockito.*; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; -import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.TrampolineScheduler.*; import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.*; public class TrampolineSchedulerInternalTest extends RxJavaTest { @Test + @SuppressUndeliverable public void scheduleDirectInterrupt() { Thread.currentThread().interrupt(); @@ -144,6 +145,7 @@ public void run() { } @Test + @SuppressUndeliverable public void reentrantScheduleInterrupt() { final Worker w = Schedulers.trampoline().createWorker(); try { @@ -209,4 +211,29 @@ public void run() { verify(r, never()).run(); } + + @Test + public void submitAndDisposeNextTask() { + Scheduler.Worker w = Schedulers.trampoline().createWorker(); + + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + Runnable run = mock(Runnable.class); + + AtomicInteger sync = new AtomicInteger(2); + + w.schedule(() -> { + Disposable d = w.schedule(run); + + Schedulers.single().scheduleDirect(() -> { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + d.dispose(); + }); + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + }); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriberTest.java index c84e3807016..c58d015abc9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableConditionalSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,15 +14,18 @@ package io.reactivex.rxjava3.internal.subscribers; import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; import org.junit.Test; import org.reactivestreams.Subscription; -import io.reactivex.rxjava3.annotations.Nullable; -import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber; -import io.reactivex.rxjava3.internal.subscriptions.ScalarSubscription; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.annotations.*; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.internal.subscriptions.*; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.testsupport.*; public class BasicFuseableConditionalSubscriberTest extends RxJavaTest { @@ -83,4 +86,172 @@ public Integer poll() throws Exception { fcs.clear(); assertTrue(fcs.isEmpty()); } + + @Test + public void implementationStopsOnSubscribe() { + @SuppressWarnings("unchecked") + ConditionalSubscriber ts = mock(ConditionalSubscriber.class); + + BasicFuseableConditionalSubscriber bfs = new BasicFuseableConditionalSubscriber(ts) { + + @Override + protected boolean beforeDownstream() { + return false; + } + + @Override + public void onNext(@NonNull Integer t) { + ts.onNext(t); + } + + @Override + public int requestFusion(int mode) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean tryOnNext(@NonNull Integer t) { + // TODO Auto-generated method stub + return false; + } + + @Override + public @Nullable Integer poll() throws Throwable { + return null; + } + }; + + bfs.onSubscribe(new BooleanSubscription()); + + verify(ts, never()).onSubscribe(any()); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f + .map(v -> v) + .filter(v -> true) + ); + } + + @Test + public void transitiveBoundaryFusionNone() { + @SuppressWarnings("unchecked") + ConditionalSubscriber ts = mock(ConditionalSubscriber.class); + + BasicFuseableConditionalSubscriber bfs = new BasicFuseableConditionalSubscriber(ts) { + + @Override + protected boolean beforeDownstream() { + return false; + } + + @Override + public void onNext(@NonNull Integer t) { + ts.onNext(t); + } + + @Override + public int requestFusion(int mode) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean tryOnNext(@NonNull Integer t) { + // TODO Auto-generated method stub + return false; + } + + @Override + public @Nullable Integer poll() throws Throwable { + return null; + } + }; + + bfs.onSubscribe(new BooleanSubscription()); + + assertEquals(QueueFuseable.NONE, bfs.transitiveBoundaryFusion(QueueFuseable.ANY)); + } + + @Test + public void transitiveBoundaryFusionAsync() { + @SuppressWarnings("unchecked") + ConditionalSubscriber ts = mock(ConditionalSubscriber.class); + + BasicFuseableConditionalSubscriber bfs = new BasicFuseableConditionalSubscriber(ts) { + + @Override + protected boolean beforeDownstream() { + return false; + } + + @Override + public void onNext(@NonNull Integer t) { + ts.onNext(t); + } + + @Override + public int requestFusion(int mode) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean tryOnNext(@NonNull Integer t) { + // TODO Auto-generated method stub + return false; + } + + @Override + public @Nullable Integer poll() throws Throwable { + return null; + } + }; + + bfs.onSubscribe(EmptySubscription.INSTANCE); + + assertEquals(QueueFuseable.ASYNC, bfs.transitiveBoundaryFusion(QueueFuseable.ANY)); + } + + @Test + public void transitiveBoundaryFusionAsyncBoundary() { + @SuppressWarnings("unchecked") + ConditionalSubscriber ts = mock(ConditionalSubscriber.class); + + BasicFuseableConditionalSubscriber bfs = new BasicFuseableConditionalSubscriber(ts) { + + @Override + protected boolean beforeDownstream() { + return false; + } + + @Override + public void onNext(@NonNull Integer t) { + ts.onNext(t); + } + + @Override + public int requestFusion(int mode) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean tryOnNext(@NonNull Integer t) { + // TODO Auto-generated method stub + return false; + } + + @Override + public @Nullable Integer poll() throws Throwable { + return null; + } + }; + + bfs.onSubscribe(EmptySubscription.INSTANCE); + + assertEquals(QueueFuseable.NONE, bfs.transitiveBoundaryFusion(QueueFuseable.ANY | QueueFuseable.BOUNDARY)); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriberTest.java index 87ccd91b92f..d6f85acc468 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BasicFuseableSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,9 +17,9 @@ import org.junit.Test; -import io.reactivex.rxjava3.annotations.Nullable; +import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.internal.subscriptions.ScalarSubscription; +import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -53,4 +53,36 @@ public Integer poll() throws Exception { fcs.clear(); assertTrue(fcs.isEmpty()); } + + @Test + public void implementationStopsOnSubscribe() { + TestSubscriber ts = new TestSubscriber<>(); + BasicFuseableSubscriber bfs = new BasicFuseableSubscriber(ts) { + + @Override + protected boolean beforeDownstream() { + return false; + } + + @Override + public void onNext(@NonNull Integer t) { + ts.onNext(t); + } + + @Override + public int requestFusion(int mode) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public @Nullable Integer poll() throws Throwable { + return null; + } + }; + + bfs.onSubscribe(new BooleanSubscription()); + + assertFalse(ts.hasSubscription()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriberTest.java index 563a52a9840..a97f4ee93e7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BlockingSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriberTest.java index d6b80cc8733..68e955097da 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/BoundedSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,7 +27,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class BoundedSubscriberTest extends RxJavaTest { @@ -315,6 +315,7 @@ public void accept(Subscription s) throws Exception { } @Test + @SuppressUndeliverable public void badSourceEmitAfterDone() { Flowable source = Flowable.fromPublisher(new Publisher() { @Override @@ -378,4 +379,37 @@ public void customOnErrorShouldReportCustomOnError() { assertTrue(subscriber.hasCustomOnError()); } + + @Test + public void cancel() { + BoundedSubscriber subscriber = new BoundedSubscriber<>(Functions.emptyConsumer(), + Functions.emptyConsumer(), + Functions.EMPTY_ACTION, + Functions.boundedConsumer(128), 128); + + BooleanSubscription bs = new BooleanSubscription(); + subscriber.onSubscribe(bs); + + subscriber.cancel(); + + assertTrue(bs.isCancelled()); + } + + @Test + public void dispose() { + BoundedSubscriber subscriber = new BoundedSubscriber<>(Functions.emptyConsumer(), + Functions.emptyConsumer(), + Functions.EMPTY_ACTION, + Functions.boundedConsumer(128), 128); + + BooleanSubscription bs = new BooleanSubscription(); + subscriber.onSubscribe(bs); + + assertFalse(subscriber.isDisposed()); + + subscriber.dispose(); + + assertTrue(bs.isCancelled()); + assertTrue(subscriber.isDisposed()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriberTest.java index 698fcc18acb..dcfcb82377f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/DeferredScalarSubscriberTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.internal.subscribers; diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/EmptyComponentTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/EmptyComponentTest.java index 60da2b7a29e..c5cf3c88ca1 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/EmptyComponentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/EmptyComponentTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/FlowableConsumersTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/FlowableConsumersTest.java new file mode 100644 index 00000000000..cc7083cde7d --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/FlowableConsumersTest.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +/* + * Copyright 2016-2019 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactivex.rxjava3.internal.subscribers; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.*; + +import org.junit.Test; +import org.reactivestreams.Subscriber; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.observers.LambdaConsumerIntrospection; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class FlowableConsumersTest implements Consumer, Action { + + final CompositeDisposable composite = new CompositeDisposable(); + + final PublishProcessor processor = PublishProcessor.create(); + + final List events = new ArrayList<>(); + + @Override + public void run() throws Exception { + events.add("OnComplete"); + } + + @Override + public void accept(Object t) throws Exception { + events.add(t); + } + + static Disposable subscribeAutoDispose(Flowable source, CompositeDisposable composite, + Consumer onNext, Consumer onError, Action onComplete) { + return source.subscribe(onNext, onError, onComplete, composite); + } + + @Test + public void onNextNormal() { + + Disposable d = subscribeAutoDispose(processor, composite, this, Functions.ON_ERROR_MISSING, () -> { }); + + assertFalse(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onErrorNormal() { + + subscribeAutoDispose(processor, composite, this, this, () -> { }); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onErrorError() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(d.getClass().toString(), ((LambdaConsumerIntrospection)d).hasCustomOnError()); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onError(new IOException()); + + assertEquals(events.toString(), 1, events.get(0)); + assertTrue(events.toString(), events.get(1) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteNormal() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onComplete(); + + assertEquals(Arrays.asList(1, "OnComplete"), events); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteError() { + + subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + processor.onNext(1); + + assertTrue(composite.size() > 0); + + assertEquals(Arrays.asList(1), events); + + processor.onError(new IOException()); + + assertEquals(events.toString(), 1, events.get(0)); + assertTrue(events.toString(), events.get(1) instanceof IOException); + + assertEquals(0, composite.size()); + } + + @Test + public void onCompleteDispose() { + + Disposable d = subscribeAutoDispose(processor, composite, this, this, this); + + assertTrue(composite.size() > 0); + + assertTrue(events.toString(), events.isEmpty()); + + assertFalse(d.isDisposed()); + + d.dispose(); + d.dispose(); + + assertTrue(d.isDisposed()); + + assertEquals(0, composite.size()); + + assertFalse(processor.hasSubscribers()); + } + + @Test + public void onNextCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, new Consumer() { + @Override + public void accept(Object t) throws Exception { + throw new IOException(); + } + }, this, this); + + processor.onNext(1); + + assertTrue(errors.toString(), errors.isEmpty()); + + assertTrue(events.toString(), events.get(0) instanceof IOException); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onNextCrashOnError() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, new Consumer() { + @Override + public void accept(Throwable t) throws Exception { + throw new IOException(t); + } + }, this); + + processor.onError(new IllegalArgumentException()); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, CompositeException.class); + List inners = TestHelper.compositeList(errors.get(0)); + TestHelper.assertError(inners, 0, IllegalArgumentException.class); + TestHelper.assertError(inners, 1, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onNextCrashNoError() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, new Consumer() { + @Override + public void accept(Object t) throws Exception { + throw new IOException(); + } + }, Functions.ON_ERROR_MISSING, () -> { }); + + processor.onNext(1); + + assertTrue(events.toString(), events.isEmpty()); + + TestHelper.assertError(errors, 0, OnErrorNotImplementedException.class); + assertTrue(errors.get(0).getCause() instanceof IOException); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void onCompleteCrash() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose(processor, composite, this, this, new Action() { + @Override + public void run() throws Exception { + throw new IOException(); + } + }); + + processor.onNext(1); + processor.onComplete(); + + assertEquals(Arrays.asList(1), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void badSource() { + List errors = TestHelper.trackPluginErrors(); + try { + subscribeAutoDispose( + new Flowable() { + @Override + protected void subscribeActual( + Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + s.onNext(1); + s.onComplete(); + + s.onSubscribe(new BooleanSubscription()); + s.onNext(2); + s.onComplete(); + s.onError(new IOException()); + } + }, composite, this, this, this + ); + + assertEquals(Arrays.asList(1, "OnComplete"), events); + + TestHelper.assertUndeliverable(errors, 0, IOException.class); + } finally { + RxJavaPlugins.reset(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriberTest.java index 69450f2ad05..56de26e5d61 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/FutureSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class FutureSubscriberTest extends RxJavaTest { @@ -155,6 +155,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorCancelRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final FutureSubscriber fs = new FutureSubscriber<>(); @@ -180,6 +181,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onCompleteCancelRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { final FutureSubscriber fs = new FutureSubscriber<>(); @@ -211,6 +213,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorOnComplete() throws Exception { fs.onError(new TestException("One")); fs.onComplete(); @@ -224,6 +227,7 @@ public void onErrorOnComplete() throws Exception { } @Test + @SuppressUndeliverable public void onCompleteOnError() throws Exception { fs.onComplete(); fs.onError(new TestException("One")); @@ -236,6 +240,7 @@ public void onCompleteOnError() throws Exception { } @Test + @SuppressUndeliverable public void cancelOnError() throws Exception { fs.cancel(true); fs.onError(new TestException("One")); @@ -249,6 +254,7 @@ public void cancelOnError() throws Exception { } @Test + @SuppressUndeliverable public void cancelOnComplete() throws Exception { fs.cancel(true); fs.onComplete(); @@ -292,4 +298,20 @@ public void getTimedOut() throws Exception { assertEquals(timeoutMessage(1, TimeUnit.NANOSECONDS), expected.getMessage()); } } + + @Test + public void onNextCompleteOnError() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + fs.onNext(1); + fs.onComplete(); + fs.onError(new TestException("One")); + + assertEquals((Integer)1, fs.get(5, TimeUnit.MILLISECONDS)); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberTest.java index e6533166cec..7856ce5d3ea 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/InnerQueuedSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriberTest.java index 17e4fb2fc95..e7f3931096c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/LambdaSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class LambdaSubscriberTest extends RxJavaTest { @@ -246,6 +246,7 @@ public void accept(Subscription s) throws Exception { } @Test + @SuppressUndeliverable public void badSourceEmitAfterDone() { Flowable source = Flowable.fromPublisher(new Publisher() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriberTest.java index 6d09484d559..985705b0e7c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/QueueDrainSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,8 +23,8 @@ import io.reactivex.rxjava3.core.RxJavaTest; import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.MissingBackpressureException; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriberTest.java index 1a9bb1310b0..8616e6ba3be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/SinglePostCompleteSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriberTest.java index 1b36462c470..ba4548d02ec 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/StrictSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapperTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapperTest.java index bafc579b639..65f2817354e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscribers/SubscriberResourceWrapperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscriptionTest.java index 9dd0cab6a5b..fc54cfe3570 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ArrayCompositeSubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscriptionTest.java index 30d93a22ae3..0375d72ba57 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/AsyncSubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscriptionTest.java index dfe9e83f89f..7ea8d58c3fe 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/DeferredScalarSubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/QueueSubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/QueueSubscriptionTest.java index fb3f66397f6..92c37e0e526 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/QueueSubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/QueueSubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscriptionTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscriptionTest.java index 55a564280c4..377691e0a25 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscriptionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/ScalarSubscriptionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiterTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiterTest.java index 4651b2e3b82..7bc7eb937aa 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiterTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionArbiterTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelperTest.java index 13a2dc61aa5..9bb222fbb83 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/subscriptions/SubscriptionHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/AtomicThrowableTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/AtomicThrowableTest.java index efe3b5c7b20..152039fac3e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/AtomicThrowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/AtomicThrowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/BackpressureHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/BackpressureHelperTest.java index ca0b0e26689..d13cde57beb 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/BackpressureHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/BackpressureHelperTest.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/BlockingHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/BlockingHelperTest.java index 419febcaee5..0218185f08e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/BlockingHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/BlockingHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/CrashingIterable.java b/src/test/java/io/reactivex/rxjava3/internal/util/CrashingIterable.java index bb053c23b0e..6bdbea27b15 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/CrashingIterable.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/CrashingIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/CrashingMappedIterable.java b/src/test/java/io/reactivex/rxjava3/internal/util/CrashingMappedIterable.java index caf09b372e0..d6b9491e2b5 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/CrashingMappedIterable.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/CrashingMappedIterable.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/EndConsumerHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/EndConsumerHelperTest.java index 1cb96e732f0..8ad19429464 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/EndConsumerHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/EndConsumerHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/ExceptionHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/ExceptionHelperTest.java index 70b70aea1f7..130cf5767be 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/ExceptionHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/ExceptionHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerObserverTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerObserverTest.java index cbb66e6425f..ea8c405849b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import static org.junit.Assert.assertTrue; @@ -160,6 +161,7 @@ public void onComplete() { } @Test + @SuppressUndeliverable @SuppressWarnings({ "rawtypes", "unchecked" }) public void reentrantErrorOnError() { final AtomicInteger wip = new AtomicInteger(); @@ -234,6 +236,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorOnCompleteRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerSubscriberTest.java index 44eea4907cb..19198646481 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/HalfSerializerSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import static org.junit.Assert.assertTrue; @@ -166,6 +167,7 @@ public void onComplete() { } @Test + @SuppressUndeliverable @SuppressWarnings({ "rawtypes", "unchecked" }) public void reentrantErrorOnError() { final AtomicInteger wip = new AtomicInteger(); @@ -240,6 +242,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorOnCompleteRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java b/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java index 985ac202c3e..1a55807dd08 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.io.File; diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java index aa388a684ae..2fdc7fe2d61 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.awt.image.BufferedImage; diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/MergerBiFunctionTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/MergerBiFunctionTest.java index dce15c4b28c..b8a5f8b8433 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/MergerBiFunctionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/MergerBiFunctionTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/MiscUtilTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/MiscUtilTest.java index b27279eb432..adc779a302c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/MiscUtilTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/MiscUtilTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -60,9 +60,13 @@ public void errorModeEnum() { @Test public void linkedArrayList() { LinkedArrayList list = new LinkedArrayList(2); + assertEquals(0, list.size()); list.add(1); + assertEquals(1, list.size()); list.add(2); + assertEquals(2, list.size()); list.add(3); + assertEquals(3, list.size()); assertEquals("[1, 2, 3]", list.toString()); } diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/NotificationLiteTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/NotificationLiteTest.java index 7e701ff5b96..7638a98ead9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/NotificationLiteTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/NotificationLiteTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/ObservableToFlowabeTestSync.java b/src/test/java/io/reactivex/rxjava3/internal/util/ObservableToFlowabeTestSync.java index fbe13a185e2..7bf668e2f1e 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/ObservableToFlowabeTestSync.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/ObservableToFlowabeTestSync.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OpenHashSetTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/OpenHashSetTest.java index c87bd13192f..f8c1bdf04da 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OpenHashSetTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OpenHashSetTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java index 727b522d05c..1814a26bbc0 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 714a6809f9a..9c5f058ff45 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/QueueDrainHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/QueueDrainHelperTest.java index 5fac86182a5..7929ea8782b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/QueueDrainHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/QueueDrainHelperTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,9 +27,9 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.BooleanSupplier; -import io.reactivex.rxjava3.internal.queue.SpscArrayQueue; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.SpscArrayQueue; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.TestHelper; diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/TestingHelper.java b/src/test/java/io/reactivex/rxjava3/internal/util/TestingHelper.java index 976757acd78..207c85236d6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/TestingHelper.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/TestingHelper.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.internal.util; import java.util.*; diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayListTest.java b/src/test/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayListTest.java index c59537c988b..3ce08aa3dc8 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayListTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/VolatileSizeArrayListTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeCreateTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeCreateTest.java index 152a297e8d7..e3bbfb4bfc1 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeCreateTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeCreateTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeRetryTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeRetryTest.java index 6c88f8501c8..731dd03e23b 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeRetryTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeRetryTest.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2017-present, RxJava Contributors. +/* + * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java index 401bdcc918e..acc7066c292 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,10 +30,10 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.operators.flowable.FlowableZipTest.ArgsToString; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.schedulers.Schedulers; diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTimerTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTimerTest.java index 03f229483be..286639042df 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableCombineLatestTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableCombineLatestTests.java index b4b11420d12..957268ecf19 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableCombineLatestTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableCombineLatestTests.java @@ -1,18 +1,16 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observable; import org.junit.Test; diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableConcatTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableConcatTests.java index f867a165d2c..53c4f990297 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableConcatTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableConcatTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observable; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableCovarianceTest.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableCovarianceTest.java index e7e3302fd81..54cf0f9908f 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableCovarianceTest.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableCovarianceTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.observable; diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableDoOnTest.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableDoOnTest.java index 6c3b5f54ab5..0e7ed9ef889 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableDoOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableDoOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableErrorHandlingTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableErrorHandlingTests.java index c524261032e..9ec13895b01 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableErrorHandlingTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableErrorHandlingTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableEventStream.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableEventStream.java index 6b161dcb0ac..48e637f5c3a 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableEventStream.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableEventStream.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableFuseableTest.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableFuseableTest.java index 1d01a790ab2..8de9b9bc0bb 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableFuseableTest.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableFuseableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.observable; import java.util.Arrays; @@ -17,7 +18,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.TestHelper; public class ObservableFuseableTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableGroupByTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableGroupByTests.java index e5de6cdc85c..1db6ebb9088 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableGroupByTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableGroupByTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableMergeTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableMergeTests.java index 902bcd7ba1c..25a3317b7fe 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableMergeTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableMergeTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableNullTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableNullTests.java index 4189438e32e..178adb62306 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableNullTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableNullTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableReduceTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableReduceTests.java index 8dec71b98e9..01c2106affe 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableReduceTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableReduceTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableScanTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableScanTests.java index bc73a886b24..8bc33ac19f8 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableScanTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableScanTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableStartWithTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableStartWithTests.java index 9c9261273c3..8e0fe35add0 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableStartWithTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableStartWithTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableSubscriberTest.java index 60e8470ca42..c8a1047fe39 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableTest.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableTest.java index 030687e989a..87e6463d3cd 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleLastTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleLastTests.java index e93f9409e0c..d8107cc4344 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleLastTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleLastTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -13,10 +13,10 @@ package io.reactivex.rxjava3.observable; -import static org.mockito.Mockito.inOrder; - import java.util.concurrent.TimeUnit; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Action; import org.junit.Test; import org.mockito.InOrder; @@ -25,8 +25,78 @@ import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.testsupport.TestHelper; +import static org.mockito.Mockito.*; + public class ObservableThrottleLastTests extends RxJavaTest { + @Test + public void throttleLastWithDropCallbackException() throws Throwable { + Observer observer = TestHelper.mockObserver(); + + Action whenDisposed = mock(Action.class); + + TestScheduler s = new TestScheduler(); + PublishSubject o = PublishSubject.create(); + o.doOnDispose(whenDisposed) + .throttleLast(500, TimeUnit.MILLISECONDS, s, e -> { + if (e == 1) { + throw new TestException("Forced"); + } + }) + .subscribe(observer); + + // send events with simulated time increments + s.advanceTimeTo(0, TimeUnit.MILLISECONDS); + o.onNext(1); // skip + o.onNext(2); // try to deliver + s.advanceTimeTo(501, TimeUnit.MILLISECONDS); + + InOrder inOrder = inOrder(observer); + inOrder.verify(observer).onError(any(TestException.class)); + inOrder.verifyNoMoreInteractions(); + verify(whenDisposed).run(); + } + + @Test + public void throttleLastWithDropCallback() { + Observer observer = TestHelper.mockObserver(); + + Observer dropCallbackObserver = TestHelper.mockObserver(); + + TestScheduler s = new TestScheduler(); + PublishSubject o = PublishSubject.create(); + o.throttleLast(500, TimeUnit.MILLISECONDS, s, dropCallbackObserver::onNext).subscribe(observer); + + // send events with simulated time increments + s.advanceTimeTo(0, TimeUnit.MILLISECONDS); + o.onNext(1); // skip + o.onNext(2); // deliver + s.advanceTimeTo(501, TimeUnit.MILLISECONDS); + o.onNext(3); // skip + s.advanceTimeTo(600, TimeUnit.MILLISECONDS); + o.onNext(4); // skip + s.advanceTimeTo(700, TimeUnit.MILLISECONDS); + o.onNext(5); // skip + o.onNext(6); // deliver + s.advanceTimeTo(1001, TimeUnit.MILLISECONDS); + o.onNext(7); // deliver + s.advanceTimeTo(1501, TimeUnit.MILLISECONDS); + o.onComplete(); + + InOrder inOrder = inOrder(observer); + InOrder dropCallbackOrder = inOrder(dropCallbackObserver); + dropCallbackOrder.verify(dropCallbackObserver).onNext(1); + inOrder.verify(observer).onNext(2); + dropCallbackOrder.verify(dropCallbackObserver).onNext(3); + dropCallbackOrder.verify(dropCallbackObserver).onNext(4); + dropCallbackOrder.verify(dropCallbackObserver).onNext(5); + inOrder.verify(observer).onNext(6); + inOrder.verify(observer).onNext(7); + inOrder.verify(observer).onComplete(); + inOrder.verifyNoMoreInteractions(); + dropCallbackOrder.verifyNoMoreInteractions(); + } + @Test public void throttle() { Observer observer = TestHelper.mockObserver(); diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleWithTimeoutTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleWithTimeoutTests.java index bcacab55133..80f82fb5f4f 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleWithTimeoutTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableThrottleWithTimeoutTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableWindowTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableWindowTests.java index 9e1076017a4..4bc561bd1b2 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableWindowTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableWindowTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observable/ObservableZipTests.java b/src/test/java/io/reactivex/rxjava3/observable/ObservableZipTests.java index 1f671133485..b2b26719bb3 100644 --- a/src/test/java/io/reactivex/rxjava3/observable/ObservableZipTests.java +++ b/src/test/java/io/reactivex/rxjava3/observable/ObservableZipTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/DisposableCompletableObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/DisposableCompletableObserverTest.java index 19ee3e7f06d..fde1dc75de6 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/DisposableCompletableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/DisposableCompletableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/DisposableMaybeObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/DisposableMaybeObserverTest.java index 36dc6a6d3b3..7bd2f20a95a 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/DisposableMaybeObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/DisposableMaybeObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/DisposableObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/DisposableObserverTest.java index c2b766e7615..1b5b477552e 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/DisposableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/DisposableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/DisposableSingleObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/DisposableSingleObserverTest.java index b6239d65ee2..8dac144591f 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/DisposableSingleObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/DisposableSingleObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/ResourceCompletableObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/ResourceCompletableObserverTest.java index f0079405920..e2d1fa34bac 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/ResourceCompletableObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/ResourceCompletableObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/ResourceMaybeObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/ResourceMaybeObserverTest.java index 08d06044e76..257a5785f86 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/ResourceMaybeObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/ResourceMaybeObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/ResourceObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/ResourceObserverTest.java index 94934d82df3..543095582bb 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/ResourceObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/ResourceObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/ResourceSingleObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/ResourceSingleObserverTest.java index b720931088f..10f17e18d62 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/ResourceSingleObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/ResourceSingleObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/observers/SafeObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/SafeObserverTest.java index 3afced2d407..77b3d7b9b9f 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/SafeObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/SafeObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -221,6 +221,7 @@ public void dispose() { } @Test + @SuppressUndeliverable public void onNextAfterComplete() { TestObserver to = new TestObserver<>(); diff --git a/src/test/java/io/reactivex/rxjava3/observers/SerializedObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/SerializedObserverTest.java index e581012d9bc..689908f59fc 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/SerializedObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/SerializedObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,7 +24,7 @@ import org.junit.*; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.util.ExceptionHelper; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -340,11 +340,11 @@ public void onNext(String t) { * * When using SynchronizedSubscriber we get this output: * - * p1: 18 p2: 68 => should be close to each other unless we have thread starvation + * {@code p1: 18 p2: 68 =>} should be close to each other unless we have thread starvation * * When using SerializedObserver we get: * - * p1: 1 p2: 2445261 => should be close to each other unless we have thread starvation + * {@code p1: 1 p2: 2445261 =>} should be close to each other unless we have thread starvation * * This demonstrates how SynchronizedSubscriber balances back and forth better, and blocks emission. * The real issue in this example is the async buffer-bloat, so we need backpressure. @@ -1142,4 +1142,29 @@ public void nullOnNext() { to.assertFailureAndMessage(NullPointerException.class, ExceptionHelper.nullWarning("onNext called with a null value.")); } + + @Test + @SuppressUndeliverable + public void onErrorQueuedUp() { + AtomicReference> soRef = new AtomicReference<>(); + TestObserverEx to = new TestObserverEx() { + @Override + public void onNext(Integer t) { + super.onNext(t); + soRef.get().onNext(2); + soRef.get().onError(new TestException()); + } + }; + + final SerializedObserver so = new SerializedObserver<>(to, true); + soRef.set(so); + + Disposable d = Disposable.empty(); + + so.onSubscribe(d); + + so.onNext(1); + + to.assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/observers/TestObserverTest.java b/src/test/java/io/reactivex/rxjava3/observers/TestObserverTest.java index 01d6d76789f..f2d5f206c35 100644 --- a/src/test/java/io/reactivex/rxjava3/observers/TestObserverTest.java +++ b/src/test/java/io/reactivex/rxjava3/observers/TestObserverTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import org.junit.Test; +import org.junit.function.ThrowingRunnable; import org.mockito.InOrder; import org.reactivestreams.Subscriber; @@ -39,6 +40,16 @@ public class TestObserverTest extends RxJavaTest { + static void assertThrowsWithMessage(String message, Class clazz, ThrowingRunnable run) { + assertEquals(message, assertThrows(clazz, run).getMessage()); + } + + static void assertThrowsWithMessageMatchRegex(String regex, Class clazz, ThrowingRunnable run) { + assertTrue(assertThrows(clazz, run).getMessage().matches(regex)); + } + + private static final String ASSERT_MESSAGE_REGEX = "\nexpected: (.*)\n\\s*got: (.*)"; + @Test public void assertTestObserver() { Flowable oi = Flowable.fromIterable(Arrays.asList(1, 2)); @@ -843,7 +854,7 @@ public void errorMeansDisposed() { @Test public void assertValuePredicateEmpty() { - assertThrows("No values", AssertionError.class, () -> { + assertThrowsWithMessage("No values (latch = 0, values = 0, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.empty().subscribe(to); @@ -871,7 +882,7 @@ public void assertValuePredicateMatch() { @Test public void assertValuePredicateNoMatch() { - assertThrows("Value not present", AssertionError.class, () -> { + assertThrowsWithMessage("Value 1 (class: Integer) at position 0 did not pass the predicate (latch = 0, values = 1, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just(1).subscribe(to); @@ -886,7 +897,7 @@ public void assertValuePredicateNoMatch() { @Test public void assertValuePredicateMatchButMore() { - assertThrows("Value present but other values as well", AssertionError.class, () -> { + assertThrowsWithMessage("The first value passed the predicate but this consumer received more than one value (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just(1, 2).subscribe(to); @@ -901,7 +912,7 @@ public void assertValuePredicateMatchButMore() { @Test public void assertValueAtPredicateEmpty() { - assertThrows("No values", AssertionError.class, () -> { + assertThrowsWithMessage("No values (latch = 0, values = 0, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.empty().subscribe(to); @@ -929,7 +940,7 @@ public void assertValueAtPredicateMatch() { @Test public void assertValueAtPredicateNoMatch() { - assertThrows("Value not present", AssertionError.class, () -> { + assertThrowsWithMessage("Value 3 (class: Integer) at position 2 did not pass the predicate (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just(1, 2, 3).subscribe(to); @@ -944,7 +955,7 @@ public void assertValueAtPredicateNoMatch() { @Test public void assertValueAtInvalidIndex() { - assertThrows("Invalid index: 2 (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + assertThrowsWithMessage("Index 2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just(1, 2).subscribe(to); @@ -957,9 +968,24 @@ public void assertValueAtInvalidIndex() { }); } + @Test + public void assertValueAtInvalidIndexNegative() { + assertThrowsWithMessage("Index -2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just(1, 2).subscribe(to); + + to.assertValueAt(-2, new Predicate() { + @Override public boolean test(final Integer o) throws Exception { + return o == 1; + } + }); + }); + } + @Test public void assertValueAtIndexEmpty() { - assertThrows("No values", AssertionError.class, () -> { + assertThrowsWithMessage("No values (latch = 0, values = 0, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.empty().subscribe(to); @@ -979,7 +1005,18 @@ public void assertValueAtIndexMatch() { @Test public void assertValueAtIndexNoMatch() { - assertThrows("expected: b (class: String) but was: c (class: String) (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + assertThrowsWithMessage("\nexpected: b (class: String)\ngot: c (class: String); Value at position 2 differ (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValueAt(2, "b"); + }); + } + + @Test + public void assertValueAtIndexThrowsMessageMatchRegex() { + assertThrowsWithMessageMatchRegex(ASSERT_MESSAGE_REGEX, AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just("a", "b", "c").subscribe(to); @@ -988,9 +1025,97 @@ public void assertValueAtIndexNoMatch() { }); } + @Test + public void assertValuesCountNoMatch() { + assertThrowsWithMessage("\nexpected: 2 [a, b]\ngot: 3 [a, b, c]; Value count differs (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValues("a", "b"); + }); + } + + @Test + public void assertValuesCountThrowsMessageMatchRegex() { + assertThrowsWithMessageMatchRegex(ASSERT_MESSAGE_REGEX, AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValues("a", "b"); + }); + } + + @Test + public void assertValuesNoMatch() { + assertThrowsWithMessage("\nexpected: d (class: String)\ngot: c (class: String); Value at position 2 differ (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValues("a", "b", "d"); + }); + } + + @Test + public void assertValuesThrowsMessageMatchRegex() { + assertThrowsWithMessageMatchRegex(ASSERT_MESSAGE_REGEX, AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValues("a", "b", "d"); + }); + } + + @Test + public void assertValueCountNoMatch() { + assertThrowsWithMessage("\nexpected: 2\ngot: 3; Value counts differ (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValueCount(2); + }); + } + + @Test + public void assertValueCountThrowsMessageMatchRegex() { + assertThrowsWithMessageMatchRegex(ASSERT_MESSAGE_REGEX, AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValueCount(2); + }); + } + + @Test + public void assertValueSequenceNoMatch() { + assertThrowsWithMessage("\nexpected: d (class: String)\ngot: c (class: String); Value at position 2 differ (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValueSequence(Arrays.asList("a", "b", "d")); + }); + } + + @Test + public void assertValueSequenceThrowsMessageMatchRegex() { + assertThrowsWithMessageMatchRegex(ASSERT_MESSAGE_REGEX, AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b", "c").subscribe(to); + + to.assertValueSequence(Arrays.asList("a", "b", "d")); + }); + } + @Test public void assertValueAtIndexInvalidIndex() { - assertThrows("Invalid index: 2 (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + assertThrowsWithMessage("Index 2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserver to = new TestObserver<>(); Observable.just("a", "b").subscribe(to); @@ -999,6 +1124,17 @@ public void assertValueAtIndexInvalidIndex() { }); } + @Test + public void assertValueAtIndexInvalidIndexNegative() { + assertThrowsWithMessage("Index -2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + TestObserver to = new TestObserver<>(); + + Observable.just("a", "b").subscribe(to); + + to.assertValueAt(-2, "c"); + }); + } + @Test public void withTag() { try { @@ -1076,4 +1212,34 @@ public void assertValuesOnlyThrowsWhenErrored() { // expected } } + + @Test + public void onErrorIsNull() { + TestObserver to = TestObserver.create(); + to.onSubscribe(Disposable.empty()); + + to.onError(null); + + to.assertFailure(NullPointerException.class); + } + + @Test + public void awaitCountTimeout() { + TestObserver to = TestObserver.create(); + to.onSubscribe(Disposable.empty()); + to.awaitCount(1); + assertTrue(to.timeout); + } + + @Test(expected = RuntimeException.class) + public void awaitCountInterrupted() { + try { + TestObserver to = TestObserver.create(); + to.onSubscribe(Disposable.empty()); + Thread.currentThread().interrupt(); + to.awaitCount(1); + } finally { + Thread.interrupted(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/queue/SimpleQueueTest.java b/src/test/java/io/reactivex/rxjava3/operators/SimpleQueueTest.java similarity index 97% rename from src/test/java/io/reactivex/rxjava3/internal/queue/SimpleQueueTest.java rename to src/test/java/io/reactivex/rxjava3/operators/SimpleQueueTest.java index e5673b49bc7..b9f998c1deb 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/queue/SimpleQueueTest.java +++ b/src/test/java/io/reactivex/rxjava3/operators/SimpleQueueTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,7 +16,7 @@ * https://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/queues/atomic */ -package io.reactivex.rxjava3.internal.queue; +package io.reactivex.rxjava3.operators; import static org.junit.Assert.*; @@ -25,6 +25,7 @@ import org.junit.Test; import io.reactivex.rxjava3.core.RxJavaTest; +import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; public class SimpleQueueTest extends RxJavaTest { diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelCollectTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelCollectTest.java index 1a94b3c2471..f582966cf96 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelCollectTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelCollectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -163,4 +163,11 @@ public void accept(List a, Object b) throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeParallel( + pf -> pf.collect(ArrayList::new, ArrayList::add) + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelDoOnNextTryTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelDoOnNextTryTest.java index 0ba01a05fd3..ba76f69cfb5 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelDoOnNextTryTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelDoOnNextTryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -384,4 +384,23 @@ public void filterInvalidSourceConditional() { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .doOnNext(v -> { }, ParallelFailureHandling.SKIP) + .sequential() + ); + } + + @Test + public void doubleOnSubscribeConditional() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .doOnNext(v -> { }, ParallelFailureHandling.SKIP) + .filter(v -> true, ParallelFailureHandling.SKIP) + .sequential() + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTest.java index 1b774509866..31e9b9a7c41 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -119,4 +119,45 @@ public boolean test(Integer v) throws Exception { .test() .assertFailure(TestException.class); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .filter(v -> true) + .sequential() + ); + } + + @Test + public void doubleOnSubscribeConditional() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .filter(v -> true) + .filter(v -> true) + .sequential() + ); + } + + @Test + public void conditionalFalseTrue() { + Flowable.just(1) + .parallel() + .filter(v -> false) + .filter(v -> true) + .sequential() + .test() + .assertResult(); + } + + @Test + public void conditionalTrueFalse() { + Flowable.just(1) + .parallel() + .filter(v -> true) + .filter(v -> false) + .sequential() + .test() + .assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTryTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTryTest.java index 084566a0a5a..69400629897 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTryTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFilterTryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -373,4 +373,45 @@ public void filterInvalidSourceConditional() { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .filter(v -> true, ParallelFailureHandling.SKIP) + .sequential() + ); + } + + @Test + public void doubleOnSubscribeConditional() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .filter(v -> true, ParallelFailureHandling.SKIP) + .filter(v -> true, ParallelFailureHandling.SKIP) + .sequential() + ); + } + + @Test + public void conditionalFalseTrue() { + Flowable.just(1) + .parallel() + .filter(v -> false, ParallelFailureHandling.SKIP) + .filter(v -> true, ParallelFailureHandling.SKIP) + .sequential() + .test() + .assertResult(); + } + + @Test + public void conditionalTrueFalse() { + Flowable.just(1) + .parallel() + .filter(v -> true, ParallelFailureHandling.SKIP) + .filter(v -> false, ParallelFailureHandling.SKIP) + .sequential() + .test() + .assertResult(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlatMapIterableTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlatMapIterableTest.java index 916d3651b93..8c18de1b0b8 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlatMapIterableTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlatMapIterableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,7 +14,6 @@ package io.reactivex.rxjava3.parallel; import java.util.Arrays; -import java.util.stream.Stream; import org.junit.Test; @@ -25,7 +24,7 @@ public class ParallelFlatMapIterableTest extends RxJavaTest { @Test public void subscriberCount() { ParallelFlowableTest.checkSubscriberCount(Flowable.range(1, 5).parallel() - .flatMapStream(v -> Stream.of(1, 2, 3))); + .flatMapIterable(v -> Arrays.asList(1, 2, 3))); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlowableTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlowableTest.java index 1d1f97163fe..c97bc5cf567 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlowableTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFlowableTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFromPublisherTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFromPublisherTest.java index c790201d98b..7d4e684bb68 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelFromPublisherTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelFromPublisherTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -21,14 +21,16 @@ import org.junit.Test; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscribers.BasicFuseableSubscriber; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; -import io.reactivex.rxjava3.processors.UnicastProcessor; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; @@ -48,7 +50,7 @@ protected void subscribeActual(Subscriber s) { .parallel(1, 1) .sequential(1) .test(0) - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); } @Test @@ -187,4 +189,107 @@ public Object apply(Integer v) throws Exception { assertTrue(map.toString(), e.contains("RxComputationThreadPool")); } } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(PublishProcessor.create().parallel()); + } + + @Test + public void syncFusedEmptyPoll() { + Flowable.just(1, 2) + .filter(v -> v == 1) + .compose(TestHelper.flowableStripBoundary()) + .parallel(1) + .sequential() + .test() + .assertResult(1); + } + + @Test + public void asyncFusedEmptyPoll() { + UnicastProcessor up = UnicastProcessor.create(); + up.onNext(1); + up.onNext(2); + up.onComplete(); + + up + .filter(v -> v == 1) + .compose(TestHelper.flowableStripBoundary()) + .parallel(1) + .sequential() + .test() + .assertResult(1); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.parallel().sequential()); + } + + @SuppressWarnings("unchecked") + @Test + public void requestUnboundedRace() { + FlowableSubscriber fs = new FlowableSubscriber() { + + @Override + public void onNext(@NonNull Integer t) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + } + + @Override + public void onSubscribe(@NonNull Subscription s) { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestHelper.race( + () -> s.request(Long.MAX_VALUE), + () -> s.request(Long.MAX_VALUE) + ); + } + } + }; + + PublishProcessor.create() + .parallel(1) + .subscribe(new FlowableSubscriber[] { fs }); + } + + @SuppressWarnings("unchecked") + @Test + public void requestRace() { + FlowableSubscriber fs = new FlowableSubscriber() { + + @Override + public void onNext(@NonNull Integer t) { + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + } + + @Override + public void onSubscribe(@NonNull Subscription s) { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + TestHelper.race( + () -> s.request(1), + () -> s.request(1) + ); + } + } + }; + + PublishProcessor.create() + .parallel(1) + .subscribe(new FlowableSubscriber[] { fs }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelInvalid.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelInvalid.java index 39e8ac21cfd..6b54ca6847e 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelInvalid.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelInvalid.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelJoinTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelJoinTest.java index fb50a775f80..8ee41cb9739 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelJoinTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -14,14 +14,17 @@ package io.reactivex.rxjava3.parallel; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import org.reactivestreams.Subscriber; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.processors.PublishProcessor; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -45,7 +48,7 @@ public int parallelism() { } .sequential(1) .test(0) - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); } @Test @@ -78,7 +81,7 @@ public int parallelism() { .sequential(1) .subscribe(ts); - ts.assertFailure(MissingBackpressureException.class, 1); + ts.assertFailure(QueueOverflowException.class, 1); } @Test @@ -108,7 +111,7 @@ public int parallelism() { .sequentialDelayError(1) .test(0) .requestMore(1) - .assertFailure(MissingBackpressureException.class, 1); + .assertFailure(QueueOverflowException.class, 1); } @Test @@ -145,7 +148,7 @@ public int parallelism() { ts.request(1); - ts.assertFailure(MissingBackpressureException.class, 1, 2); + ts.assertFailure(QueueOverflowException.class, 1, 2); } @Test @@ -326,4 +329,198 @@ public Integer apply(Integer v) throws Exception { .test() .assertFailure(TestException.class, 2, 3, 4); } + + @Test + public void takeUntil() { + Flowable.range(1, 10) + .parallel(1) + .sequential() + .takeUntil(v -> true) + .test(0L) + .requestMore(100) + .assertResult(1); + } + + @Test + public void takeUntilDelayError() { + Flowable.range(1, 10) + .parallel(1) + .sequentialDelayError() + .takeUntil(v -> true) + .test(0L) + .requestMore(100) + .assertResult(1); + } + + @Test + public void oneItemNext() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.parallel(1) + .sequential() + .test(0L); + + pp.onNext(1); + + ts.requestMore(10) + .assertValuesOnly(1); + } + + @Test + public void delayErrorOneItemNext() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp.parallel(1) + .sequentialDelayError() + .test(0L); + + pp.onNext(1); + + ts.requestMore(10) + .assertValuesOnly(1); + } + + @Test + public void onNextWhileProcessingSlowPath() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + if (t == 1) { + pp.onNext(2); + } + } + }; + + ParallelFlowable.fromArray(pp) + .sequential() + .subscribeWith(ts); + + pp.onNext(1); + + ts + .assertValuesOnly(1, 2); + } + + @Test + public void delayErrorOnNextWhileProcessingSlowPath() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + if (t == 1) { + pp.onNext(2); + } + } + }; + + ParallelFlowable.fromArray(pp) + .sequentialDelayError() + .subscribeWith(ts); + + pp.onNext(1); + + ts + .assertValuesOnly(1, 2); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported( + ParallelFlowable.fromArray(PublishProcessor.create()) + .sequential() + ); + } + + @Test + public void onNextMissingBackpressureRace() throws Throwable { + TestHelper.withErrorTracking(errors -> { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Flowable f1 = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + ref1.set(s); + } + }; + Flowable f2 = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + ref2.set(s); + } + }; + + ParallelFlowable.fromArray(f1, f2) + .sequential(1) + .test(0) + ; + + TestHelper.race( + () -> { + ref1.get().onNext(1); + ref1.get().onNext(2); + }, + () -> { + ref2.get().onNext(3); + ref2.get().onNext(4); + } + ); + + errors.clear(); + } + }); + } + + @Test + public void onNextMissingBackpressureDelayErrorRace() throws Throwable { + TestHelper.withErrorTracking(errors -> { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + + AtomicReference> ref1 = new AtomicReference<>(); + AtomicReference> ref2 = new AtomicReference<>(); + + Flowable f1 = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + ref1.set(s); + } + }; + Flowable f2 = new Flowable() { + @Override + public void subscribeActual(Subscriber s) { + s.onSubscribe(new BooleanSubscription()); + ref2.set(s); + } + }; + + ParallelFlowable.fromArray(f1, f2) + .sequentialDelayError(1) + .test(0) + ; + + TestHelper.race( + () -> { + ref1.get().onNext(1); + ref1.get().onNext(2); + }, + () -> { + ref2.get().onNext(3); + ref2.get().onNext(4); + } + ); + + errors.clear(); + } + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTest.java index e45034d416c..493b74d34ed 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -15,15 +15,19 @@ import static org.junit.Assert.*; -import java.util.*; +import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.Test; +import org.reactivestreams.Subscriber; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.TestHelper; @@ -199,4 +203,25 @@ public void doubleOnSubscribe() { .filter(v -> true) ); } + + @Test + public void conditionalCancelIgnored() { + Flowable f = new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super @NonNull Integer> s) { + @SuppressWarnings("unchecked") + ConditionalSubscriber subscriber = (ConditionalSubscriber)s; + subscriber.onSubscribe(new BooleanSubscription()); + subscriber.tryOnNext(1); + subscriber.tryOnNext(2); + } + }; + + ParallelFlowable.fromArray(f) + .map(v -> { throw new TestException(); }) + .filter(v -> true) + .sequential() + .test() + .assertFailure(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTryTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTryTest.java index d56669d755c..a6d0de2d92e 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTryTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelMapTryTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelPeekTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelPeekTest.java index 85b311847ae..93d72ef9f60 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelPeekTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelPeekTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class ParallelPeekTest extends RxJavaTest { @@ -37,6 +37,7 @@ public void subscriberCount() { } @Test + @SuppressUndeliverable public void onSubscribeCrash() { Flowable.range(1, 5) .parallel() @@ -125,6 +126,7 @@ public void run() throws Exception { } @Test + @SuppressUndeliverable public void onCompleteCrash() { Flowable.just(1) .parallel() @@ -194,4 +196,13 @@ public void run() throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> + ParallelFlowable.fromArray(f) + .doOnComplete(() -> { }) + .sequential() + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceFullTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceFullTest.java index 25d72af909a..d9a43a247c5 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceFullTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceFullTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,7 +16,7 @@ import static org.junit.Assert.*; import java.io.IOException; -import java.util.List; +import java.util.*; import org.junit.Test; @@ -164,4 +164,11 @@ public Integer apply(Integer a, Integer b) throws Exception { .test() .assertFailure(TestException.class); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeParallelToFlowable( + pf -> pf.reduce((a, b) -> a) + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceTest.java index 5646b176b10..9c32f6afc8a 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelReduceTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -169,4 +169,11 @@ public List apply(List a, Object b) throws Exception { RxJavaPlugins.reset(); } } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeParallel( + pf -> pf.reduce(ArrayList::new, (a, b) -> a) + ); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelRunOnTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelRunOnTest.java index 907b0bb8894..44a860263a7 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelRunOnTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelRunOnTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -98,7 +98,7 @@ public void subscribe(Subscriber[] subscribers) { .runOn(ImmediateThinScheduler.INSTANCE, 1) .sequential(1) .test(0) - .assertFailure(MissingBackpressureException.class); + .assertFailure(QueueOverflowException.class); } @Test @@ -322,4 +322,60 @@ public void onNext(Integer t) { ts.assertResult(1); } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeParallel(pf -> pf.runOn(ImmediateThinScheduler.INSTANCE)); + } + + @Test + public void doubleOnSubscribeConditional() { + TestHelper.checkDoubleOnSubscribeParallel(pf -> + pf.runOn(ImmediateThinScheduler.INSTANCE) + .filter(v -> true) + ); + } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported( + ParallelFlowable.fromArray(PublishProcessor.create()) + .runOn(ImmediateThinScheduler.INSTANCE) + ); + } + + @SuppressWarnings("unchecked") + @Test + public void asManyItemsAsRequested() { + TestSubscriber ts = new TestSubscriber<>(0); + + Flowable.range(1, 5) + .parallel(1) + .runOn(ImmediateThinScheduler.INSTANCE) + .subscribe(new Subscriber[] { + ts + }); + + ts + .requestMore(5) + .assertResult(1, 2, 3, 4, 5); + } + + @SuppressWarnings("unchecked") + @Test + public void asManyItemsAsRequestedConditional() { + TestSubscriber ts = new TestSubscriber<>(0); + + Flowable.range(1, 5) + .parallel(1) + .runOn(ImmediateThinScheduler.INSTANCE) + .filter(v -> true) + .subscribe(new Subscriber[] { + ts + }); + + ts + .requestMore(5) + .assertResult(1, 2, 3, 4, 5); + } } diff --git a/src/test/java/io/reactivex/rxjava3/parallel/ParallelSortedJoinTest.java b/src/test/java/io/reactivex/rxjava3/parallel/ParallelSortedJoinTest.java index e7b5cda9b0d..9ba23c30c27 100644 --- a/src/test/java/io/reactivex/rxjava3/parallel/ParallelSortedJoinTest.java +++ b/src/test/java/io/reactivex/rxjava3/parallel/ParallelSortedJoinTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,6 +24,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.internal.operators.parallel.ParallelSortedJoin; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -207,4 +208,32 @@ public void run() { TestHelper.race(r1, r2); } } + + @Test + public void badRequest() { + TestHelper.assertBadRequestReported(PublishProcessor.create().parallel().sorted(Functions.naturalComparator())); + } + + @Test + public void comparatorCrashWhileMainOnError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + PublishProcessor> pp1 = PublishProcessor.create(); + PublishProcessor> pp2 = PublishProcessor.create(); + + new ParallelSortedJoin<>(ParallelFlowable.fromArray(pp1, pp2) + , (a, b) -> { + pp1.onError(new IOException()); + throw new TestException(); + }) + .test(); + + pp1.onNext(Arrays.asList(1)); + pp2.onNext(Arrays.asList(2)); + + pp1.onComplete(); + pp2.onComplete(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } } diff --git a/src/test/java/io/reactivex/rxjava3/plugins/RxJavaPluginsTest.java b/src/test/java/io/reactivex/rxjava3/plugins/RxJavaPluginsTest.java index defc141800c..6aa166d118f 100644 --- a/src/test/java/io/reactivex/rxjava3/plugins/RxJavaPluginsTest.java +++ b/src/test/java/io/reactivex/rxjava3/plugins/RxJavaPluginsTest.java @@ -1,17 +1,14 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava3.plugins; @@ -592,6 +589,61 @@ public void onComplete() { .assertComplete(); } + @SuppressWarnings("rawtypes") + @Test + public void parallelFlowableStart() { + try { + RxJavaPlugins.setOnParallelSubscribe(new BiFunction() { + @Override + public Subscriber[] apply(ParallelFlowable f, final Subscriber[] t) { + return new Subscriber[] { new Subscriber() { + + @Override + public void onSubscribe(Subscription s) { + t[0].onSubscribe(s); + } + + @SuppressWarnings("unchecked") + @Override + public void onNext(Object value) { + t[0].onNext((Integer)value - 9); + } + + @Override + public void onError(Throwable e) { + t[0].onError(e); + } + + @Override + public void onComplete() { + t[0].onComplete(); + } + + } + }; + } + }); + + Flowable.range(10, 3) + .parallel(1) + .sequential() + .test() + .assertValues(1, 2, 3) + .assertNoErrors() + .assertComplete(); + } finally { + RxJavaPlugins.reset(); + } + // make sure the reset worked + Flowable.range(10, 3) + .parallel(1) + .sequential() + .test() + .assertValues(10, 11, 12) + .assertNoErrors() + .assertComplete(); + } + @SuppressWarnings("rawtypes") @Test public void singleCreate() { @@ -1176,6 +1228,7 @@ public void onComplete() { } AllSubscriber all = new AllSubscriber(); + Subscriber[] allArray = { all }; assertNull(RxJavaPlugins.onSubscribe(Observable.never(), null)); @@ -1197,6 +1250,10 @@ public void onComplete() { assertSame(all, RxJavaPlugins.onSubscribe(Maybe.never(), all)); + assertNull(RxJavaPlugins.onSubscribe(Flowable.never().parallel(), null)); + + assertSame(allArray, RxJavaPlugins.onSubscribe(Flowable.never().parallel(), allArray)); + final Scheduler s = ImmediateThinScheduler.INSTANCE; Supplier c = new Supplier() { @Override diff --git a/src/test/java/io/reactivex/rxjava3/processors/AsyncProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/AsyncProcessorTest.java index 6daaf15245c..81afc972dc7 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/AsyncProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/AsyncProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,8 +26,8 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.subscribers.TestSubscriber; import io.reactivex.rxjava3.testsupport.*; @@ -112,6 +112,7 @@ public void subscribeAfterError() { } @Test + @SuppressUndeliverable public void error() { AsyncProcessor processor = AsyncProcessor.create(); @@ -424,6 +425,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorCancelRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { @@ -481,6 +483,7 @@ public void onNext(Object t) { } @Test + @SuppressUndeliverable public void onErrorCrossCancel() { AsyncProcessor p = AsyncProcessor.create(); @@ -523,4 +526,9 @@ public void onComplete() { ts1.assertResult(); ts2.assertEmpty(); } + + @Test + public void cancel() { + TestHelper.checkDisposed(AsyncProcessor.create()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/processors/BehaviorProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/BehaviorProcessorTest.java index d49ba5f5658..991a599b82e 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/BehaviorProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/BehaviorProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -612,6 +612,36 @@ public void run() { } } + @Test + public void multipleSubscribersRemoveSomeRace() { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + final BehaviorProcessor p = BehaviorProcessor.create(); + + final TestSubscriber ts1 = p.test(); + final TestSubscriber ts2 = p.test(); + final TestSubscriber ts3 = p.test(); + + Runnable r1 = new Runnable() { + @Override + public void run() { + ts1.cancel(); + } + }; + + Runnable r2 = new Runnable() { + @Override + public void run() { + ts2.cancel(); + } + }; + + TestHelper.race(r1, r2); + + p.onNext(1); + ts3.assertValuesOnly(1); + } + } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void subscribeOnNextRace() { diff --git a/src/test/java/io/reactivex/rxjava3/processors/FlowableProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/FlowableProcessorTest.java index ae659623e05..1575a5669c3 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/FlowableProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/FlowableProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/processors/MulticastProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/MulticastProcessorTest.java index afa14b8deb8..0ac22cf1b2e 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/MulticastProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/MulticastProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/processors/PublishProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/PublishProcessorTest.java index 7c413d9dc0f..380f6445189 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/PublishProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/PublishProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class PublishProcessorTest extends FlowableProcessorTest { @@ -40,6 +40,7 @@ protected FlowableProcessor create() { } @Test + @SuppressUndeliverable public void completed() { PublishProcessor processor = PublishProcessor.create(); @@ -113,6 +114,7 @@ private void assertCompletedSubscriber(Subscriber subscriber) { } @Test + @SuppressUndeliverable public void error() { PublishProcessor processor = PublishProcessor.create(); @@ -434,6 +436,7 @@ public void onNext(Integer t) { } @Test + @SuppressUndeliverable public void crossCancelOnError() { final TestSubscriber ts1 = new TestSubscriber<>(); TestSubscriber ts2 = new TestSubscriber() { diff --git a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorBoundedConcurrencyTest.java b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorBoundedConcurrencyTest.java index 4590a6dec97..f080ce5e1d5 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorBoundedConcurrencyTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorBoundedConcurrencyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorConcurrencyTest.java b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorConcurrencyTest.java index 3cacc0d67a2..3afe66dd252 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorConcurrencyTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorConcurrencyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorTest.java index bb4b97e68b8..35a877911bb 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/ReplayProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,6 +26,7 @@ import org.mockito.*; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; @@ -46,6 +47,7 @@ protected FlowableProcessor create() { } @Test + @SuppressUndeliverable public void completed() { ReplayProcessor processor = ReplayProcessor.create(); @@ -70,6 +72,7 @@ public void completed() { } @Test + @SuppressUndeliverable public void completedStopsEmittingData() { ReplayProcessor channel = ReplayProcessor.create(); Subscriber observerA = TestHelper.mockSubscriber(); @@ -139,6 +142,7 @@ public void completedStopsEmittingData() { } @Test + @SuppressUndeliverable public void completedAfterError() { ReplayProcessor processor = ReplayProcessor.create(); @@ -169,6 +173,7 @@ private void assertCompletedSubscriber(Subscriber subscriber) { } @Test + @SuppressUndeliverable public void error() { ReplayProcessor processor = ReplayProcessor.create(); @@ -1199,6 +1204,30 @@ public void takeSizeAndTime() { .assertResult(2); } + @Test + public void takeSizeAndTime2() { + TestScheduler scheduler = new TestScheduler(); + + ReplayProcessor rp = ReplayProcessor.createWithTimeAndSize(1, TimeUnit.SECONDS, scheduler, 2); + + rp.onNext(1); + rp.onNext(2); + rp.onNext(3); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + cancel(); + onComplete(); + } + }; + + rp + .subscribeWith(ts) + .assertResult(2); + } + @Test public void takeSize() { ReplayProcessor rp = ReplayProcessor.createWithSize(2); @@ -1213,6 +1242,28 @@ public void takeSize() { .assertResult(2); } + @Test + public void takeSize2() { + ReplayProcessor rp = ReplayProcessor.createWithSize(2); + + rp.onNext(1); + rp.onNext(2); + rp.onNext(3); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + cancel(); + onComplete(); + } + }; + + rp + .subscribeWith(ts) + .assertResult(2); + } + @Test public void reentrantDrain() { TestScheduler scheduler = new TestScheduler(); @@ -1781,4 +1832,69 @@ public void timeAndSizeRemoveCorrectNumberOfOld() { rp.test().assertValuesOnly(4, 5); } -} + + @Test + public void terminationSubscriptionRaceUnbounded() throws Throwable { + for (int i = 1; i <= 10000; i++) { + ReplayProcessor source = ReplayProcessor.create(); + PublishProcessor sink = PublishProcessor.create(); + TestSubscriber subscriber = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(new BooleanSubscription()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + subscriber.await().assertValues("hello", "world").assertComplete(); + } + } + + @Test + public void terminationSubscriptionRaceSizeBound() throws Throwable { + for (int i = 1; i <= 10000; i++) { + ReplayProcessor source = ReplayProcessor.createWithSize(20); + PublishProcessor sink = PublishProcessor.create(); + TestSubscriber subscriber = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(new BooleanSubscription()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + subscriber.await().assertValues("hello", "world").assertComplete(); + } + } + + @Test + public void terminationSubscriptionRaceTimeBound() throws Throwable { + for (int i = 1; i <= 10000; i++) { + ReplayProcessor source = ReplayProcessor.createWithTime(20, TimeUnit.MINUTES, Schedulers.computation()); + PublishProcessor sink = PublishProcessor.create(); + TestSubscriber subscriber = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(new BooleanSubscription()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + subscriber.await().assertValues("hello", "world").assertComplete(); + } + }} diff --git a/src/test/java/io/reactivex/rxjava3/processors/SerializedProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/SerializedProcessorTest.java index fc50ade3ef8..515b8d1430b 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/SerializedProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/SerializedProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,6 +20,7 @@ import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; @@ -664,4 +665,27 @@ public void run() { ts.assertEmpty(); } } + + @Test + public void onErrorQueued() { + FlowableProcessor sp = PublishProcessor.create().toSerialized(); + + TestSubscriber ts = new TestSubscriber() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + if (t == 1) { + sp.onNext(2); + sp.onSubscribe(new BooleanSubscription()); + sp.onError(new TestException()); + } + } + }; + + sp.subscribe(ts); + + sp.onNext(1); + + ts.assertFailure(TestException.class, 1); // errors skip ahead + } } diff --git a/src/test/java/io/reactivex/rxjava3/processors/UnicastProcessorTest.java b/src/test/java/io/reactivex/rxjava3/processors/UnicastProcessorTest.java index 002d6a17d3f..f65cc46a5ed 100644 --- a/src/test/java/io/reactivex/rxjava3/processors/UnicastProcessorTest.java +++ b/src/test/java/io/reactivex/rxjava3/processors/UnicastProcessorTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,9 +25,9 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subscribers.TestSubscriber; diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerConcurrencyTests.java b/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerConcurrencyTests.java index 399a7653052..ae7d1b24b0b 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerConcurrencyTests.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerConcurrencyTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerTests.java b/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerTests.java index 34d8ac1b39c..2419fe557cc 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerTests.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -27,6 +27,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.disposables.SequentialDisposable; @@ -771,4 +772,51 @@ public void schedulePeriodicallyDirectNullRunnable() { assertEquals("run is null", npe.getMessage()); } } + + void schedulePrint(Function onSchedule) { + CountDownLatch waitForBody = new CountDownLatch(1); + CountDownLatch waitForPrint = new CountDownLatch(1); + + try { + Disposable d = onSchedule.apply(() -> { + waitForBody.countDown(); + try { + waitForPrint.await(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + }); + + waitForBody.await(); + + assertNotEquals("", d.toString()); + } catch (Throwable ex) { + throw new AssertionError(ex); + } finally { + waitForPrint.countDown(); + } + } + + @Test + public void scheduleDirectPrint() { + if (getScheduler() instanceof TrampolineScheduler) { + // no concurrency with Trampoline + return; + } + schedulePrint(r -> getScheduler().scheduleDirect(r)); + } + + @Test + public void schedulePrint() { + if (getScheduler() instanceof TrampolineScheduler) { + // no concurrency with Trampoline + return; + } + Worker worker = getScheduler().createWorker(); + try { + schedulePrint(worker::schedule); + } finally { + worker.dispose(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/CachedThreadSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/CachedThreadSchedulerTest.java index 8782142035e..b4576ebb53c 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/CachedThreadSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/CachedThreadSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,6 +24,7 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.schedulers.IoScheduler; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverable; public class CachedThreadSchedulerTest extends AbstractSchedulerConcurrencyTests { @@ -91,6 +92,7 @@ public void workerDisposed() { } @Test + @SuppressUndeliverable public void shutdownRejects() { final int[] calls = { 0 }; diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/ComputationSchedulerTests.java b/src/test/java/io/reactivex/rxjava3/schedulers/ComputationSchedulerTests.java index 0e6248cc890..c88415209d0 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/ComputationSchedulerTests.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/ComputationSchedulerTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,14 +17,17 @@ import java.util.HashMap; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; -import io.reactivex.rxjava3.disposables.Disposable; import org.junit.Test; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Scheduler.Worker; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.schedulers.ComputationScheduler; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverable; public class ComputationSchedulerTests extends AbstractSchedulerConcurrencyTests { @@ -159,6 +162,7 @@ public void cancelledTaskRetention() throws InterruptedException { } @Test + @SuppressUndeliverable public void shutdownRejects() { final int[] calls = { 0 }; @@ -192,4 +196,129 @@ public void run() { assertEquals(0, calls[0]); } + + @Test + public void exceptionFromObservableShouldNotBeSwallowed() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + + // #3 thread's uncaught exception handler + Scheduler computationScheduler = new ComputationScheduler(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setUncaughtExceptionHandler((thread, throwable) -> { + latch.countDown(); + }); + return t; + } + }); + + // #2 RxJava exception handler + RxJavaPlugins.setErrorHandler(h -> { + latch.countDown(); + }); + + // Exceptions, fatal or not, should be handled by + // #1 observer's onError(), or + // #2 RxJava exception handler, or + // #3 thread's uncaught exception handler, + // and should not be swallowed. + try { + + // #1 observer's onError() + Observable.create(s -> { + + s.onNext(1); + throw new OutOfMemoryError(); + }) + .subscribeOn(computationScheduler) + .subscribe(v -> { }, + e -> { latch.countDown(); } + ); + + assertTrue(latch.await(2, TimeUnit.SECONDS)); + } finally { + RxJavaPlugins.reset(); + computationScheduler.shutdown(); + } + } + + @Test + public void exceptionFromObserverShouldNotBeSwallowed() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + + // #3 thread's uncaught exception handler + Scheduler computationScheduler = new ComputationScheduler(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setUncaughtExceptionHandler((thread, throwable) -> { + latch.countDown(); + }); + return t; + } + }); + + // #2 RxJava exception handler + RxJavaPlugins.setErrorHandler(h -> { + latch.countDown(); + }); + + // Exceptions, fatal or not, should be handled by + // #1 observer's onError(), or + // #2 RxJava exception handler, or + // #3 thread's uncaught exception handler, + // and should not be swallowed. + try { + + // #1 observer's onError() + Flowable.interval(500, TimeUnit.MILLISECONDS, computationScheduler) + .subscribe(v -> { + throw new OutOfMemoryError(); + }, e -> { + latch.countDown(); + }); + + assertTrue(latch.await(2, TimeUnit.SECONDS)); + } finally { + RxJavaPlugins.reset(); + computationScheduler.shutdown(); + } + } + + @Test + @SuppressUndeliverable + public void periodicTaskShouldStopOnError() throws Exception { + AtomicInteger repeatCount = new AtomicInteger(); + + Schedulers.computation().schedulePeriodicallyDirect(new Runnable() { + @Override + public void run() { + repeatCount.incrementAndGet(); + throw new OutOfMemoryError(); + } + }, 0, 1, TimeUnit.MILLISECONDS); + + Thread.sleep(200); + + assertEquals(1, repeatCount.get()); + } + + @Test + @SuppressUndeliverable + public void periodicTaskShouldStopOnError2() throws Exception { + AtomicInteger repeatCount = new AtomicInteger(); + + Schedulers.computation().schedulePeriodicallyDirect(new Runnable() { + @Override + public void run() { + repeatCount.incrementAndGet(); + throw new OutOfMemoryError(); + } + }, 0, 1, TimeUnit.NANOSECONDS); + + Thread.sleep(200); + + assertEquals(1, repeatCount.get()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerFairTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerFairTest.java index 128a3bd5b52..c01f0f9f1fe 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerFairTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerFairTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerInterruptibleTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerInterruptibleTest.java index e9c953b049c..074ac8039a7 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerInterruptibleTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerInterruptibleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -505,4 +505,609 @@ public void run() { worker.dispose(); } } + + @Test + public void interruptibleDirectTaskScheduledExecutor() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, true); + + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = scheduler.scheduleDirect(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertTrue("Interruption did not propagate", isInterrupted.get()); + } finally { + exec.shutdown(); + } + } + + @Test + public void interruptibleWorkerTaskScheduledExecutor() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, true); + + Worker worker = scheduler.createWorker(); + + try { + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = worker.schedule(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertTrue("Interruption did not propagate", isInterrupted.get()); + } finally { + worker.dispose(); + } + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleDirectTask() throws Exception { + ExecutorService exec = Executors.newSingleThreadExecutor(); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = scheduler.scheduleDirect(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleWorkerTask() throws Exception { + ExecutorService exec = Executors.newSingleThreadExecutor(); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + Worker worker = scheduler.createWorker(); + + try { + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = worker.schedule(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + worker.dispose(); + } + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleDirectTaskScheduledExecutor() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = scheduler.scheduleDirect(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleWorkerTaskScheduledExecutor() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + Worker worker = scheduler.createWorker(); + + try { + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = worker.schedule(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + worker.dispose(); + } + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleDirectTaskTimed() throws Exception { + ExecutorService exec = Executors.newSingleThreadExecutor(); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = scheduler.scheduleDirect(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }, 1, TimeUnit.MILLISECONDS); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleWorkerTaskTimed() throws Exception { + ExecutorService exec = Executors.newSingleThreadExecutor(); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + Worker worker = scheduler.createWorker(); + + try { + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = worker.schedule(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }, 1, TimeUnit.MILLISECONDS); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + worker.dispose(); + } + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleDirectTaskScheduledExecutorTimed() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = scheduler.scheduleDirect(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }, 1, TimeUnit.MILLISECONDS); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + exec.shutdown(); + } + } + + @Test + public void nonInterruptibleWorkerTaskScheduledExecutorTimed() throws Exception { + ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); + try { + Scheduler scheduler = Schedulers.from(exec, false); + + Worker worker = scheduler.createWorker(); + + try { + final AtomicInteger sync = new AtomicInteger(2); + + final AtomicBoolean isInterrupted = new AtomicBoolean(); + + Disposable d = worker.schedule(new Runnable() { + @Override + public void run() { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + isInterrupted.set(true); + } + } + }, 1, TimeUnit.MILLISECONDS); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + Thread.sleep(500); + + d.dispose(); + + int i = 20; + while (i-- > 0 && !isInterrupted.get()) { + Thread.sleep(50); + } + + assertFalse("Interruption happened", isInterrupted.get()); + } finally { + worker.dispose(); + } + } finally { + exec.shutdown(); + } + } + + public static class TrackInterruptScheduledExecutor extends ScheduledThreadPoolExecutor { + + public final AtomicBoolean interruptReceived = new AtomicBoolean(); + + public TrackInterruptScheduledExecutor() { + super(10); + } + + @Override + public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { + return new TrackingScheduledFuture(super.schedule(callable, delay, unit)); + } + + class TrackingScheduledFuture implements ScheduledFuture { + + ScheduledFuture original; + + TrackingScheduledFuture(ScheduledFuture original) { + this.original = original; + } + + @Override + public long getDelay(TimeUnit unit) { + return original.getDelay(unit); + } + + @Override + public int compareTo(Delayed o) { + return original.compareTo(o); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (mayInterruptIfRunning) { + interruptReceived.set(true); + } + return original.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return original.isCancelled(); + } + + @Override + public boolean isDone() { + return original.isDone(); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + return original.get(); + } + + @Override + public V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return get(timeout, unit); + } + } + } + + @Test + public void noInterruptBeforeRunningDelayedWorker() throws Throwable { + TrackInterruptScheduledExecutor exec = new TrackInterruptScheduledExecutor(); + + try { + Scheduler sch = Schedulers.from(exec, false); + + Worker worker = sch.createWorker(); + + Disposable d = worker.schedule(() -> { }, 1, TimeUnit.SECONDS); + + d.dispose(); + + int i = 150; + + while (i-- > 0) { + assertFalse("Task interrupt detected", exec.interruptReceived.get()); + Thread.sleep(10); + } + + } finally { + exec.shutdownNow(); + } + } + + @Test + public void hasInterruptBeforeRunningDelayedWorker() throws Throwable { + TrackInterruptScheduledExecutor exec = new TrackInterruptScheduledExecutor(); + + try { + Scheduler sch = Schedulers.from(exec, true); + + Worker worker = sch.createWorker(); + + Disposable d = worker.schedule(() -> { }, 1, TimeUnit.SECONDS); + + d.dispose(); + + Thread.sleep(100); + assertTrue("Task interrupt detected", exec.interruptReceived.get()); + + } finally { + exec.shutdownNow(); + } + } + + @Test + public void noInterruptAfterRunningDelayedWorker() throws Throwable { + TrackInterruptScheduledExecutor exec = new TrackInterruptScheduledExecutor(); + + try { + Scheduler sch = Schedulers.from(exec, false); + + Worker worker = sch.createWorker(); + AtomicBoolean taskRun = new AtomicBoolean(); + + Disposable d = worker.schedule(() -> { + taskRun.set(true); + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + exec.interruptReceived.set(true); + } + }, 100, TimeUnit.MILLISECONDS); + + Thread.sleep(150); + ; + d.dispose(); + + int i = 50; + + while (i-- > 0) { + assertFalse("Task interrupt detected", exec.interruptReceived.get()); + Thread.sleep(10); + } + + assertTrue("Task run at all", taskRun.get()); + + } finally { + exec.shutdownNow(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerTest.java index b2e90cdb00c..bb3e759884c 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/ExecutorSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -18,14 +18,14 @@ import java.lang.management.*; import java.util.List; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.*; import org.junit.Test; import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.internal.disposables.EmptyDisposable; +import io.reactivex.rxjava3.internal.disposables.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.internal.schedulers.*; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -93,7 +93,7 @@ public void run() { System.out.println("Wait before second GC"); System.out.println("JDK 6 purge is N log N because it removes and shifts one by one"); - int t = (int)(n * Math.log(n) / 100) + SchedulerPoolFactory.PURGE_PERIOD_SECONDS * 1000; + int t = (int)(n * Math.log(n) / 100) + 1000; int sleepStep = 100; while (t > 0) { System.out.printf(" >> Waiting for purge: %.2f s remaining%n", t / 1000d); @@ -509,4 +509,42 @@ public void run() { assertSame(Functions.EMPTY_RUNNABLE, wrapper.getWrappedRunnable()); } + + @Test + public void interruptibleRunnableRunDisposeRace() { + ExecutorService exec = Executors.newSingleThreadExecutor(); + try { + Scheduler s = Schedulers.from(r -> exec.execute(r), true); + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + SequentialDisposable sd = new SequentialDisposable(); + + TestHelper.race( + () -> sd.update(s.scheduleDirect(() -> { })), + () -> sd.dispose() + ); + } + } finally { + exec.shutdown(); + } + } + + @Test + public void interruptibleRunnableRunDispose() { + try { + for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { + AtomicReference runRef = new AtomicReference<>(); + Scheduler s = Schedulers.from(r -> { + runRef.set(r); + }, true); + + Disposable d = s.scheduleDirect(() -> { }); + TestHelper.race( + () -> runRef.get().run(), + () -> d.dispose() + ); + } + } finally { + Thread.interrupted(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/FailOnBlockingTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/FailOnBlockingTest.java index d8891ddc0c5..7cb4c15e073 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/FailOnBlockingTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/FailOnBlockingTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/NewThreadSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/NewThreadSchedulerTest.java index 352e13333cd..37c7b85f87b 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/NewThreadSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/NewThreadSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -23,6 +23,7 @@ import io.reactivex.rxjava3.core.Scheduler.Worker; import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.internal.schedulers.NewThreadWorker; +import io.reactivex.rxjava3.testsupport.SuppressUndeliverable; public class NewThreadSchedulerTest extends AbstractSchedulerConcurrencyTests { @@ -37,6 +38,7 @@ public final void handledErrorIsNotDeliveredToThreadHandler() throws Interrupted } @Test + @SuppressUndeliverable public void shutdownRejects() { final int[] calls = { 0 }; @@ -75,6 +77,7 @@ public void run() { * @throws Exception on error */ @Test + @SuppressUndeliverable public void npeRegression() throws Exception { Scheduler s = getScheduler(); NewThreadWorker w = (NewThreadWorker) s.createWorker(); diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerLifecycleTest.java index c3784482204..58b51254d8a 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerLifecycleTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerLifecycleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTest.java index fa97b1c0e7f..a9ec2205a7f 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -61,18 +61,28 @@ public void run() { assertEquals(2, count[0]); } - @Test(expected = TestException.class) - public void periodicDirectThrows() { - TestScheduler scheduler = new TestScheduler(); + @Test + public void periodicDirectThrows() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestScheduler scheduler = new TestScheduler(); - scheduler.schedulePeriodicallyDirect(new Runnable() { - @Override - public void run() { - throw new TestException(); + try { + scheduler.schedulePeriodicallyDirect(new Runnable() { + @Override + public void run() { + throw new TestException(); + } + }, 100, 100, TimeUnit.MILLISECONDS); + + scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS); + + fail("Should have thrown!"); + } catch (TestException expected) { + // expected } - }, 100, 100, TimeUnit.MILLISECONDS); - scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS); + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); } @Test @@ -233,7 +243,7 @@ public void run() { Thread.sleep(250); - assertEquals(1, list.size()); + assertTrue(list.size() >= 1); TestHelper.assertUndeliverable(list, 0, TestException.class, null); } finally { diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTestHelper.java b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTestHelper.java index 05dda6a058c..3c899f262ec 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTestHelper.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerTestHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -28,6 +28,8 @@ private SchedulerTestHelper() { /** * Verifies that the given Scheduler does not deliver handled errors to its executing Thread's * {@link java.lang.Thread.UncaughtExceptionHandler}. + * + * @param scheduler {@link Scheduler} to verify. */ static void handledErrorIsNotDeliveredToThreadHandler(Scheduler scheduler) throws InterruptedException { Thread.UncaughtExceptionHandler originalHandler = Thread.getDefaultUncaughtExceptionHandler(); diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerWorkerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerWorkerTest.java index 87ad3698adc..17b7fa5dd76 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerWorkerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/SchedulerWorkerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/TestSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/TestSchedulerTest.java index 8bcb1770532..4c2e776e0d9 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/TestSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/TestSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,6 +30,7 @@ import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; import io.reactivex.rxjava3.internal.util.ExceptionHelper; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.TestScheduler.*; public class TestSchedulerTest extends RxJavaTest { @@ -260,4 +261,95 @@ public void constructorTimeSetsTime() { assertEquals(5, ts.now(TimeUnit.SECONDS)); assertEquals(5000, ts.now(TimeUnit.MILLISECONDS)); } + + @Test + public void withOnScheduleHook() { + AtomicInteger run = new AtomicInteger(); + AtomicInteger counter = new AtomicInteger(); + RxJavaPlugins.setScheduleHandler(r -> { + counter.getAndIncrement(); + return r; + }); + try { + Runnable r = () -> run.getAndIncrement(); + TestScheduler ts = new TestScheduler(true); + + ts.createWorker().schedule(r); + ts.createWorker().schedule(r, 1, TimeUnit.SECONDS); + + ts.advanceTimeBy(1, TimeUnit.SECONDS); + + assertEquals(2, run.get()); + assertEquals(2, counter.get()); + + ts = new TestScheduler(); + + ts.createWorker().schedule(r); + ts.createWorker().schedule(r, 1, TimeUnit.SECONDS); + + ts.advanceTimeBy(1, TimeUnit.SECONDS); + + assertEquals(4, run.get()); + assertEquals(2, counter.get()); + } finally { + RxJavaPlugins.setScheduleHandler(null); + } + } + + @Test + public void withOnScheduleHookInitialTime() { + AtomicInteger run = new AtomicInteger(); + AtomicInteger counter = new AtomicInteger(); + RxJavaPlugins.setScheduleHandler(r -> { + counter.getAndIncrement(); + return r; + }); + try { + Runnable r = () -> run.getAndIncrement(); + TestScheduler ts = new TestScheduler(1, TimeUnit.HOURS, true); + + ts.createWorker().schedule(r); + ts.createWorker().schedule(r, 1, TimeUnit.SECONDS); + + ts.advanceTimeBy(1, TimeUnit.SECONDS); + + assertEquals(2, run.get()); + assertEquals(2, counter.get()); + + ts = new TestScheduler(1, TimeUnit.HOURS); + + ts.createWorker().schedule(r); + ts.createWorker().schedule(r, 1, TimeUnit.SECONDS); + + ts.advanceTimeBy(1, TimeUnit.SECONDS); + + assertEquals(4, run.get()); + assertEquals(2, counter.get()); + } finally { + RxJavaPlugins.setScheduleHandler(null); + } + } + + @Test + public void disposeWork() { + AtomicInteger run = new AtomicInteger(); + Runnable r = () -> run.getAndIncrement(); + TestScheduler ts = new TestScheduler(1, TimeUnit.HOURS, true); + + Disposable d = ts.createWorker().schedule(r); + + assertFalse(d.isDisposed()); + + d.dispose(); + + assertTrue(d.isDisposed()); + + d.dispose(); + + assertTrue(d.isDisposed()); + + ts.advanceTimeBy(1, TimeUnit.SECONDS); + + assertEquals(0, run.get()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java index ce117c2fb79..7d82af675e3 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/TrampolineSchedulerTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/TrampolineSchedulerTest.java index b409aa143af..d98c93a435b 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/TrampolineSchedulerTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/TrampolineSchedulerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleCacheTest.java b/src/test/java/io/reactivex/rxjava3/single/SingleCacheTest.java index 1851c15e1f7..3fe2da558cc 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleCacheTest.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleCacheTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleNullTests.java b/src/test/java/io/reactivex/rxjava3/single/SingleNullTests.java index a6133bd720d..058ecdc6b04 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleNullTests.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleNullTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleRetryTest.java b/src/test/java/io/reactivex/rxjava3/single/SingleRetryTest.java index 2fe5fa9f49a..e38322a4abc 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleRetryTest.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleRetryTest.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2017-present, RxJava Contributors. +/* + * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/single/SingleSubscribeTest.java index 68484d63c1f..df363bee830 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleSubscribeTest.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleSubscribeTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleTest.java b/src/test/java/io/reactivex/rxjava3/single/SingleTest.java index 1f7cba7e2d2..7b51c97471d 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/single/SingleTimerTest.java b/src/test/java/io/reactivex/rxjava3/single/SingleTimerTest.java index c8624b710a9..7fefa15467f 100644 --- a/src/test/java/io/reactivex/rxjava3/single/SingleTimerTest.java +++ b/src/test/java/io/reactivex/rxjava3/single/SingleTimerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/AsyncSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/AsyncSubjectTest.java index 395300e2923..8228b74b5d2 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/AsyncSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/AsyncSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -24,11 +24,11 @@ import org.mockito.*; import io.reactivex.rxjava3.core.Observer; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.testsupport.*; public class AsyncSubjectTest extends SubjectTest { @@ -112,6 +112,7 @@ public void subscribeAfterError() { } @Test + @SuppressUndeliverable public void error() { AsyncSubject subject = AsyncSubject.create(); @@ -418,6 +419,7 @@ public void run() { } @Test + @SuppressUndeliverable public void onErrorCancelRace() { for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) { @@ -475,6 +477,7 @@ public void onNext(Object t) { } @Test + @SuppressUndeliverable public void onErrorCrossCancel() { AsyncSubject p = AsyncSubject.create(); @@ -517,4 +520,9 @@ public void onComplete() { to1.assertResult(); to2.assertEmpty(); } + + @Test + public void dispose() { + TestHelper.checkDisposed(AsyncSubject.create()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/subjects/BehaviorSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/BehaviorSubjectTest.java index 8e472ec4c5f..8871ee8e7ee 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/BehaviorSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/BehaviorSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -833,4 +833,19 @@ public void emittingEmitNext() { assertNotNull(bd.queue); } + + @Test + public void hasObservers() { + BehaviorSubject bs = BehaviorSubject.create(); + + assertFalse(bs.hasObservers()); + + TestObserver to = bs.test(); + + assertTrue(bs.hasObservers()); + + to.dispose(); + + assertFalse(bs.hasObservers()); + } } diff --git a/src/test/java/io/reactivex/rxjava3/subjects/CompletableSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/CompletableSubjectTest.java index 02ac92b064a..6b5a7a6085c 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/CompletableSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/CompletableSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/MaybeSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/MaybeSubjectTest.java index 31742e10a9e..c741f025088 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/MaybeSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/MaybeSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/PublishSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/PublishSubjectTest.java index 7c2c333a2ba..a4b464c5129 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/PublishSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/PublishSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -29,7 +29,7 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.observers.*; -import io.reactivex.rxjava3.testsupport.TestHelper; +import io.reactivex.rxjava3.testsupport.*; public class PublishSubjectTest extends SubjectTest { @@ -39,6 +39,7 @@ protected Subject create() { } @Test + @SuppressUndeliverable public void completed() { PublishSubject subject = PublishSubject.create(); @@ -112,6 +113,7 @@ private void assertCompletedSubscriber(Observer observer) { } @Test + @SuppressUndeliverable public void error() { PublishSubject subject = PublishSubject.create(); @@ -414,6 +416,7 @@ public void onNext(Integer t) { } @Test + @SuppressUndeliverable public void crossCancelOnError() { final TestObserver to1 = new TestObserver<>(); TestObserver to2 = new TestObserver() { diff --git a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectBoundedConcurrencyTest.java b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectBoundedConcurrencyTest.java index 369fcfc59fd..419e5c92a96 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectBoundedConcurrencyTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectBoundedConcurrencyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectConcurrencyTest.java b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectConcurrencyTest.java index 767553dc599..454b56e515e 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectConcurrencyTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectConcurrencyTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectTest.java index eb06a1a0eaa..8417b530819 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/ReplaySubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -44,6 +44,7 @@ protected Subject create() { } @Test + @SuppressUndeliverable public void completed() { ReplaySubject subject = ReplaySubject.create(); @@ -68,6 +69,7 @@ public void completed() { } @Test + @SuppressUndeliverable public void completedStopsEmittingData() { ReplaySubject channel = ReplaySubject.create(); Observer observerA = TestHelper.mockObserver(); @@ -137,6 +139,7 @@ public void completedStopsEmittingData() { } @Test + @SuppressUndeliverable public void completedAfterError() { ReplaySubject subject = ReplaySubject.create(); @@ -167,6 +170,7 @@ private void assertCompletedSubscriber(Observer observer) { } @Test + @SuppressUndeliverable public void error() { ReplaySubject subject = ReplaySubject.create(); @@ -797,6 +801,7 @@ public void getValuesUnbounded() { } + @Test public void createInvalidCapacity() { try { ReplaySubject.create(-99); @@ -1373,4 +1378,70 @@ public void timeAndSizeRemoveCorrectNumberOfOld() { rs.test().assertValuesOnly(4, 5); } + + @Test + public void terminationSubscriptionRaceUnbounded() throws Throwable { + for (int i = 1; i <= 10000; i++) { + Subject source = ReplaySubject.create(); + Subject sink = PublishSubject.create(); + TestObserver observer = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(Disposable.empty()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + observer.await().assertValues("hello", "world").assertComplete(); + } + } + + @Test + public void terminationSubscriptionRaceSizeBound() throws Throwable { + for (int i = 1; i <= 10000; i++) { + Subject source = ReplaySubject.createWithSize(20); + Subject sink = PublishSubject.create(); + TestObserver observer = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(Disposable.empty()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + observer.await().assertValues("hello", "world").assertComplete(); + } + } + + @Test + public void terminationSubscriptionRaceTimeBound() throws Throwable { + for (int i = 1; i <= 10000; i++) { + Subject source = ReplaySubject.createWithTime(20, TimeUnit.MINUTES, Schedulers.computation()); + Subject sink = PublishSubject.create(); + TestObserver observer = sink.test(); + Schedulers.computation().scheduleDirect(() -> { + // issue signals to the source in adherence to the reactive streams specification + source.onSubscribe(Disposable.empty()); + source.onNext("hello"); + source.onNext("world"); + source.onComplete(); + }); + Schedulers.computation().scheduleDirect(() -> { + // connect the source to the sink in parallel with the signals issued to the source + // note the cast() operator, which is here to detect non-String escapees + source.cast(String.class).subscribe(sink); + }); + observer.await().assertValues("hello", "world").assertComplete(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/subjects/SerializedSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/SerializedSubjectTest.java index bf74ac5998b..18ff5033392 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/SerializedSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/SerializedSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -20,9 +20,10 @@ import org.junit.Test; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.RxJavaTest; -import io.reactivex.rxjava3.disposables.*; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -665,4 +666,51 @@ public void run() { to.assertEmpty(); } } + + @Test + public void onErrorQueued() { + Subject sp = PublishSubject.create().toSerialized(); + + TestObserver to = new TestObserver() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + if (t == 1) { + sp.onNext(2); + sp.onNext(3); + sp.onSubscribe(Disposable.empty()); + sp.onError(new TestException()); + } + } + }; + + sp.subscribe(to); + + sp.onNext(1); + + to.assertFailure(TestException.class, 1); // errors skip ahead + } + + @Test + public void onCompleteQueued() { + Subject sp = PublishSubject.create().toSerialized(); + + TestObserver to = new TestObserver() { + @Override + public void onNext(@NonNull Integer t) { + super.onNext(t); + if (t == 1) { + sp.onNext(2); + sp.onNext(3); + sp.onComplete(); + } + } + }; + + sp.subscribe(to); + + sp.onNext(1); + + to.assertResult(1, 2, 3); + } } diff --git a/src/test/java/io/reactivex/rxjava3/subjects/SingleSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/SingleSubjectTest.java index 521fb77fe47..751f0c72d4b 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/SingleSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/SingleSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/SubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/SubjectTest.java index ab22d10a0c0..ce7177a58d4 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/SubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/SubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subjects/UnicastSubjectTest.java b/src/test/java/io/reactivex/rxjava3/subjects/UnicastSubjectTest.java index ac000e4228e..8ae618319b8 100644 --- a/src/test/java/io/reactivex/rxjava3/subjects/UnicastSubjectTest.java +++ b/src/test/java/io/reactivex/rxjava3/subjects/UnicastSubjectTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,8 +26,8 @@ import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.testsupport.*; @@ -481,9 +481,7 @@ public void fusedNoConcurrentCleanDueToCancel() { us.onNext(i); } - to - .awaitDone(5, TimeUnit.SECONDS) - ; + to.awaitDone(10, TimeUnit.SECONDS); if (!errors.isEmpty()) { throw new CompositeException(errors); @@ -495,4 +493,20 @@ public void fusedNoConcurrentCleanDueToCancel() { } } } + + @Test + public void withCapacityHint() { + UnicastSubject us = UnicastSubject.create(16); + + TestObserver to = us.test(); + + for (int i = 0; i < 256; i++) { + us.onNext(i); + } + us.onComplete(); + + to.assertValueCount(256) + .assertComplete() + .assertNoErrors(); + } } diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/DefaultSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/DefaultSubscriberTest.java index 562759247c9..b68a6fe695f 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/DefaultSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/DefaultSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/DisposableSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/DisposableSubscriberTest.java index b58b2314673..6aa5c1ff519 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/DisposableSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/DisposableSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/ResourceSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/ResourceSubscriberTest.java index 5b135a6ed20..6bbc127cda3 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/ResourceSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/ResourceSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/SafeSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/SafeSubscriberTest.java index e2bc1b1bbd5..cd97fa11a32 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/SafeSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/SafeSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -98,6 +98,7 @@ public void onNextAfterOnCompleted() { * Ensure onError can not be called after onComplete. */ @Test + @SuppressUndeliverable public void onErrorAfterOnCompleted() { TestObservable t = new TestObservable(); Flowable st = Flowable.unsafeCreate(t); @@ -364,6 +365,7 @@ public void dispose() { } @Test + @SuppressUndeliverable public void onNextAfterComplete() { TestSubscriber ts = new TestSubscriber<>(); diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/SerializedSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/SerializedSubscriberTest.java index 00c7ae21038..2402762d939 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/SerializedSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/SerializedSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -341,11 +341,11 @@ public void onNext(String t) { * * When using SynchronizedSubscriber we get this output: * - * p1: 18 p2: 68 => should be close to each other unless we have thread starvation + * {@code p1: 18 p2: 68 =>} should be close to each other unless we have thread starvation * * When using SerializedSubscriber we get: * - * p1: 1 p2: 2445261 => should be close to each other unless we have thread starvation + * {@code p1: 1 p2: 2445261 =>} should be close to each other unless we have thread starvation * * This demonstrates how SynchronizedSubscriber balances back and forth better, and blocks emission. * The real issue in this example is the async buffer-bloat, so we need backpressure. @@ -1134,4 +1134,29 @@ public void nullOnNext() { ts.assertFailureAndMessage(NullPointerException.class, ExceptionHelper.nullWarning("onNext called with a null value.")); } + + @Test + @SuppressUndeliverable + public void onErrorQueuedUp() { + AtomicReference> ssRef = new AtomicReference<>(); + TestSubscriberEx ts = new TestSubscriberEx() { + @Override + public void onNext(Integer t) { + super.onNext(t); + ssRef.get().onNext(2); + ssRef.get().onError(new TestException()); + } + }; + + final SerializedSubscriber so = new SerializedSubscriber<>(ts, true); + ssRef.set(so); + + BooleanSubscription bs = new BooleanSubscription(); + + so.onSubscribe(bs); + + so.onNext(1); + + ts.assertFailure(TestException.class, 1, 2); + } } diff --git a/src/test/java/io/reactivex/rxjava3/subscribers/TestSubscriberTest.java b/src/test/java/io/reactivex/rxjava3/subscribers/TestSubscriberTest.java index 6ce4f4ed248..40bdcb95cc0 100644 --- a/src/test/java/io/reactivex/rxjava3/subscribers/TestSubscriberTest.java +++ b/src/test/java/io/reactivex/rxjava3/subscribers/TestSubscriberTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; +import org.junit.function.ThrowingRunnable; import org.mockito.InOrder; import org.reactivestreams.*; @@ -1391,9 +1392,13 @@ public void assertValuePredicateMatch() { }); } + static void assertThrowsWithMessage(String message, Class clazz, ThrowingRunnable run) { + assertEquals(message, assertThrows(clazz, run).getMessage()); + } + @Test public void assertValuePredicateNoMatch() { - assertThrows("Value not present", AssertionError.class, () -> { + assertThrowsWithMessage("Value 1 (class: Integer) at position 0 did not pass the predicate (latch = 0, values = 1, errors = 0, completions = 1)", AssertionError.class, () -> { TestSubscriber ts = new TestSubscriber<>(); Flowable.just(1).subscribe(ts); @@ -1408,7 +1413,7 @@ public void assertValuePredicateNoMatch() { @Test public void assertValuePredicateMatchButMore() { - assertThrows("Value present but other values as well", AssertionError.class, () -> { + assertThrowsWithMessage("The first value passed the predicate but this consumer received more than one value (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { TestSubscriber ts = new TestSubscriber<>(); Flowable.just(1, 2).subscribe(ts); @@ -1423,7 +1428,7 @@ public void assertValuePredicateMatchButMore() { @Test public void assertValueAtPredicateEmpty() { - assertThrows("No values", AssertionError.class, () -> { + assertThrowsWithMessage("No values (latch = 0, values = 0, errors = 0, completions = 1)", AssertionError.class, () -> { TestSubscriber ts = new TestSubscriber<>(); Flowable.empty().subscribe(ts); @@ -1451,7 +1456,7 @@ public void assertValueAtPredicateMatch() { @Test public void assertValueAtPredicateNoMatch() { - assertThrows("Value not present", AssertionError.class, () -> { + assertThrowsWithMessage("Value 3 (class: Integer) at position 2 did not pass the predicate (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { TestSubscriber ts = new TestSubscriber<>(); Flowable.just(1, 2, 3).subscribe(ts); @@ -1466,7 +1471,7 @@ public void assertValueAtPredicateNoMatch() { @Test public void assertValueAtInvalidIndex() { - assertThrows("Invalid index: 2 (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + assertThrowsWithMessage("Index 2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { TestSubscriber ts = new TestSubscriber<>(); Flowable.just(1, 2).subscribe(ts); @@ -1479,6 +1484,43 @@ public void assertValueAtInvalidIndex() { }); } + @Test + public void assertValueAtIndexInvalidIndex() { + assertThrowsWithMessage("Index 2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1, 2).subscribe(ts); + + ts.assertValueAt(2, 3); + }); + } + + @Test + public void assertValueAtIndexInvalidIndexNegative() { + assertThrowsWithMessage("Index -2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1, 2).subscribe(ts); + + ts.assertValueAt(-2, 3); + }); + } + + @Test + public void assertValueAtInvalidIndexNegative() { + assertThrowsWithMessage("Index -2 is out of range [0, 2) (latch = 0, values = 2, errors = 0, completions = 1)", AssertionError.class, () -> { + TestSubscriber ts = new TestSubscriber<>(); + + Flowable.just(1, 2).subscribe(ts); + + ts.assertValueAt(-2, new Predicate() { + @Override public boolean test(final Integer o) throws Exception { + return o == 1; + } + }); + }); + } + @Test public void requestMore() { Flowable.range(1, 5) @@ -1661,4 +1703,40 @@ public void assertValuesOnlyThrowsWhenErrored() { // expected } } + + @Test + public void onErrorIsNull() { + TestSubscriber ts = TestSubscriber.create(); + ts.onSubscribe(new BooleanSubscription()); + + ts.onError(null); + + ts.assertFailure(NullPointerException.class); + } + + static final class TestSubscriberImpl extends TestSubscriber { + public boolean isTimeout() { + return timeout; + } + } + + @Test + public void awaitCountTimeout() { + TestSubscriberImpl ts = new TestSubscriberImpl<>(); + ts.onSubscribe(new BooleanSubscription()); + ts.awaitCount(1); + assertTrue(ts.isTimeout()); + } + + @Test(expected = RuntimeException.class) + public void awaitCountInterrupted() { + try { + TestSubscriber ts = TestSubscriber.create(); + ts.onSubscribe(new BooleanSubscription()); + Thread.currentThread().interrupt(); + ts.awaitCount(1); + } finally { + Thread.interrupted(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/tck/AllTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/AllTckTest.java index 5d2ce5eed98..4b8060fba92 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/AllTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/AllTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/AmbArrayTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/AmbArrayTckTest.java index 88b24a00abf..1260dd2d582 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/AmbArrayTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/AmbArrayTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/AmbTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/AmbTckTest.java index a0d4a637644..6c687b7461b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/AmbTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/AmbTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/AnyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/AnyTckTest.java index 5d93dd54625..34e9fe55178 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/AnyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/AnyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/AsyncProcessorAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/AsyncProcessorAsPublisherTckTest.java index 87dd4afb336..87a75f00529 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/AsyncProcessorAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/AsyncProcessorAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/BaseTck.java b/src/test/java/io/reactivex/rxjava3/tck/BaseTck.java index 82c25e95919..aa42bcc03a0 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/BaseTck.java +++ b/src/test/java/io/reactivex/rxjava3/tck/BaseTck.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -51,7 +51,7 @@ public long maxElementsFromPublisher() { /** * Creates an Iterable with the specified number of elements or an infinite one if - * elements > {@link Integer#MAX_VALUE}. + * {@code elements >} {@link Integer#MAX_VALUE}. * @param elements the number of elements to return, {@link Integer#MAX_VALUE} means an infinite sequence * @return the Iterable */ diff --git a/src/test/java/io/reactivex/rxjava3/tck/BehaviorProcessorAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/BehaviorProcessorAsPublisherTckTest.java index 219a8ab1a25..94c5e15c140 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/BehaviorProcessorAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/BehaviorProcessorAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/BufferBoundaryTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/BufferBoundaryTckTest.java index 18a6fe4a21e..cf79b210d6b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/BufferBoundaryTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/BufferBoundaryTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/BufferExactSizeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/BufferExactSizeTckTest.java index 5af053e052c..d4b7a7abf57 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/BufferExactSizeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/BufferExactSizeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CacheTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CacheTckTest.java index 460fb80e70e..ec9c481fdc0 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CacheTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CacheTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CollectTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CollectTckTest.java index fe09c2f061d..76c359f3273 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CollectTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CollectTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayDelayErrorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayDelayErrorTckTest.java index ec7005ea417..80bccac2733 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayDelayErrorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayDelayErrorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayTckTest.java index 2cebfe655b0..c5a040dc255 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestArrayTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableDelayErrorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableDelayErrorTckTest.java index 5581b9551ee..41883ab6c1b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableDelayErrorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableDelayErrorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableTckTest.java index 744d9099492..a7b9279a569 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CombineLatestIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CompletableAndThenPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CompletableAndThenPublisherTckTest.java index 9e9eae893d3..22c1d4ceef3 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CompletableAndThenPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CompletableAndThenPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatArrayEagerTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatArrayEagerTckTest.java index 9885f3b939e..25afb450605 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatArrayEagerTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatArrayEagerTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatIterableEagerTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatIterableEagerTckTest.java index e3654184499..491f211cc20 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatIterableEagerTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatIterableEagerTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapIterableTckTest.java index 43dcb2cf20c..1a5ab461930 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapMaybeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapMaybeTckTest.java index f01d8ec5115..5216b6a50f1 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapMaybeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapMaybeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapSingleTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapSingleTckTest.java index 9259f0dcd95..5d41ff67757 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapSingleTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapSingleTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapTckTest.java index 7629d887428..83a3774193b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatMapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatMapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherEagerTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherEagerTckTest.java index 126fe4f01ad..194d7e79de9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherEagerTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherEagerTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherTckTest.java index 4bbfe152f72..ad61abd029d 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatTckTest.java index 1ad7d79412b..c5eb360c731 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithCompletableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithCompletableTckTest.java index a1431efbf8a..a5734952f5e 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithCompletableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithCompletableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeEmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeEmptyTckTest.java index 81611f79e42..e333457b820 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeEmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeEmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeTckTest.java index 08ecaee5ac1..b56ac86eac1 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithMaybeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithSingleTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithSingleTckTest.java index 234ebdf4199..56746e24fc4 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ConcatWithSingleTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ConcatWithSingleTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/CreateTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/CreateTckTest.java index 45a2d86ad79..ff4b0597d84 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/CreateTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/CreateTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DefaultIfEmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DefaultIfEmptyTckTest.java index d8692cfc361..c9d9078bf5c 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DefaultIfEmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DefaultIfEmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DeferTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DeferTckTest.java index cb75dbb2900..f834c1e637b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DeferTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DeferTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DelaySubscriptionTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DelaySubscriptionTckTest.java index 28cc3243d7b..5db6d0b877d 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DelaySubscriptionTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DelaySubscriptionTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DelayTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DelayTckTest.java index d2d4c08de9e..87ccaa37d2c 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DelayTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DelayTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DistinctTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DistinctTckTest.java index 35fe9537200..629d96fee60 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DistinctTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DistinctTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DistinctUntilChangedTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DistinctUntilChangedTckTest.java index 4c08351e462..ba69771a4fd 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DistinctUntilChangedTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DistinctUntilChangedTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DoAfterNextTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DoAfterNextTckTest.java index 1f988ee9f09..3b8fbebecb3 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DoAfterNextTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DoAfterNextTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DoFinallyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DoFinallyTckTest.java index e59dc8ba7dc..029892f4403 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DoFinallyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DoFinallyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/DoOnNextTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/DoOnNextTckTest.java index 418535f8e4e..f7e343803b4 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/DoOnNextTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/DoOnNextTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ElementAtTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ElementAtTckTest.java index 1563beb090e..58e18778d02 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ElementAtTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ElementAtTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/EmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/EmptyTckTest.java index 0b960f51b06..da65d54fe4e 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/EmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/EmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FilterTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FilterTckTest.java index fc3cf46588e..6c975dabfc6 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FilterTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FilterTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FirstTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FirstTckTest.java index 5dac1a42f1e..29082117ddc 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FirstTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FirstTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FlatMapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FlatMapTckTest.java index 39b9afc4540..88e937f282e 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FlatMapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FlatMapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FromArrayTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FromArrayTckTest.java index d8d88a1e68d..84bcb0b70d9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FromArrayTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FromArrayTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FromCallableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FromCallableTckTest.java index e235109619f..d7860609333 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FromCallableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FromCallableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FromFutureTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FromFutureTckTest.java index 7b47ac31925..edff3c277b6 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FromFutureTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FromFutureTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FromIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FromIterableTckTest.java index 0418584039f..94dc77c5557 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FromIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FromIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/FromSupplierTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/FromSupplierTckTest.java index a19028deb82..acbe1df8b02 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/FromSupplierTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/FromSupplierTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/GenerateTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/GenerateTckTest.java index 97cbb4a8113..b5c5ef30f6d 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/GenerateTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/GenerateTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/GroupByTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/GroupByTckTest.java index 7d5f0503da2..ebaedb86ae9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/GroupByTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/GroupByTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/HideTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/HideTckTest.java index 6fa26977c17..62c3e76c4e7 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/HideTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/HideTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/IgnoreElementsTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/IgnoreElementsTckTest.java index 6a1848e88ad..289e2e90eb6 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/IgnoreElementsTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/IgnoreElementsTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/IntervalRangeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/IntervalRangeTckTest.java index 181823e981c..b6c09d3d21a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/IntervalRangeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/IntervalRangeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/IntervalTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/IntervalTckTest.java index 05a25f6774e..b9a01afc32a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/IntervalTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/IntervalTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/IsEmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/IsEmptyTckTest.java index 73cfb285502..a9ffce0294a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/IsEmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/IsEmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/JustTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/JustTckTest.java index 02805e5125d..668b32a31a5 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/JustTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/JustTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/LastTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/LastTckTest.java index facdb09c32d..eb75e0342ab 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/LastTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/LastTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/LimitTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/LimitTckTest.java index 3fe61b627ac..08c526af034 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/LimitTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/LimitTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MapTckTest.java index 6c27b381d2b..9875c412aca 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MaybeFlatMapPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MaybeFlatMapPublisherTckTest.java index 7b582b97c5a..d23521b8abf 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MaybeFlatMapPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MaybeFlatMapPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeIterableTckTest.java index 79d781d8488..38a105e2be9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergePublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergePublisherTckTest.java index 71241d03b15..42baefbf64a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergePublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergePublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeTckTest.java index aaefe13fee4..d0280ca83d5 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeWithCompletableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeWithCompletableTckTest.java index 7345c157da2..e7cd1a2aac2 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeWithCompletableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeWithCompletableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeEmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeEmptyTckTest.java index cb7e919577d..cd8bec50792 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeEmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeEmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeTckTest.java index d064babcdfe..1da618c6097 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeWithMaybeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MergeWithSingleTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MergeWithSingleTckTest.java index cf0c894eae5..09332534185 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MergeWithSingleTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MergeWithSingleTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorAsPublisherTckTest.java index 0c780502124..b4479181d34 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorRefCountedTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorRefCountedTckTest.java index 53b150ef5e8..907d3e3f3fc 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorRefCountedTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorRefCountedTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorTckTest.java index ed6de68012b..ac82f963f7f 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/MulticastProcessorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ObserveOnTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ObserveOnTckTest.java index 4b897c82bef..d6e555be9c9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ObserveOnTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ObserveOnTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/OnBackpressureBufferTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/OnBackpressureBufferTckTest.java index 86839c926f1..58053819aaa 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/OnBackpressureBufferTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/OnBackpressureBufferTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/OnErrorResumeWithTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/OnErrorResumeWithTckTest.java index d70e27bcf25..4d239c9f4d6 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/OnErrorResumeWithTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/OnErrorResumeWithTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/OnErrorReturnItemTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/OnErrorReturnItemTckTest.java index 708fe268296..abd7b28a4fc 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/OnErrorReturnItemTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/OnErrorReturnItemTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/PublishProcessorAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/PublishProcessorAsPublisherTckTest.java index 6154fd4b114..8e596b19958 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/PublishProcessorAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/PublishProcessorAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/PublishSelectorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/PublishSelectorTckTest.java index 85cc6538257..f996fabe36f 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/PublishSelectorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/PublishSelectorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/PublishTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/PublishTckTest.java index 8d436c2a066..b85684d1da1 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/PublishTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/PublishTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/RangeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/RangeTckTest.java index 3cba4e05660..53f3ca180ee 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/RangeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/RangeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/RebatchRequestsTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/RebatchRequestsTckTest.java index cca0025f766..c08682d2373 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/RebatchRequestsTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/RebatchRequestsTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReduceTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReduceTckTest.java index 70253dcafbd..94950214884 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReduceTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReduceTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReduceWithTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReduceWithTckTest.java index ba56f602c7d..9a4f4049821 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReduceWithTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReduceWithTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/RefCountProcessor.java b/src/test/java/io/reactivex/rxjava3/tck/RefCountProcessor.java index c65a0bd58f8..f7c62cf7525 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/RefCountProcessor.java +++ b/src/test/java/io/reactivex/rxjava3/tck/RefCountProcessor.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/RepeatTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/RepeatTckTest.java index 1af7ffa8ff9..32f5832afd3 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/RepeatTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/RepeatTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorSizeBoundAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorSizeBoundAsPublisherTckTest.java index 9608b573585..a32e49c6b97 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorSizeBoundAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorSizeBoundAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorTimeBoundAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorTimeBoundAsPublisherTckTest.java index 41e55297962..f53df02ae6a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorTimeBoundAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorTimeBoundAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorUnboundedAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorUnboundedAsPublisherTckTest.java index 3bc7682284d..6f286d68def 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorUnboundedAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReplayProcessorUnboundedAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReplaySelectorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReplaySelectorTckTest.java index e944e579553..84b1a86d451 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReplaySelectorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReplaySelectorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ReplayTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ReplayTckTest.java index 4380e957467..f62ffb08f36 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ReplayTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ReplayTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/RetryTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/RetryTckTest.java index d2608c2dce7..ba0a0f4b1fd 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/RetryTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/RetryTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ScanTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ScanTckTest.java index 231e9a25907..8a43120c020 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ScanTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ScanTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SequenceEqualTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SequenceEqualTckTest.java index 6c016354031..a4af22ed7eb 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SequenceEqualTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SequenceEqualTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ShareTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ShareTckTest.java index 6e6b57e1b5a..35c9b08e4b9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ShareTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ShareTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SingleFlatMapFlowableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SingleFlatMapFlowableTckTest.java index 653ad462c16..62565e6470a 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SingleFlatMapFlowableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SingleFlatMapFlowableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SingleTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SingleTckTest.java index 10de09fba7d..96af86f6bb8 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SingleTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SingleTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SkipLastTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SkipLastTckTest.java index 9583bbe646d..953986813ff 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SkipLastTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SkipLastTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SkipTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SkipTckTest.java index fcd248374ec..4f299404851 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SkipTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SkipTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SkipUntilTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SkipUntilTckTest.java index 762ca1256bd..976c4983f14 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SkipUntilTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SkipUntilTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SkipWhileTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SkipWhileTckTest.java index b560bb4694c..e4995aedd82 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SkipWhileTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SkipWhileTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SortedTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SortedTckTest.java index c8132593e21..51ff134a9c1 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SortedTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SortedTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SubscribeOnTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SubscribeOnTckTest.java index c38720d6d05..f4303d56053 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SubscribeOnTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SubscribeOnTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SwitchIfEmptyTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SwitchIfEmptyTckTest.java index 9ba97747ff6..eb792e45f08 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SwitchIfEmptyTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SwitchIfEmptyTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SwitchMapDelayErrorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SwitchMapDelayErrorTckTest.java index cb27667aec6..d9086e275d6 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SwitchMapDelayErrorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SwitchMapDelayErrorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SwitchMapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SwitchMapTckTest.java index 1d8ec8f8007..1d41a6d11b8 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SwitchMapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SwitchMapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/SwitchOnNextTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/SwitchOnNextTckTest.java index d275ca67665..196bf4f8259 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/SwitchOnNextTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/SwitchOnNextTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TakeLastTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TakeLastTckTest.java index 594db93c9f6..c737554363e 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TakeLastTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TakeLastTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TakeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TakeTckTest.java index 1b2529c914f..50fe18caf1d 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TakeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TakeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TakeUntilTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TakeUntilTckTest.java index 256c01cc00a..96955606156 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TakeUntilTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TakeUntilTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TakeWhileTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TakeWhileTckTest.java index aa2d32939b2..24f6bd4d0d2 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TakeWhileTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TakeWhileTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TimeIntervalTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TimeIntervalTckTest.java index d0c7cd52f47..3daebf143af 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TimeIntervalTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TimeIntervalTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TimeoutTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TimeoutTckTest.java index 52ad8d01aae..447a60e9512 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TimeoutTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TimeoutTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TimerTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TimerTckTest.java index 5e280bd5201..4a6eb000058 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TimerTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TimerTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/TimestampTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/TimestampTckTest.java index acdef0b9ee5..48d34c87516 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/TimestampTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/TimestampTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ToListTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ToListTckTest.java index 7d7c11bf8ce..e9d17f370f3 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ToListTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ToListTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ToMapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ToMapTckTest.java index 8fe43611894..ae27183ca09 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ToMapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ToMapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ToMultimapTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ToMultimapTckTest.java index 925f147a7ee..c0d65cbd338 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ToMultimapTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ToMultimapTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ToSortedListTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ToSortedListTckTest.java index fed8ec3669f..11d1029fc2b 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ToSortedListTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ToSortedListTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorAsPublisherTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorAsPublisherTckTest.java index 142ffbd4a7b..a888ce35fa0 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorAsPublisherTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorAsPublisherTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorTckTest.java index 079c3492456..44bcc5a1424 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/UnicastProcessorTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/UnsubscribeOnTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/UnsubscribeOnTckTest.java index c3a386f3875..1ab8398b743 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/UnsubscribeOnTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/UnsubscribeOnTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/UsingTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/UsingTckTest.java index 9c0e41f3d96..03460fdabac 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/UsingTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/UsingTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/WindowBoundaryTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/WindowBoundaryTckTest.java index bee09d0eb55..5b01ad696c9 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/WindowBoundaryTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/WindowBoundaryTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/WindowExactSizeTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/WindowExactSizeTckTest.java index 5ee35003792..dae3bf0c45d 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/WindowExactSizeTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/WindowExactSizeTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/WithLatestFromTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/WithLatestFromTckTest.java index 3d91048c37b..ae7cddb7f91 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/WithLatestFromTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/WithLatestFromTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ZipIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ZipIterableTckTest.java index 8ef456e6093..9dae4bcd9a0 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ZipIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ZipIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ZipTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ZipTckTest.java index 4c94e97ed78..c9427876d88 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ZipTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ZipTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ZipWithIterableTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ZipWithIterableTckTest.java index 2d9eae43eab..6a4cde43f51 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ZipWithIterableTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ZipWithIterableTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/tck/ZipWithTckTest.java b/src/test/java/io/reactivex/rxjava3/tck/ZipWithTckTest.java index f71dd6b98de..6992605ad82 100644 --- a/src/test/java/io/reactivex/rxjava3/tck/ZipWithTckTest.java +++ b/src/test/java/io/reactivex/rxjava3/tck/ZipWithTckTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/BaseTestConsumerEx.java b/src/test/java/io/reactivex/rxjava3/testsupport/BaseTestConsumerEx.java index 8eb1d9f9061..47016f1fa52 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/BaseTestConsumerEx.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/BaseTestConsumerEx.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -16,9 +16,10 @@ import java.util.List; import io.reactivex.rxjava3.functions.Predicate; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.util.ExceptionHelper; import io.reactivex.rxjava3.observers.BaseTestConsumer; +import io.reactivex.rxjava3.operators.QueueFuseable; + import java.util.Objects; /** @@ -159,7 +160,8 @@ public final U assertErrorMessage(String message) { Throwable e = errors.get(0); String errorMessage = e.getMessage(); if (!Objects.equals(message, errorMessage)) { - throw fail("Error message differs; exptected: " + message + " but was: " + errorMessage); + throw fail("\nexpected: " + message + "\ngot: " + errorMessage + + "; Error message differs"); } } else { throw fail("Multiple errors"); diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverable.java b/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverable.java new file mode 100644 index 00000000000..4e701137abf --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverable.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.testsupport; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface SuppressUndeliverable { +} diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverableRule.java b/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverableRule.java new file mode 100644 index 00000000000..28f6d2f89ec --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/testsupport/SuppressUndeliverableRule.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.testsupport; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import io.reactivex.rxjava3.exceptions.UndeliverableException; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * A rule for suppressing UndeliverableException handling. + * + *

Test classes that use this rule can suppress UndeliverableException + * handling by annotating the test method with SuppressUndeliverable. + */ +public class SuppressUndeliverableRule implements TestRule { + + static final class SuppressUndeliverableRuleStatement extends Statement { + private Statement base; + + SuppressUndeliverableRuleStatement(Statement base) { + this.base = base; + } + + @Override + public void evaluate() throws Throwable { + try { + RxJavaPlugins.setErrorHandler(throwable -> { + if (!(throwable instanceof UndeliverableException)) { + throwable.printStackTrace(); + Thread currentThread = Thread.currentThread(); + currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, throwable); + } + }); + base.evaluate(); + } finally { + RxJavaPlugins.setErrorHandler(null); + } + } + } + + @Override + public Statement apply(Statement base, Description description) { + if (description != null && description.getAnnotation(SuppressUndeliverable.class) != null) { + return new SuppressUndeliverableRuleStatement(base); + } else { + return base; + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java index bb6608e96dd..d38ad8f9985 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,19 +30,24 @@ import org.mockito.stubbing.Answer; import org.reactivestreams.*; +import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.operators.completable.CompletableToFlowable; import io.reactivex.rxjava3.internal.operators.maybe.MaybeToFlowable; import io.reactivex.rxjava3.internal.operators.single.SingleToFlowable; -import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription; +import io.reactivex.rxjava3.internal.subscriptions.*; import io.reactivex.rxjava3.internal.util.ExceptionHelper; import io.reactivex.rxjava3.observers.BaseTestConsumer; +import io.reactivex.rxjava3.operators.ConditionalSubscriber; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; +import io.reactivex.rxjava3.operators.SimpleQueue; import io.reactivex.rxjava3.parallel.ParallelFlowable; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.processors.PublishProcessor; @@ -356,6 +361,68 @@ public void onComplete() { RxJavaPlugins.setErrorHandler(null); } } + + /** + * Assert that by consuming the Publisher with a bad request amount, it is + * reported to the plugin error handler promptly. + * @param source the source to consume + */ + public static void assertBadRequestReported(ParallelFlowable source) { + List list = trackPluginErrors(); + try { + final CountDownLatch cdl = new CountDownLatch(1); + + FlowableSubscriber bad = new FlowableSubscriber() { + + @Override + public void onSubscribe(Subscription s) { + try { + s.request(-99); + s.cancel(); + s.cancel(); + } finally { + cdl.countDown(); + } + } + + @Override + public void onNext(Object t) { + + } + + @Override + public void onError(Throwable t) { + + } + + @Override + public void onComplete() { + + } + + }; + + @SuppressWarnings("unchecked") + FlowableSubscriber[] subs = new FlowableSubscriber[source.parallelism()]; + subs[0] = bad; + for (int i = 1; i < subs.length; i++) { + subs[i] = NoOpConsumer.INSTANCE; + } + source.subscribe(subs); + + try { + assertTrue(cdl.await(5, TimeUnit.SECONDS)); + } catch (InterruptedException ex) { + throw new AssertionError(ex.getMessage()); + } + + assertTrue(list.toString(), list.get(0) instanceof IllegalArgumentException); + assertEquals("n > 0 required but it was -99", list.get(0).getMessage()); + } finally { + RxJavaPlugins.setErrorHandler(null); + } + } + /** * Synchronizes the execution of two runnables (as much as possible) * to test race conditions. @@ -616,6 +683,18 @@ public static void doubleOnSubscribe(MaybeObserver observer) { } } + public static void checkDisposed(Disposable d) { + assertFalse("Disposed upfront?!", d.isDisposed()); + + d.dispose(); + + assertTrue("Not disposed?!", d.isDisposed()); + + d.dispose(); + + assertTrue("Not disposed again?!", d.isDisposed()); + } + /** * Checks if the upstream's Subscription sent through the onSubscribe reports * isCancelled properly before and after calling dispose. @@ -1485,6 +1564,69 @@ public int parallelism() { RxJavaPlugins.reset(); } } + /** + * Check if the given transformed reactive type reports multiple onSubscribe calls to + * RxJavaPlugins. + * @param the input value type + * @param transform the transform to drive an operator + */ + public static void checkDoubleOnSubscribeParallelToFlowable(Function, ? extends Flowable> transform) { + List errors = trackPluginErrors(); + try { + final Boolean[] b = { null, null, null, null }; + final CountDownLatch cdl = new CountDownLatch(2); + + ParallelFlowable source = new ParallelFlowable() { + @Override + public void subscribe(Subscriber[] subscribers) { + for (int i = 0; i < subscribers.length; i++) { + try { + BooleanSubscription bs1 = new BooleanSubscription(); + + subscribers[i].onSubscribe(bs1); + + BooleanSubscription bs2 = new BooleanSubscription(); + + subscribers[i].onSubscribe(bs2); + + b[i * 2 + 0] = bs1.isCancelled(); + b[i * 2 + 1] = bs2.isCancelled(); + } finally { + cdl.countDown(); + } + } + } + + @Override + public int parallelism() { + return 2; + } + }; + + Flowable out = transform.apply(source); + + out.subscribe(NoOpConsumer.INSTANCE); + + try { + assertTrue("Timed out", cdl.await(5, TimeUnit.SECONDS)); + } catch (InterruptedException ex) { + throw ExceptionHelper.wrapOrThrow(ex); + } + + assertEquals("Rail 1 First disposed?", false, b[0]); + assertEquals("Rail 1 Second not disposed?", true, b[1]); + + assertEquals("Rail 2 First disposed?", false, b[2]); + assertEquals("Rail 2 Second not disposed?", true, b[3]); + + assertError(errors, 0, IllegalStateException.class, "Subscription already set!"); + assertError(errors, 1, IllegalStateException.class, "Subscription already set!"); + } catch (Throwable ex) { + throw ExceptionHelper.wrapOrThrow(ex); + } finally { + RxJavaPlugins.reset(); + } + } /** * Check if the given transformed reactive type reports multiple onSubscribe calls to @@ -2298,23 +2440,16 @@ public static void assertCompositeExceptions(TestSubscriberEx ts, Class ts, Object... classes) { + public static void assertCompositeExceptions(TestSubscriberEx ts, Object... classesAndMessages) { ts .assertSubscribed() .assertError(CompositeException.class) .assertNotComplete(); - List list = compositeList(ts.errors().get(0)); - - assertEquals(classes.length, list.size()); - - for (int i = 0; i < classes.length; i += 2) { - assertError(list, i, (Class)classes[i], (String)classes[i + 1]); - } + assertCompositeExceptionListOf(ts.errors().get(0), classesAndMessages); } /** @@ -2343,22 +2478,26 @@ public static void assertCompositeExceptions(TestObserverEx to, Class to, Object... classes) { + public static void assertCompositeExceptions(TestObserverEx to, Object... classesAndMessages) { to .assertSubscribed() .assertError(CompositeException.class) .assertNotComplete(); - List list = compositeList(to.errors().get(0)); + assertCompositeExceptionListOf(to.errors().get(0), classesAndMessages); + } - assertEquals(classes.length, list.size()); + @SuppressWarnings("unchecked") + static void assertCompositeExceptionListOf(Throwable ex, Object... classesAndMessages) { + List list = compositeList(ex); + + assertEquals(classesAndMessages.length, 2 * list.size()); - for (int i = 0; i < classes.length; i += 2) { - assertError(list, i, (Class)classes[i], (String)classes[i + 1]); + for (int i = 0; i < list.size(); i++) { + assertError(list, i, (Class)classesAndMessages[2 * i], (String)classesAndMessages[2 * i + 1]); } } @@ -2880,6 +3019,12 @@ public static void checkInvalidParallelSubscribers(ParallelFlowable sourc } } + /** + * Creates a fuseable Observable that does not emit anything but rejects + * fusion requests. + * @param the element type + * @return the new Observable + */ public static Observable rejectObservableFusion() { return new Observable() { @Override @@ -2928,6 +3073,12 @@ public boolean isDisposed() { }; } + /** + * Creates a fuseable Flowable that does not emit anything but rejects + * fusion requests. + * @param the element type + * @return the new Observable + */ public static Flowable rejectFlowableFusion() { return new Flowable() { @Override @@ -3365,18 +3516,26 @@ public static File findSource(String baseClassName, String parentPackage) throws parentPackage = parentPackage.replace(".", "/"); // System.out.println(path); - int i = path.toLowerCase().indexOf("/rxjava"); - if (i < 0) { - System.out.println("Can't find the base RxJava directory"); - return null; - } - - // find end of any potential postfix to /RxJava - int j = path.indexOf("/", i + 6); + // Locate the src/main/java directory + String p = null; + while (true) { + int idx = path.lastIndexOf("/"); + if (idx < 0) { + break; + } + path = path.substring(0, idx); + String check = path + "/src/main/java"; - String basePackage = path.substring(0, j + 1) + "src/main/java"; + if (new File(check).exists()) { + p = check + "/" + parentPackage + "/" + baseClassName + ".java"; + break; + } + } - String p = basePackage + "/" + parentPackage + "/" + baseClassName + ".java"; + if (p == null) { + System.err.println("Unable to locate the RxJava sources"); + return null; + } File f = new File(p); @@ -3581,4 +3740,124 @@ public static void assertError(CompletableFuture cf, Class { + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + + run.run(); + + resume.countDown(); + }); + + if (sync.decrementAndGet() != 0) { + while (sync.get() != 0) { } + } + } + + /** + * Inserts a ConditionalSubscriber into the chain to trigger the conditional paths + * without interfering with the requestFusion parts. + * @param the element type + * @return the new FlowableTransformer instance + */ + public static FlowableTransformer conditional() { + return f -> new Flowable() { + @Override + protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> subscriber) { + f.subscribe(new ForwardingConditionalSubscriber<>(subscriber)); + } + }; + } + + /** + * Wraps a Subscriber and exposes it as a fuseable conditional subscriber without interfering with + * requestFusion. + * @param the element type + */ + static final class ForwardingConditionalSubscriber extends BasicQueueSubscription implements ConditionalSubscriber { + + private static final long serialVersionUID = 365317603608134078L; + + final Subscriber downstream; + + Subscription upstream; + + QueueSubscription qs; + + ForwardingConditionalSubscriber(Subscriber downstream) { + this.downstream = downstream; + } + + @SuppressWarnings("unchecked") + @Override + public void onSubscribe(@NonNull Subscription s) { + this.upstream = s; + if (s instanceof QueueSubscription) { + this.qs = (QueueSubscription)s; + } + downstream.onSubscribe(this); + } + + @Override + public void onNext(@NonNull T t) { + downstream.onNext(t); + } + + @Override + public boolean tryOnNext(@NonNull T t) { + downstream.onNext(t); + return true; + } + + @Override + public void onError(Throwable t) { + downstream.onError(t); + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + + @Override + public int requestFusion(int mode) { + return qs != null ? qs.requestFusion(mode) : 0; + } + + @Override + public @Nullable T poll() throws Throwable { + return qs.poll(); + } + + @Override + public boolean isEmpty() { + return qs.isEmpty(); + } + + @Override + public void clear() { + qs.clear(); + } + + @Override + public void request(long n) { + upstream.request(n); + } + + @Override + public void cancel() { + upstream.cancel(); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverEx.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverEx.java index ff7df2d8b3a..f029ce5457c 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverEx.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverEx.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.testsupport; import java.util.concurrent.atomic.AtomicReference; @@ -17,7 +18,8 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.fuseable.*; +import io.reactivex.rxjava3.operators.QueueDisposable; +import io.reactivex.rxjava3.operators.QueueFuseable; /** * An extended test Observer that records events and allows making assertions about them. @@ -252,8 +254,8 @@ public final TestObserverEx assertFusionMode(int mode) { int m = establishedFusionMode; if (m != mode) { if (qd != null) { - throw new AssertionError("Fusion mode different. Expected: " + fusionModeToString(mode) - + ", actual: " + fusionModeToString(m)); + throw new AssertionError("\nexpected: " + fusionModeToString(mode) + + "\ngot: " + fusionModeToString(m) + "; Fusion mode different"); } else { throw fail("Upstream is not fuseable"); } diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverExTest.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverExTest.java index 6026501a1d1..2296ceb7576 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverExTest.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestObserverExTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,9 +30,9 @@ import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.operators.observable.ObservableScalarXMap.ScalarDisposable; import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.*; @@ -1274,7 +1274,7 @@ public void assertValueAtIndexMatch() { @Test public void assertValueAtIndexNoMatch() { - assertThrows("expected: b (class: String) but was: c (class: String) (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { + assertThrows("\nexpected: b (class: String)\ngot: c (class: String) (latch = 0, values = 3, errors = 0, completions = 1)", AssertionError.class, () -> { TestObserverEx to = new TestObserverEx<>(); Observable.just("a", "b", "c").subscribe(to); diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberEx.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberEx.java index 43d4087c3e8..c3d9837c2b2 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberEx.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberEx.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -10,6 +10,7 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ + package io.reactivex.rxjava3.testsupport; import java.util.concurrent.atomic.*; @@ -17,8 +18,9 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.core.FlowableSubscriber; -import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; +import io.reactivex.rxjava3.operators.QueueFuseable; +import io.reactivex.rxjava3.operators.QueueSubscription; /** * An extended test subscriber that records events and allows making assertions about them. @@ -315,8 +317,8 @@ public final TestSubscriberEx assertFusionMode(int mode) { int m = establishedFusionMode; if (m != mode) { if (qs != null) { - throw new AssertionError("Fusion mode different. Expected: " + fusionModeToString(mode) - + ", actual: " + fusionModeToString(m)); + throw new AssertionError("\nexpected: " + fusionModeToString(mode) + + "\ngot: " + fusionModeToString(m) + "; Fusion mode different"); } else { throw fail("Upstream is not fuseable"); } diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberExTest.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberExTest.java index 0918c08e119..f3d19f9cc79 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberExTest.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestSubscriberExTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -30,8 +30,8 @@ import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; import io.reactivex.rxjava3.internal.subscriptions.*; +import io.reactivex.rxjava3.operators.QueueFuseable; import io.reactivex.rxjava3.processors.*; import io.reactivex.rxjava3.schedulers.Schedulers; diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TimesteppingScheduler.java b/src/test/java/io/reactivex/rxjava3/testsupport/TimesteppingScheduler.java index 2615a3fbe5d..06804fa2823 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TimesteppingScheduler.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TimesteppingScheduler.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/BaseTypeAnnotations.java b/src/test/java/io/reactivex/rxjava3/validators/BaseTypeAnnotations.java index 504232be2eb..582df0fa712 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/BaseTypeAnnotations.java +++ b/src/test/java/io/reactivex/rxjava3/validators/BaseTypeAnnotations.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -22,6 +22,7 @@ import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.DisposableContainer; import io.reactivex.rxjava3.flowables.ConnectableFlowable; import io.reactivex.rxjava3.observables.ConnectableObservable; import io.reactivex.rxjava3.parallel.ParallelFlowable; @@ -44,7 +45,8 @@ static void checkCheckReturnValueSupport(Class clazz) { for (Method m : clazz.getMethods()) { if (m.getDeclaringClass() == clazz) { - boolean isSubscribeMethod = "subscribe".equals(m.getName()) && m.getParameterTypes().length == 0; + boolean isSubscribeMethod = "subscribe".equals(m.getName()) && + (m.getParameterTypes().length == 0 || m.getParameterTypes()[m.getParameterCount() - 1] == DisposableContainer.class); boolean isConnectMethod = "connect".equals(m.getName()) && m.getParameterTypes().length == 0; boolean isAnnotationPresent = m.isAnnotationPresent(CheckReturnValue.class); diff --git a/src/test/java/io/reactivex/rxjava3/validators/BaseTypeParser.java b/src/test/java/io/reactivex/rxjava3/validators/BaseTypeParser.java index 39704aba146..528ee6de97e 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/BaseTypeParser.java +++ b/src/test/java/io/reactivex/rxjava3/validators/BaseTypeParser.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/CatchThrowIfFatalCheck.java b/src/test/java/io/reactivex/rxjava3/validators/CatchThrowIfFatalCheck.java index 5b78a2da0a5..45594fe17ba 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/CatchThrowIfFatalCheck.java +++ b/src/test/java/io/reactivex/rxjava3/validators/CatchThrowIfFatalCheck.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/CheckLocalVariablesInTests.java b/src/test/java/io/reactivex/rxjava3/validators/CheckLocalVariablesInTests.java index df6f0a378a7..0ec5952f8b4 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/CheckLocalVariablesInTests.java +++ b/src/test/java/io/reactivex/rxjava3/validators/CheckLocalVariablesInTests.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/FixLicenseHeaders.java b/src/test/java/io/reactivex/rxjava3/validators/FixLicenseHeaders.java index c5e601d017f..5d7223cbd1a 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/FixLicenseHeaders.java +++ b/src/test/java/io/reactivex/rxjava3/validators/FixLicenseHeaders.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ public class FixLicenseHeaders { String[] header = { - "/**", + "/*", " * Copyright (c) 2016-present, RxJava Contributors.", " *", " * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in", @@ -88,7 +88,7 @@ public void checkAndUpdateLicenses() throws Exception { in.close(); } - if (!lines.get(0).equals(header[0]) && !lines.get(1).equals(header[1])) { + if (!lines.get(0).equals(header[0]) || !lines.get(1).equals(header[1])) { fail.append("java.lang.RuntimeException: missing header added, refresh and re-run tests!\r\n") .append(" at ") ; diff --git a/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java b/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java index a1ad772f05f..bbf86c4188e 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/JavadocCodesAndLinks.java b/src/test/java/io/reactivex/rxjava3/validators/JavadocCodesAndLinks.java index 55cecb6097f..698fdf7e831 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/JavadocCodesAndLinks.java +++ b/src/test/java/io/reactivex/rxjava3/validators/JavadocCodesAndLinks.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -65,6 +65,21 @@ public void checkCompositeDisposable() throws Exception { checkSource("CompositeDisposable", "io.reactivex.rxjava3.disposables"); } + @Test + public void checkConnectableFlowable() throws Exception { + checkSource("ConnectableFlowable", "io.reactivex.rxjava3.flowables"); + } + + @Test + public void checkConnectableObservable() throws Exception { + checkSource("ConnectableObservable", "io.reactivex.rxjava3.observables"); + } + + @Test + public void checkSchedulers() throws Exception { + checkSource("Schedulers", "io.reactivex.rxjava3.schedulers"); + } + static void checkSource(String baseClassName, String packageName) throws Exception { File f = TestHelper.findSource(baseClassName, packageName); if (f == null) { @@ -408,7 +423,9 @@ static void blankRange(StringBuilder builder, int start, int end) { "List", "ArrayList", "HashMap", "HashSet", "CharSequence", - "TestSubscriber", "TestObserver", "Class" + "TestSubscriber", "TestObserver", "Class", + + "ThreadFactory", "Runnable", "Executor", "ExecutorService", "Executors", "RejectedExecutionException" ); static final Set ALWAYS_CODE = new HashSet<>(Arrays.asList( diff --git a/src/test/java/io/reactivex/rxjava3/validators/JavadocFindUnescapedAngleBrackets.java b/src/test/java/io/reactivex/rxjava3/validators/JavadocFindUnescapedAngleBrackets.java index 083da2902cc..016e1b02a2c 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/JavadocFindUnescapedAngleBrackets.java +++ b/src/test/java/io/reactivex/rxjava3/validators/JavadocFindUnescapedAngleBrackets.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -12,6 +12,7 @@ */ package io.reactivex.rxjava3.validators; + import java.io.*; import java.util.*; diff --git a/src/test/java/io/reactivex/rxjava3/validators/JavadocForAnnotations.java b/src/test/java/io/reactivex/rxjava3/validators/JavadocForAnnotations.java index 9a63ea2b0d5..1c683783d67 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/JavadocForAnnotations.java +++ b/src/test/java/io/reactivex/rxjava3/validators/JavadocForAnnotations.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -95,7 +95,7 @@ static final void scanFor(StringBuilder sourceCode, String annotation, String in ; int lc = lineNumber(sourceCode, idx); - e.append(" at io.reactivex.").append(baseClassName) + e.append(" at io.reactivex.rxjava3.core.").append(baseClassName) .append(" (").append(baseClassName).append(".java:") .append(lc).append(")").append("\r\n\r\n"); } diff --git a/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java b/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java index e22fdd95212..3ab41589a3e 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java +++ b/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -309,6 +309,7 @@ public void flowableDocRefersToFlowableTypes() throws Exception { && !m.signature.contains("Maybe") && !m.signature.contains("MaybeSource") && !m.signature.contains("Disposable") + && !m.signature.contains("void subscribe") ) { CharSequence subSequence = m.javadoc.subSequence(idx - 6, idx + 11); if (idx < 6 || !subSequence.equals("{@link Disposable")) { diff --git a/src/test/java/io/reactivex/rxjava3/validators/MaybeNo2Dot0Since.java b/src/test/java/io/reactivex/rxjava3/validators/MaybeNo2Dot0Since.java index f8b9e63164c..b8944928940 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/MaybeNo2Dot0Since.java +++ b/src/test/java/io/reactivex/rxjava3/validators/MaybeNo2Dot0Since.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/NewLinesBeforeAnnotation.java b/src/test/java/io/reactivex/rxjava3/validators/NewLinesBeforeAnnotation.java index 36a0297a43a..2c27fc6fd45 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/NewLinesBeforeAnnotation.java +++ b/src/test/java/io/reactivex/rxjava3/validators/NewLinesBeforeAnnotation.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/NoAnonymousInnerClassesTest.java b/src/test/java/io/reactivex/rxjava3/validators/NoAnonymousInnerClassesTest.java index 47e5d1dfd69..61db410b5b9 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/NoAnonymousInnerClassesTest.java +++ b/src/test/java/io/reactivex/rxjava3/validators/NoAnonymousInnerClassesTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/NonNullMethodTypeArgumentCheck.java b/src/test/java/io/reactivex/rxjava3/validators/NonNullMethodTypeArgumentCheck.java new file mode 100644 index 00000000000..e8c4b81715e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/validators/NonNullMethodTypeArgumentCheck.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.validators; + +import static org.junit.Assert.assertEquals; + +import java.io.*; +import java.nio.file.Files; +import java.util.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.testsupport.TestHelper; + +/** + * Verify static methods and final methods declaring type arguments + * declare {@code @NonNull} for said argument. + * + */ +public class NonNullMethodTypeArgumentCheck { + + static void process(Class clazz) { + + String className = clazz.getSimpleName(); + String parentPackage = clazz.getPackage().getName(); + + StringBuilder result = new StringBuilder(); + int count = 0; + + try { + File f = TestHelper.findSource(className, parentPackage); + + try (BufferedReader in = Files.newBufferedReader(f.toPath())) { + int lineCount = 1; + String line = null; + + while ((line = in.readLine()) != null) { + line = line.trim(); + + if (!line.contains(" to(")) { + if (line.startsWith("public static <") || line.startsWith("public final <")) { + + for (String ta : parseTypeArguments(line)) { + if (!ta.startsWith("@NonNull") && !ta.startsWith("@Nullable")) { + if (!("Maybe".equals(clazz.getSimpleName()) && (line.contains("fromCallable(") || line.contains("fromSupplier(")))) { + result.append("Missing annotation on argument ").append(ta).append("\r\nat ") + .append(parentPackage).append(".").append(className).append(".method(") + .append(className).append(".java:").append(lineCount).append(")\r\n"); + count++; + } + } + } + } + } + lineCount++; + } + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + if (count != 0) { + throw new IllegalArgumentException("Found " + count + " cases\r\n" + result.toString()); + } + } + + static List parseTypeArguments(String line) { + List result = new ArrayList<>(); + int offset = line.indexOf("<"); + int c = 1; + int i = offset + 1; + int j = i; + for (; i < line.length(); i++) { + if (line.charAt(i) == '<') { + c++; + } else + if (line.charAt(i) == '>') { + c--; + if (c == 0) { + break; + } + } else + if (line.charAt(i) == ',' && c == 1) { + result.add(line.substring(j, i).trim()); + j = i + 1; + } + } + result.add(line.substring(j, i).trim()); + return result; + } + + @Test + public void parseTypeArguments() { + assertEquals(new ArrayList<>(Arrays.asList("T")), parseTypeArguments("")); + assertEquals(new ArrayList<>(Arrays.asList("T", "U")), parseTypeArguments("")); + assertEquals(new ArrayList<>(Arrays.asList("T", "Flowable")), parseTypeArguments(">")); + assertEquals(new ArrayList<>(Arrays.asList("T", "Flowable")), parseTypeArguments(">")); + } + + @Test + public void flowable() { + process(Flowable.class); + } + + @Test + public void observable() { + process(Observable.class); + } + + @Test + public void maybe() { + process(Maybe.class); + } + + @Test + public void single() { + process(Single.class); + } + + @Test + public void completable() { + process(Completable.class); + } + + @Test + public void parallel() { + process(ParallelFlowable.class); + } + + @Test + public void plugins() { + process(RxJavaPlugins.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/validators/OperatorsAreFinal.java b/src/test/java/io/reactivex/rxjava3/validators/OperatorsAreFinal.java index 6343a6e02bf..a59e3aefa20 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/OperatorsAreFinal.java +++ b/src/test/java/io/reactivex/rxjava3/validators/OperatorsAreFinal.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java b/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java index e521c15b6e1..76d4a836f9a 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java +++ b/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -17,13 +17,13 @@ import java.lang.reflect.*; import java.util.*; -import java.util.Observable; import java.util.concurrent.Callable; import org.junit.Test; import org.reactivestreams.Publisher; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.parallel.ParallelFlowable; diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java index 7eff55d15e3..c2ca87d4d2d 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observer; -import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; @@ -149,9 +149,11 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // null Action allowed addOverride(new ParamOverride(Flowable.class, 1, ParamMode.ANY, "onBackpressureBuffer", Long.TYPE, Action.class, BackpressureOverflowStrategy.class)); + addOverride(new ParamOverride(Flowable.class, 1, ParamMode.ANY, "onBackpressureBuffer", Long.TYPE, Action.class, BackpressureOverflowStrategy.class, Consumer.class)); // zero repeat is allowed addOverride(new ParamOverride(Flowable.class, 0, ParamMode.NON_NEGATIVE, "repeat", Long.TYPE)); @@ -177,6 +179,7 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "take", Long.TYPE, TimeUnit.class)); @@ -190,6 +193,7 @@ public void checkParallelFlowable() { addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Boolean.TYPE)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "takeLast", Long.TYPE, TimeUnit.class)); @@ -220,16 +224,19 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Boolean.TYPE)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); + addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE, Consumer.class)); // negative buffer time is considered as zero buffer time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "window", Long.TYPE, TimeUnit.class)); @@ -396,6 +403,7 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "debounce", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // zero repeat is allowed addOverride(new ParamOverride(Observable.class, 0, ParamMode.NON_NEGATIVE, "repeat", Long.TYPE)); @@ -421,6 +429,7 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleWithTimeout", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "take", Long.TYPE, TimeUnit.class)); @@ -434,6 +443,7 @@ public void checkParallelFlowable() { addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Boolean.TYPE)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "sample", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "takeLast", Long.TYPE, TimeUnit.class)); @@ -464,16 +474,19 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleFirst", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLast", Long.TYPE, TimeUnit.class, Scheduler.class, Consumer.class)); // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Boolean.TYPE)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); + addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "throttleLatest", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE, Consumer.class)); // negative buffer time is considered as zero buffer time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "window", Long.TYPE, TimeUnit.class)); @@ -560,6 +573,7 @@ public void checkParallelFlowable() { for (Class interfaces : AllFunctionals.class.getInterfaces()) { defaultValues.put(interfaces, af); } + defaultValues.put(Subscriber.class, af); defaultValues.put(TimeUnit.class, TimeUnit.SECONDS); defaultValues.put(Scheduler.class, Schedulers.single()); defaultValues.put(BackpressureStrategy.class, BackpressureStrategy.MISSING); @@ -580,6 +594,8 @@ public void checkParallelFlowable() { defaultValues.put(ParallelFailureHandling.class, ParallelFailureHandling.ERROR); + defaultValues.put(DisposableContainer.class, new CompositeDisposable()); + // JDK 8 types defaultValues.put(Optional.class, Optional.of(1)); @@ -924,7 +940,7 @@ static final class AllFunctionals Function3, Function4, Function5, Function6, Function7, Function8, Function9, FlowableOnSubscribe, ObservableOnSubscribe, SingleOnSubscribe, MaybeOnSubscribe, CompletableOnSubscribe, FlowableTransformer, ObservableTransformer, SingleTransformer, MaybeTransformer, CompletableTransformer, - Subscriber, FlowableSubscriber, Observer, SingleObserver, MaybeObserver, CompletableObserver, + FlowableSubscriber, Observer, SingleObserver, MaybeObserver, CompletableObserver, FlowableOperator, ObservableOperator, SingleOperator, MaybeOperator, CompletableOperator, Comparator, ParallelTransformer { @@ -1209,4 +1225,4 @@ public String toString() { return "NeverCompletable"; } } -} +} \ No newline at end of file diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java index 0445bfbe713..1928fbee60b 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParameterNamesInClassesTest.java b/src/test/java/io/reactivex/rxjava3/validators/ParameterNamesInClassesTest.java index 11e376a6538..2284e32f6ab 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParameterNamesInClassesTest.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParameterNamesInClassesTest.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/PublicFinalMethods.java b/src/test/java/io/reactivex/rxjava3/validators/PublicFinalMethods.java index f7f59d630d0..ad7df44964e 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/PublicFinalMethods.java +++ b/src/test/java/io/reactivex/rxjava3/validators/PublicFinalMethods.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/SourceAnnotationCheck.java b/src/test/java/io/reactivex/rxjava3/validators/SourceAnnotationCheck.java index ed1080023fd..dfa4aea548b 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/SourceAnnotationCheck.java +++ b/src/test/java/io/reactivex/rxjava3/validators/SourceAnnotationCheck.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in @@ -385,7 +385,9 @@ else if (skippingDepth == 0) { for (String typeName : TYPES_REQUIRING_NONNULL_TYPEARG) { String pattern = typeName + ".*"; + if (line.contains(pattern) && !line.matches(patternRegex)) { + errorCount++; errors.append("L") .append(j) @@ -402,6 +404,45 @@ else if (skippingDepth == 0) { ; } } + for (String typeName : TYPES_FORBIDDEN_NONNULL_TYPEARG) { + String patternRegex = ".*" + typeName + "\\<@NonNull (\\? (extends|super) )?" + COMMON_TYPE_ARG_NAMES + "\\>.*"; + + if (line.matches(patternRegex)) { + errorCount++; + errors.append("L") + .append(j) + .append(" : @NonNull type argument should be on the arg declaration ") + .append(typeName) + .append("\r\n") + .append(" at ") + .append(fullClassName) + .append(".method(") + .append(f.getName()) + .append(":") + .append(j + 1) + .append(")\r\n") + ; + } + } + + for (String typeName : TYPES_REQUIRING_NONNULL_TYPEARG_ON_FUNC) { + if (line.matches(".*Function[\\d]?\\<.*, (\\? (extends|super) )?" + typeName + ".*")) { + errorCount++; + errors.append("L") + .append(j) + .append(" : Missing @NonNull type argument annotation on Function argument ") + .append(typeName) + .append("\r\n") + .append(" at ") + .append(fullClassName) + .append(".method(") + .append(f.getName()) + .append(":") + .append(j + 1) + .append(")\r\n") + ; + } + } } if (errorCount != 0) { @@ -445,6 +486,16 @@ else if (skippingDepth == 0) { ); static final List TYPES_REQUIRING_NONNULL_TYPEARG = Arrays.asList( - "Iterable", "Stream", "Publisher", "Subscriber", "Processor" + "Iterable", "Stream", "Publisher", "Processor", "Subscriber", "Optional" ); + static final List TYPES_FORBIDDEN_NONNULL_TYPEARG = Arrays.asList( + "Iterable", "Stream", "Publisher", "Processor", "Subscriber", "Optional" + ); + + static final List TYPES_REQUIRING_NONNULL_TYPEARG_ON_FUNC = Arrays.asList( + "Iterable", "Stream", "Publisher", "Processor", "Subscriber", "Optional", + "Observer", "SingleObserver", "MaybeObserver", "CompletableObserver" + ); + + static final String COMMON_TYPE_ARG_NAMES = "([A-Z][0-9]?|TOpening|TClosing|TLeft|TLeftEnd|TRight|TRightEnd)"; } diff --git a/src/test/java/io/reactivex/rxjava3/validators/TestPrefixInMethodName.java b/src/test/java/io/reactivex/rxjava3/validators/TestPrefixInMethodName.java index 2fb3460a73a..7a75611b10c 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/TestPrefixInMethodName.java +++ b/src/test/java/io/reactivex/rxjava3/validators/TestPrefixInMethodName.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/TextualAorAn.java b/src/test/java/io/reactivex/rxjava3/validators/TextualAorAn.java index 6aff9cc10e1..654b4884b42 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/TextualAorAn.java +++ b/src/test/java/io/reactivex/rxjava3/validators/TextualAorAn.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in diff --git a/src/test/java/io/reactivex/rxjava3/validators/TooManyEmptyNewLines.java b/src/test/java/io/reactivex/rxjava3/validators/TooManyEmptyNewLines.java index 581e78301b6..c79c879337a 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/TooManyEmptyNewLines.java +++ b/src/test/java/io/reactivex/rxjava3/validators/TooManyEmptyNewLines.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in