8000 RxJava/DESIGN.md at 2.x · pedes/RxJava · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":"gradle","path":"gradle","contentType":"directory"},{"name":"src","path":"src","contentType":"directory"},{"name":".gitattributes","path":".gitattributes","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".travis.yml","path":".travis.yml","contentType":"file"},{"name":"CHANGES.md","path":"CHANGES.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"DESIGN.md","path":"DESIGN.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"build.gradle","path":"build.gradle","contentType":"file"},{"name":"checkstyle.xml","path":"checkstyle.xml","contentType":"file"},{"name":"gradle.properties","path":"gradle.properties","contentType":"file"},{"name":"gradlew","path":"gradlew","contentType":"file"},{"name":"gradlew.bat","path":"gradlew.bat","contentType":"file"},{"name":"pmd.xml","path":"pmd.xml","contentType":"file"},{"name":"settings.gradle","path":"settings.gradle","contentType":"file"}],"totalCount":17}},"fileTreeProcessingTime":14.291284,"foldersToFetch":[],"incompleteFileTree":false,"repo":{"id":68570863,"defaultBranch":"1.x","name":"RxJava","ownerLogin":"pedes","currentUserCanPush":false,"isFork":true,"isEmpty":false,"createdAt":"2016-09-19T05:04:40.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/533797?v=4","public":true,"private":false,"isOrgOwned":false},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"2.x","listCacheKey":"v0:1614059500.576631","canEdit":false,"refType":"branch","currentOid":"679cdf61495f1f271046914e9cbc55da0cacde4e"},"path":"DESIGN.md","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/pedes/RxJava/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"DESIGN.md","displayUrl":"https://github.com/pedes/RxJava/blob/2.x/DESIGN.md?raw=true","headerInfo":{"blobSize":"25 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"7d65f88","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fpedes%2FRxJava%2Fblob%2F2.x%2FDESIGN.md","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"RxJava v2 Design","anchor":"rxjava-v2-design","htmlText":"RxJava v2 Design"},{"level":3,"text":"Terminology \u0026 Definitions","anchor":"terminology--definitions","htmlText":"Terminology \u0026amp; Definitions"},{"level":5,"text":"Interactive","anchor":"interactive","htmlText":"Interactive"},{"level":5,"text":"Reactive","anchor":"reactive","htmlText":"Reactive"},{"level":5,"text":"Hot","anchor":"hot","htmlText":"Hot"},{"level":5,"text":"Cold","anchor":"cold","htmlText":"Cold"},{"level":5,"text":"Reactive/Push","anchor":"reactivepush","htmlText":"Reactive/Push"},{"level":5,"text":"Synchronous Interactive/Pull","anchor":"synchronous-interactivepull","htmlText":"Synchronous Interactive/Pull"},{"level":5,"text":"Async Pull (Async Interactive)","anchor":"async-pull-async-interactive","htmlText":"Async Pull (Async Interactive)"},{"level":5,"text":"Flow Control","anchor":"flow-control","htmlText":"Flow Control"},{"level":5,"text":"Eager","anchor":"eager","htmlText":"Eager"},{"level":5,"text":"Lazy","anchor":"lazy","htmlText":"Lazy"},{"level":3,"text":"RxJava \u0026 Related Types","anchor":"rxjava--related-types","htmlText":"RxJava \u0026amp; Related Types"},{"level":5,"text":"Observable","anchor":"observable","htmlText":"Observable"},{"level":5,"text":"Flowable","anchor":"flowable","htmlText":"Flowable"},{"level":5,"text":"Single","anchor":"single","htmlText":"Single"},{"level":5,"text":"Completable","anchor":"completable","htmlText":"Completable"},{"level":5,"text":"Observer","anchor":"observer","htmlText":"Observer"},{"level":5,"text":"Publisher","anchor":"publisher","htmlText":"Publisher"},{"level":5,"text":"Subscriber","anchor":"subscriber","htmlText":"Subscriber"},{"level":5,"text":"Subscription","anchor":"subscription","htmlText":"Subscription"},{"level":5,"text":"Processor","anchor":"processor","htmlText":"Processor"},{"level":5,"text":"Subject","anchor":"subject","htmlText":"Subject"},{"level":5,"text":"Disposable","anchor":"disposable","htmlText":"Disposable"},{"level":5,"text":"Operator","anchor":"operator","htmlText":"Operator"},{"level":3,"text":"Creation","anchor":"creation","htmlText":"Creation"},{"level":3,"text":"Terminal behavior","anchor":"terminal-behavior","htmlText":"Terminal behavior"},{"level":3,"text":"JVM target and source compatibility","anchor":"jvm-target-and-source-compatibility","htmlText":"JVM target and source compatibility"},{"level":3,"text":"Future work","anchor":"future-work","htmlText":"Future work"},{"level":4,"text":"Custom Observable, Single, Completable, or Flowable","anchor":"custom-observable-single-completable-or-flowable","htmlText":"Custom Observable, Single, Completable, or Flowable"},{"level":4,"text":"Fusion","anchor":"fusion","htmlText":"Fusion"},{"level":5,"text":"Macro-fusion","anchor":"macro-fusion","htmlText":"Macro-fusion"},{"level":5,"text":"Micro-fusion","anchor":"micro-fusion","htmlText":"Micro-fusion"},{"level":6,"text":"1) Conditional Subscriber","anchor":"1-conditional-subscriber","htmlText":"1) Conditional Subscriber"},{"level":6,"text":"2) Queue-fusion","anchor":"2-queue-fusion","htmlText":"2) Queue-fusion"}],"lineInfo":{"truncatedLoc":"598","truncatedSloc":"366"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/pedes/RxJava/blob/2.x/DESIGN.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/pedes/RxJava/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/pedes/RxJava/raw/refs/heads/2.x/DESIGN.md","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRxJava v2 Design\u003c/h2\u003e\u003ca id=\"user-content-rxjava-v2-design\" class=\"anchor\" aria-label=\"Permalink: RxJava v2 Design\" href=\"#rxjava-v2-design\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis document explains the terminology, principles, contracts, and other aspects of the design of RxJava v2.\nIts intended audience is the implementers of the library.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTerminology \u0026amp; Definitions\u003c/h3\u003e\u003ca id=\"user-content-terminology--definitions\" class=\"anchor\" aria-label=\"Permalink: Terminology \u0026amp; Definitions\" href=\"#terminology--definitions\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInteractive\u003c/h5\u003e\u003ca id=\"user-content-interactive\" class=\"anchor\" aria-label=\"Permalink: Interactive\" href=\"#interactive\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eProducer obeys consumer-driven flow control.\nConsumer manages capacity by requesting data.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eReactive\u003c/h5\u003e\u003ca id=\"user-content-reactive\" class=\"anchor\" aria-label=\"Permalink: Reactive\" href=\"#reactive\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eProducer is in charge. Consumer has to do whatever it needs to keep up.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHot\u003c/h5\u003e\u003ca id=\"user-content-hot\" class=\"anchor\" aria-label=\"Permalink: Hot\" href=\"#hot\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen used to refer to a data source (such as an \u003ccode\u003eObservable\u003c/code\u003e), it means it does not have side-effects when subscribed to.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor example, an \u003ccode\u003eObservable\u003c/code\u003e of mouse events. Subscribing to that \u003ccode\u003eObservable\u003c/code\u003e does not cause the mouse events, but starts receiving them.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e(Note: Yes, there are \u003cem\u003esome\u003c/em\u003e side-effects of adding a listener, but they are inconsequential as far as the 'hot' usage is concerned).\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCold\u003c/h5\u003e\u003ca id=\"user-content-cold\" class=\"anchor\" aria-label=\"Permalink: Cold\" href=\"#cold\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen used to refer to a data source (such as an \u003ccode\u003eObservable\u003c/code\u003e), it means it has side-effects when subscribed to.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor example, an \u003ccode\u003eObservable\u003c/code\u003e of data from a remote API (such as an RPC call). Each time that \u003ccode\u003eObservable\u003c/code\u003e is subscribed to causes a new network call to occur.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eReactive/Push\u003c/h5\u003e\u003ca id=\"user-content-reactivepush\" class=\"anchor\" aria-label=\"Permalink: Reactive/Push\" href=\"#reactivepush\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eProducer is in charge. Consumer has to do whatever it needs to keep up.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eObservable\u003c/code\u003e (RxJS, Rx.Net, RxJava v1.x without backpressure, RxJava v2)\u003c/li\u003e\n\u003cli\u003eCallbacks (the producer calls the function at its convenience)\u003c/li\u003e\n\u003cli\u003eIRQ, mouse events, IO interrupts\u003c/li\u003e\n\u003cli\u003e2.x \u003ccode\u003eFlowable\u003c/code\u003e (with \u003ccode\u003erequest(n)\u003c/code\u003e credit always granted faster or in larger quantity than producer)\u003c/li\u003e\n\u003cli\u003eReactive Streams \u003ccode\u003ePublisher\u003c/code\u003e (with \u003ccode\u003erequest(n)\u003c/code\u003e credit always granted faster or in larger quantity than producer)\u003c/li\u003e\n\u003cli\u003eJava 9 \u003ccode\u003eFlow.Publisher\u003c/code\u003e (with \u003ccode\u003erequest(n)\u003c/code\u003e credit always granted faster than or in larger quantity producer)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSynchronous Interactive/Pull\u003c/h5\u003e\u003ca id=\"user-content-synchronous-interactivepull\" class=\"anchor\" aria-label=\"Permalink: Synchronous Interactive/Pull\" href=\"#synchronous-interactivepull\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eConsumer is in charge. Producer has to do whatever it needs to keep up.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eIterable\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e2.x/1.x \u003ccode\u003eObservable\u003c/code\u003e (without concurrency, producer and consumer on the same thread)\u003c/li\u003e\n\u003cli\u003e2.x \u003ccode\u003eFlowable\u003c/code\u003e (without concurrency, producer and consumer on the same thread)\u003c/li\u003e\n\u003cli\u003eReactive Streams \u003ccode\u003ePublisher\u003c/code\u003e (without concurrency, producer and consumer on the same thread)\u003c/li\u003e\n\u003cli\u003eJava 9 \u003ccode\u003eFlow.Publisher\u003c/code\u003e (without concurrency, producer and consumer on the same thread)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAsync Pull (Async Interactive)\u003c/h5\u003e\u003ca id=\"user-content-async-pull-async-interactive\" class=\"anchor\" aria-label=\"Permalink: Async Pull (Async Interactive)\" href=\"#async-pull-async-interactive\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eConsumer requests data when it wishes, and the data is then pushed when the producer wishes to.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eFuture\u003c/code\u003e \u0026amp; \u003ccode\u003ePromise\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSingle\u003c/code\u003e (lazy \u003ccode\u003eFuture\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e2.x \u003ccode\u003eFlowable\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eReactive Streams \u003ccode\u003ePublisher\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eJava 9 \u003ccode\u003eFlow.Publisher\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e1.x \u003ccode\u003eObservable\u003c/code\u003e (with backpressure)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAsyncEnumerable\u003c/code\u003e/\u003ccode\u003eAsyncIterable\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThere is an overhead (performance and mental) for achieving this, which is why we also have the 2.x \u003ccode\u003eObservable\u003c/code\u003e without backpressure.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFlow Control\u003c/h5\u003e\u003ca id=\"user-content-flow-control\" class=\"anchor\" aria-label=\"Permalink: Flow Control\" href=\"#flow-control\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFlow control is any mitigation strategies that a consumer applies to reduce the flow of data.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eControlling the production of data, such as with \u003ccode\u003eIterator.next\u003c/code\u003e or \u003ccode\u003eSubscription.request(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003ePreventing the delivery of data, such as buffer, drop, sample/throttle, and debounce.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eEager\u003c/h5\u003e\u003ca id=\"user-content-eager\" class=\"anchor\" aria-label=\"Permalink: Eager\" href=\"#eager\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eContaining object immediately start work when it is created.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eA \u003ccode\u003eFuture\u003c/code\u003e once created has work being performed and represents the eventual value of that work. It can not be deferred once created.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLazy\u003c/h5\u003e\u003ca id=\"user-content-lazy\" class=\"anchor\" aria-label=\"Permalink: Lazy\" href=\"#lazy\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eContaining object does nothing until it is subscribed to or otherwise started.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eObservable.create\u003c/code\u003e does not start any work until \u003ccode\u003eObservable.subscribe\u003c/code\u003e starts the work.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRxJava \u0026amp; Related Types\u003c/h3\u003e\u003ca id=\"user-content-rxjava--related-types\" class=\"anchor\" aria-label=\"Permalink: RxJava \u0026amp; Related Types\" href=\"#rxjava--related-types\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eObservable\u003c/h5\u003e\u003ca id=\"user-content-observable\" class=\"anchor\" aria-label=\"Permalink: Observable\" href=\"#observable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eStream that supports async and synchronous push. It does \u003cem\u003enot\u003c/em\u003e support interactive flow control (\u003ccode\u003erequest(n)\u003c/code\u003e).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eUsable for:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003esync or async\u003c/li\u003e\n\u003cli\u003epush\u003c/li\u003e\n\u003cli\u003e0, 1, many or infinite items\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eFlow control support:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003ebuffering, sampling, throttling, windowing, dropping, etc\u003c/li\u003e\n\u003cli\u003etemporal and count-based strategies\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eType Signature\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"class Observable\u0026lt;T\u0026gt; {\n void subscribe(Observer\u0026lt;T\u0026gt; observer);\n\n interface Observer\u0026lt;T\u0026gt; {\n void onNext(T t);\n void onError(Throwable t);\n void onComplete();\n void onSubscribe(Disposable d);\n }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eObservable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eObserver\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003eobserver\u003c/span\u003e);\n\n \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eObserver\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonNext\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003et\u003c/span\u003e);\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonError\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003et\u003c/span\u003e);\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonComplete\u003c/span\u003e();\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonSubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe rule for using this type signature is:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eonSubscribe onNext* (onError | onComplete)?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFlowable\u003c/h5\u003e\u003ca id=\"user-content-flowable\" class=\"anchor\" aria-label=\"Permalink: Flowable\" href=\"#flowable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eStream that supports async and synchronous push and pull. It supports interactive flow control (\u003ccode\u003erequest(n)\u003c/code\u003e).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eUsable for:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003epull sources\u003c/li\u003e\n\u003cli\u003epush Observables with backpressure strategy (ie. \u003ccode\u003eObservable.toFlowable(onBackpressureStrategy)\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003esync or async\u003c/li\u003e\n\u003cli\u003e0, 1, many or infinite items\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eFlow control support:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003ebuffering, sampling, throttling, windowing, dropping, etc\u003c/li\u003e\n\u003cli\u003etemporal and count-based strategies\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003erequest(n)\u003c/code\u003e consumer demand signal\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003efor pull-based sources, this allows batched \"async pull\"\u003c/li\u003e\n\u003cli\u003efor push-based sources, this allows backpressure signals to conditionally apply strategies (i.e. drop, first, buffer, sample, fail, etc)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eYou get a flowable from:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eConverting a Observable with a backpressure strategy\u003c/li\u003e\n\u003cli\u003eCreate from sync/async OnSubscribe API (which participate in backpressure semantics)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eType Signature\u003c/em\u003e\u003c/p\u003e\n\u003cdiv c 8000 lass=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"class Flowable\u0026lt;T\u0026gt; implements Flow.Publisher\u0026lt;T\u0026gt;, io.reactivestreams.Publisher\u0026lt;T\u0026gt; {\n void subscribe(Subscriber\u0026lt;T\u0026gt; subscriber);\n\n interface Subscription implements Flow.Subscription, io.reactivestreams.Subscription {\n void cancel();\n void request(long n);\n }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlow\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003ePublisher\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt;, \u003cspan class=\"pl-smi\"\u003eio\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003ereactivestreams\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003ePublisher\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003esubscriber\u003c/span\u003e);\n\n \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eSubscription\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eFlow\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eSubscription\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eio\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ereactivestreams\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eSubscription\u003c/span\u003e {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ecancel\u003c/span\u003e();\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003erequest\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003elong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003en\u003c/span\u003e);\n }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eNOTE: To support \u003ccode\u003eFlow.Publisher\u003c/code\u003e in Java 9+ without breaking Java 7+ compatibility, we want to use the \u003ca href=\"http://openjdk.java.net/jeps/238\" rel=\"nofollow\"\u003emulti-release jar file support\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe rule for using this type signature is:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eonSubscribe onNext* (onError | onComplete)?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSingle\u003c/h5\u003e\u003ca id=\"user-content-single\" class=\"anchor\" aria-label=\"Permalink: Single\" href=\"#single\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLazy representation of a single response (lazy equivalent of \u003ccode\u003eFuture\u003c/code\u003e/\u003ccode\u003ePromise\u003c/code\u003e).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eUsable for:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003epull sources\u003c/li\u003e\n\u003cli\u003epush sources being windowed or flow controlled (such as \u003ccode\u003ewindow(1)\u003c/code\u003e or \u003ccode\u003etake(1)\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003esync or async\u003c/li\u003e\n\u003cli\u003e1 item\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eFlow control:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNot applicable (don't subscribe if the single response is not wanted)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eType Signature\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"class Single\u0026lt;T\u0026gt; {\n void subscribe(Single.Subscriber\u0026lt;T\u0026gt; subscriber);\n}\n\ninterface SingleSubscriber\u0026lt;T\u0026gt; {\n void onSuccess(T t);\n void onError(Throwable t);\n void onSubscribe(Disposable d);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSingle\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSingle\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003esubscriber\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSingleSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonSuccess\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003et\u003c/span\u003e);\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonError\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003et\u003c/span\u003e);\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonSubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eonSubscribe (onError | onSuccess)?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCompletable\u003c/h5\u003e\u003ca id=\"user-content-completable\" class=\"anchor\" aria-label=\"Permalink: Completable\" href=\"#completable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLazy representation of a unit of work that can complete or fail\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eSemantic equivalent of \u003ccode\u003eObservable.empty().doOnSubscribe()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eAlternative for scenarios often represented with types such as \u003ccode\u003eSingle\u0026lt;Void\u0026gt;\u003c/code\u003e or \u003ccode\u003eObservable\u0026lt;Void\u0026gt;\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eUsable for:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003esync or async\u003c/li\u003e\n\u003cli\u003e0 items\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eType Signature\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"class Completable {\n void subscribe(Completable.Subscriber subscriber);\n}\n\ninterface CompletableSubscriber {\n void onComplete();\n void onError(Throwable t);\n void onSubscribe(Disposable d);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eCompletable\u003c/span\u003e {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eCompletable\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003esubscriber\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eCompletableSubscriber\u003c/span\u003e {\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonComplete\u003c/span\u003e();\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonError\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003et\u003c/span\u003e);\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eonSubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eonSubscribe (onError | onComplete)?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eObserver\u003c/h5\u003e\u003ca id=\"user-content-observer\" class=\"anchor\" aria-label=\"Permalink: Observer\" href=\"#observer\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eReactive consumer of events (without consumer-driven flow control). Involved in subscription lifecycle to allow unsubscription.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePublisher\u003c/h5\u003e\u003ca id=\"user-content-publisher\" class=\"anchor\" aria-label=\"Permalink: Publisher\" href=\"#publisher\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eInteractive producer of events (with flow control). Implemented by \u003ccode\u003eFlowable\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/README.md#1-publisher-code\"\u003eReactive Streams producer\u003c/a\u003e of data.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSubscriber\u003c/h5\u003e\u003ca id=\"user-content-subscriber\" class=\"anchor\" aria-label=\"Permalink: Subscriber\" href=\"#subscriber\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eInteractive consumer of events (with consumer-driven flow control). Involved in subscription lifecycle to allow unsubscription.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/README.md#2-subscriber-code\"\u003eReactive Streams consumer\u003c/a\u003e of data.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSubscription\u003c/h5\u003e\u003ca id=\"user-content-subscription\" class=\"anchor\" aria-label=\"Permalink: Subscription\" href=\"#subscription\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/README.md#3-subscription-code\"\u003eReactive Streams state\u003c/a\u003e of subscription supporting flow control and cancellation.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eDisposable\u003c/code\u003e is a similar type used for lifecycle management on the \u003ccode\u003eObservable\u003c/code\u003e type without interactive flow control.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eProcessor\u003c/h5\u003e\u003ca id=\"user-content-processor\" class=\"anchor\" aria-label=\"Permalink: Processor\" href=\"#processor\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/README.md#4processor-code\"\u003eReactive Streams operator\u003c/a\u003e for defining behavior between \u003ccode\u003ePublisher\u003c/code\u003e and \u003ccode\u003eSubscriber\u003c/code\u003e. It must obey the contracts of \u003ccode\u003ePublisher\u003c/code\u003e and \u003ccode\u003eSubscriber\u003c/code\u003e, meaning it is sequential, serialized, and must obey \u003ccode\u003erequest(n)\u003c/code\u003e flow control.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSubject\u003c/h5\u003e\u003ca id=\"user-content-subject\" class=\"anchor\" aria-label=\"Permalink: Subject\" href=\"#subject\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA \"hot\", push-based data source that allows a producer to emit events to it and consumers to subscribe to events in a multicast manner. It is \"hot\" because consumers subscribing to it does not cause side-effects, or affect the data flow in any way. It is push-based and reactive because the producer is fully in charge.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eA \u003ccode\u003eSubject\u003c/code\u003e is used to decouple unsubscription. Termination is fully in the control of the producer. \u003ccode\u003eonError\u003c/code\u003e and \u003ccode\u003eonComplete\u003c/code\u003e are still terminal events.\n\u003ccode\u003eSubject\u003c/code\u003es are stateful and retain their terminal state (for replaying to all/future subscribers).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eRelation to Reactive Streams:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eIt can not implement Reactive Streams \u003ccode\u003ePublisher\u003c/code\u003e unless it is created with a default consumer-driven flow control strategy.\u003c/li\u003e\n\u003cli\u003eIt can not implement \u003ccode\u003eProcessor\u003c/code\u003e since a \u003ccode\u003eProcessor\u003c/code\u003e must compose \u003ccode\u003erequest(n)\u003c/code\u003e which can not be done with multicasting or push.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eHere is an approach to converting from a \u003ccode\u003eSubject\u003c/code\u003e to Reactive Streams types by adding a default flow control strategy:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Subject s = PublishSubject.create();\n// convert to Publisher with backpressure strategy\nPublisher p = s.toPublisher(onBackpressureStrategy);\n\n// now the request(n) semantics are handled by default\np.subscribe(subscriber1);\np.subscribe(subscriber2);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eSubject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003ePublishSubject\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ecreate\u003c/span\u003e();\n\u003cspan class=\"pl-c\"\u003e// convert to Publisher with backpressure strategy\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003ePublisher\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ep\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003etoPublisher\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eonBackpressureStrategy\u003c/span\u003e);\n\n\u003cspan class=\"pl-c\"\u003e// now the request(n) semantics are handled by default\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003ep\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003esubscriber1\u003c/span\u003e);\n\u003cspan class=\"pl-s1\"\u003ep\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003esubscriber2\u003c/span\u003e);\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn this example, \u003ccode\u003esubscriber1\u003c/code\u003e and \u003ccode\u003esubscriber2\u003c/code\u003e can consume at different rates, \u003ccode\u003erequest(n)\u003c/code\u003e will propagate to the provided \u003ccode\u003eonBackpressureStrategy\u003c/code\u003e, not the original \u003ccode\u003eSubject\u003c/code\u003e which can't propagate \u003ccode\u003erequest(n)\u003c/code\u003e upstream.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDisposable\u003c/h5\u003e\u003ca id=\"user-content-disposable\" class=\"anchor\" aria-label=\"Permalink: Disposable\" href=\"#disposable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA type representing work or resource that can be cancelled or disposed.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExamples:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eAn \u003ccode\u003eObservable.subscribe\u003c/code\u003e passes a \u003ccode\u003eDisposable\u003c/code\u003e to the \u003ccode\u003eObservable.onSubscribe\u003c/code\u003e to allow the \u003ccode\u003eObserver\u003c/code\u003e to dispose of the subscription.\u003c/li\u003e\n\u003cli\u003eA \u003ccode\u003eScheduler\u003c/code\u003e returns a \u003ccode\u003eDisposable\u003c/code\u003e that you use for disposing of the \u003ccode\u003eScheduler\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eSubscription\u003c/code\u003e is a similar type used for lifecycle management on the \u003ccode\u003eFlowable\u003c/code\u003e type with interactive flow control.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eOperator\u003c/h5\u003e\u003ca id=\"user-content-operator\" class=\"anchor\" aria-label=\"Permalink: Operator\" href=\"#operator\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAn operator follows a specific lifecycle (union of the producer/consumer contract).\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eIt must propagate the \u003ccode\u003esubscribe\u003c/code\u003e event upstream (to the producer).\u003c/li\u003e\n\u003cli\u003eIt must obey the RxJava contract (serialize all events, \u003ccode\u003eonError\u003c/code\u003e/\u003ccode\u003eonComplete\u003c/code\u003e are terminal).\u003c/li\u003e\n\u003cli\u003eIf it has resources to cleanup it is responsible for watching \u003ccode\u003eonError\u003c/code\u003e, \u003ccode\u003eonComplete\u003c/code\u003e, and \u003ccode\u003ecancel/dispose\u003c/code\u003e, and doing the necessary cleanup.\u003c/li\u003e\n\u003cli\u003eIt must propagate the \u003ccode\u003ecancel/dispose\u003c/code\u003e upstream.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eIn the addition of the previous rules, an operator for \u003ccode\u003eFlowable\u003c/code\u003e:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eIt must propagate/negotiate the \u003ccode\u003erequest(n)\u003c/code\u003e event.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCreation\u003c/h3\u003e\u003ca id=\"user-content-creation\" class=\"anchor\" aria-label=\"Permalink: Creation\" href=\"#creation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eUnlike RxJava 1.x, 2.x base classes are to be abstract, stateless and generally no longer wrap an \u003ccode\u003eOnSubscribe\u003c/code\u003e callback - this saves allocation in assembly time without limiting the expressiveness. Operator methods and standard factories still live as final on the base classes.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eInstead of the indirection of an \u003ccode\u003eOnSubscribe\u003c/code\u003e and \u003ccode\u003elift\u003c/code\u003e, operators are to be implemented by extending the base classes. For example, the \u003ccode\u003emap\u003c/code\u003e\noperator will look like this:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public final class FlowableMap\u0026lt;T, R\u0026gt; extends Flowable\u0026lt;R\u0026gt; {\n \n final Flowable\u0026lt;? extends T\u0026gt; source;\n \n final Function\u0026lt;? super T, ? extends R\u0026gt; mapper;\n \n public FlowableMap(Flowable\u0026lt;? extends T\u0026gt; source, Function\u0026lt;? super T, ? extends R\u0026gt; mapper) {\n this.source = source;\n this.mapper = mapper;\n }\n \n @Override\n protected void subscribeActual(Subscriber\u0026lt;? super R\u0026gt; subscriber) {\n source.subscribe(new FlowableMapSubscriber\u0026lt;T, R\u0026gt;(subscriber, mapper));\n }\n \n static final class FlowableMapSubscriber\u0026lt;T, R\u0026gt; implements Subscriber\u0026lt;T\u0026gt;, Subscription {\n // ...\n }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowableMap\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; {\n \n \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowable\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e;\n \n \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFunction\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, ? \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e;\n \n \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowableMap\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eFlowable\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eFunction\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, ? \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e) {\n \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e;\n \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e;\n }\n \n \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n \u003cspan class=\"pl-k\"\u003eprotected\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribeActual\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003esubscriber\u003c/span\u003e) {\n \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowableMapSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt;(\u003cspan class=\"pl-s1\"\u003esubscriber\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e));\n }\n \n \u003cspan class=\"pl-k\"\u003estatic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowableMapSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt;, \u003cspan class=\"pl-smi\"\u003eSubscription\u003c/span\u003e {\n \u003cspan class=\"pl-c\"\u003e// ...\u003c/span\u003e\n }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSince Java still doesn't have extension methods, \"adding\" more operators can only happen through helper methods such as \u003ccode\u003elift(C -\u0026gt; C)\u003c/code 8000 \u003e and \u003ccode\u003ecompose(R -\u0026gt; P)\u003c/code\u003e where \u003ccode\u003eC\u003c/code\u003e is the default consumer type (i.e., \u003ccode\u003ers.Subscriber\u003c/code\u003e), \u003ccode\u003eR\u003c/code\u003e is the base type (i.e., \u003ccode\u003eFlowable\u003c/code\u003e) and \u003ccode\u003eP\u003c/code\u003e is the base interface (i.e., \u003ccode\u003ers.Publisher\u003c/code\u003e). As before, the library itself may gain or lose standard operators and/or overloads through the same community process.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn concert, \u003ccode\u003ecreate(OnSubscribe)\u003c/code\u003e will not be available; standard operators extend the base types directly. The conversion of other RS-based libraries will happen through the \u003ccode\u003eFlowable.wrap(Publisher\u0026lt;T\u0026gt;)\u003c/code\u003e static method.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e(\u003cem\u003eThe unfortunate effect of \u003ccode\u003ecreate\u003c/code\u003e in 1.x was the ignorance of the Observable contract and beginner's first choice as an entry point. We can't eliminate this path since \u003ccode\u003ers.Publisher\u003c/code\u003e is a single method functional interface that can be implemented just as badly.\u003c/em\u003e)\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTherefore, new standard factory methods will try to address the common entry point requirements.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eFlowable\u003c/code\u003e will contain the following \u003ccode\u003ecreate\u003c/code\u003e methods:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ecreate(SyncGenerator\u0026lt;T, S\u0026gt;)\u003c/code\u003e: safe, synchronous generation of signals, one-by-one\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreate(AsyncOnSubscribe\u0026lt;T, S\u0026gt;)\u003c/code\u003e: batch-create signals based on request patterns\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreate(Consumer\u0026lt;? super FlowEmitter\u0026lt;T\u0026gt;\u0026gt;)\u003c/code\u003e: relay multiple values or error from multi-valued reactive-sources (i.e., button-clicks) while also give flow control options right there (buffer, drop, error, etc.).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreateSingle(Consumer\u0026lt;? super SingleEmitter\u0026lt;T\u0026gt;\u0026gt;)\u003c/code\u003e: relay a single value or error from other reactive sources (i.e., addListener callbacks)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreateEmpty(Consumer\u0026lt;? super CompletionEmitter\u0026gt;)\u003c/code\u003e: signal a completion or error from valueless reactive sources\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eObservable\u003c/code\u003e will contain the following \u003ccode\u003ecreate\u003c/code\u003e methods:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ecreate(SyncGenerator\u0026lt;T, S\u0026gt;)\u003c/code\u003e: safe, synchronous generation of signals, one-by-one\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreate(Consumer\u0026lt;? super FlowEmitter\u0026lt;T\u0026gt;\u0026gt;)\u003c/code\u003e: relay multiple values or error from multi-valued reactive-sources (i.e., button-clicks) while also give flow control options right there (buffer, drop, error, etc.).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreateSingle(Consumer\u0026lt;? super SingleEmitter\u0026lt;T\u0026gt;\u0026gt;)\u003c/code\u003e: relay a single value or error from other reactive sources (i.e., addListener callbacks)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecreateEmpty(Consumer\u0026lt;? super CompletionEmitter\u0026gt;)\u003c/code\u003e: signal a completion or error from valueless reactive sources\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eSingle\u003c/code\u003e will contain the following \u003ccode\u003ecreate\u003c/code\u003e method:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ecreate(Consumer\u0026lt;? super SingleEmitter\u0026lt;T\u0026gt;\u0026gt;)\u003c/code\u003e: relay a single value or error from other reactive sources (i.e., addListener callbacks)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eCompletable\u003c/code\u003e will contain the following \u003ccode\u003ecreate\u003c/code\u003e method:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ecreate(Consumer\u0026lt;? super CompletionEmitter\u0026gt;)\u003c/code\u003e: signal a completion or error from valueless reactive sources\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThe first two \u003ccode\u003ecreate\u003c/code\u003e methods take an implementation of an interface which provides state and the generator methods:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"interface SyncGenerator\u0026lt;T, S\u0026gt; {\n\n S createState();\n \n S generate(S state, Observer\u0026lt;T\u0026gt; output);\n \n void disposeState(S state);\n}\n\ninterface AsyncGenerator\u0026lt;T, S\u0026gt; {\n\n S createState();\n \n S generate(S state, long requested, Observer\u0026lt;Observable\u0026lt;T\u0026gt;\u0026gt; output);\n \n void disposeState(S state);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSyncGenerator\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e\u0026gt; {\n\n \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ecreateState\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-en\"\u003egenerate\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003estate\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eObserver\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003eoutput\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003edisposeState\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003estate\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eAsyncGenerator\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e\u0026gt; {\n\n \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ecreateState\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-en\"\u003egenerate\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003estate\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003elong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003erequested\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eObserver\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eObservable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt;\u0026gt; \u003cspan class=\"pl-s1\"\u003eoutput\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003edisposeState\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eS\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003estate\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThese latter three \u003ccode\u003ecreate\u003c/code\u003e methods will provide the following interaction interfaces to the \u003ccode\u003ejava.util.function.Consumer\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"interface SingleEmitter\u0026lt;T\u0026gt; {\n\n complete(T value);\n \n fail(Throwable error);\n \n stop();\n \n setDisposable(Disposable d);\n \n}\n\ninterface FlowEmitter\u0026lt;T\u0026gt; {\n\n void next(T value);\n \n void fail(Throwable error);\n \n void complete();\n \n void stop();\n\n setDisposable(Disposable d);\n\n enum BackpressureHandling {\n IGNORE,\n ERROR,\n DROP,\n LATEST,\n BUFFER\n }\n\n void setBackpressureHandling(BackpressureHandling mode);\n \n}\n\ninterface CompletableEmitter\u0026lt;T\u0026gt; {\n\n complete();\n \n fail(Throwable error);\n \n stop();\n \n setDisposable(Disposable d);\n \n}\n\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSingleEmitter\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n\n \u003cspan class=\"pl-smi\"\u003ecomplete\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003efail\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eerror\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003estop\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003esetDisposable\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n \n}\n\n\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowEmitter\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003enext\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003efail\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eerror\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ecomplete\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003estop\u003c/span\u003e();\n\n \u003cspan class=\"pl-smi\"\u003esetDisposable\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n\n \u003cspan class=\"pl-k\"\u003eenum\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eBackpressureHandling\u003c/span\u003e {\n \u003cspan class=\"pl-c1\"\u003eIGNORE\u003c/span\u003e,\n \u003cspan class=\"pl-c1\"\u003eERROR\u003c/span\u003e,\n \u003cspan class=\"pl-c1\"\u003eDROP\u003c/span\u003e,\n \u003cspan class=\"pl-c1\"\u003eLATEST\u003c/span\u003e,\n \u003cspan class=\"pl-c1\"\u003eBUFFER\u003c/span\u003e\n }\n\n \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esetBackpressureHandling\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eBackpressureHandling\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emode\u003c/span\u003e);\n \n}\n\n\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eCompletableEmitter\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n\n \u003cspan class=\"pl-smi\"\u003ecomplete\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003efail\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eThrowable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eerror\u003c/span\u003e);\n \n \u003cspan class=\"pl-smi\"\u003estop\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e();\n \n \u003cspan class=\"pl-smi\"\u003esetDisposable\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDisposable\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ed\u003c/span\u003e);\n \n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBy extending the base classes, operator implementations would loose the tracking/wrapping features of 1.x. To avoid this, the methods \u003ccode\u003esubscribe(C)\u003c/code\u003e will be final and operators have to implement a protected \u003ccode\u003esubscribeActual\u003c/code\u003e (or any other reasonable name).\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Override\npublic final void subscribe(Subscriber\u0026lt;? super T\u0026gt; s) {\n subscribeActual(hook.onSubscribe(s));\n} \n\nprotected abstract void subscribeActual(Subscriber\u0026lt;? super T\u0026gt; s);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e) {\n \u003cspan class=\"pl-en\"\u003esubscribeActual\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ehook\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eonSubscribe\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e));\n} \n\n\u003cspan class=\"pl-k\"\u003eprotected\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eabstract\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribeActual\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e);\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAssembly-time hooks will be moved into the individual standard methods on the base types:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public final Flowable\u0026lt;R\u0026gt; map(Function\u0026lt;? super T, ? extends R\u0026gt; mapper) {\n return hook.onAssembly(new FlowableMap\u0026lt;T, R\u0026gt;(this, mapper));\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efinal\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-en\"\u003emap\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eFunction\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, ? \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e) {\n \u003cspan class=\"pl-k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ehook\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eonAssembly\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFlowableMap\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eR\u003c/span\u003e\u0026gt;(\u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003emapper\u003c/span\u003e));\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTerminal behavior\u003c/h3\u003e\u003ca id=\"user-content-terminal-behavior\" class=\"anchor\" aria-label=\"Permalink: Terminal behavior\" href=\"#terminal-behavior\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA producer can terminate a stream by emitting \u003ccode\u003eonComplete\u003c/code\u003e or \u003ccode\u003eonError\u003c/code\u003e. A consumer can terminate a stream by calling \u003ccode\u003ecancel\u003c/code\u003e/\u003ccode\u003edispose\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAny resource cleanup of the source or operators must account for any of these three termination events. In other words, if an operator needs cleanup, then it should register the cleanup callback with \u003ccode\u003ecancel\u003c/code\u003e/\u003ccode\u003edispose\u003c/code\u003e, \u003ccode\u003eonError\u003c/code\u003e and \u003ccode\u003eonComplete\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe final \u003ccode\u003esubscribe\u003c/code\u003e will \u003cem\u003enot\u003c/em\u003e invoke \u003ccode\u003ecancel\u003c/code\u003e/\u003ccode\u003edispose\u003c/code\u003e after receiving an \u003ccode\u003eonComplete\u003c/code\u003e or \u003ccode\u003eonError\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJVM target and source compatibility\u003c/h3\u003e\u003ca id=\"user-content-jvm-target-and-source-compatibility\" class=\"anchor\" aria-label=\"Permalink: JVM target and source compatibility\" href=\"#jvm-target-and-source-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe 2.x version will target JDK6+ to let Android users consume the new version of RxJava.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFuture work\u003c/h3\u003e\u003ca id=\"user-content-future-work\" class=\"anchor\" aria-label=\"Permalink: Future work\" href=\"#future-work\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis section contains current design work which needs more discussion and elaboration before it is merged into this document as a stated goal for 2.x.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCustom Observable, Single, Completable, or Flowable\u003c/h4\u003e\u003ca id=\"user-content-custom-observable-single-completable-or-flowable\" class=\"anchor\" aria-label=\"Permalink: Custom Observable, Single, Completable, or Flowable\" href=\"#custom-observable-single-completable-or-flowable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe are investigate a base interface (similar to \u003ccode\u003ePublisher\u003c/code\u003e) for the \u003ccode\u003eObservable\u003c/code\u003e, \u003ccode\u003eSingle\u003c/code\u003e, and \u003ccode\u003eCompletable\u003c/code\u003e (currently referred to as \u003ccode\u003eConsumable\u003c/code\u003e or \u003ccode\u003eConsumableObservable\u003c/code\u003e). This would empower library owners and api developers to implement their own type of \u003ccode\u003eObservable\u003c/code\u003e, \u003ccode\u003eSingle\u003c/code\u003e, or \u003ccode\u003eCompletable\u003c/code\u003e without extending the class. This would result in a change the type signatures of \u003ccode\u003esubscribe\u003c/code\u003e as well as any operator that operates over an \u003ccode\u003eObservable\u003c/code\u003e, \u003ccode\u003eSingle\u003c/code\u003e, or \u003ccode\u003eCompletable\u003c/code\u003e to accept a more generic type (i.e. \u003ccode\u003eConsumableObservable\u003c/code\u003e). For more information see the proof of concept project \u003ca href=\"https://github.com/stealthcode/Consumable\"\u003eConsumable\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFusion\u003c/h4\u003e\u003ca id=\"user-content-fusion\" class=\"anchor\" aria-label=\"Permalink: Fusion\" href=\"#fusion\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOperator fusion exploits the declarative nature of building flows; the developer specifies the \"what\", \"where\" and \"when\", the library then tries to optimize the \"how\".\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThere are two main levels of operator fusion: \u003cem\u003emacro\u003c/em\u003e and \u003cem\u003emicro\u003c/em\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMacro-fusion\u003c/h5\u003e\u003ca id=\"user-content-macro-fusion\" class=\"anchor\" aria-label=\"Permalink: Macro-fusion\" href=\"#macro-fusion\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMacro fusion deals with the higher level view of the operators, their identity and their combination (mostly in the form of subsequence). This is partially an internal affair of the operators, triggered by the downstream operator and may work with several cases. Given an operator application pair \u003ccode\u003ea().b()\u003c/code\u003e where \u003ccode\u003ea\u003c/code\u003e could be a source or an intermediate operator itself, when the application of \u003ccode\u003eb\u003c/code\u003e happens in assembly time, the following can happen:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eb\u003c/code\u003e identifies \u003ccode\u003ea\u003c/code\u003e and decides to not apply itself. Example: \u003ccode\u003eempty().flatMap()\u003c/code\u003e is functionally a no-op\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eb\u003c/code\u003e identifies \u003ccode\u003ea\u003c/code\u003e and decides to apply a different, conventional operator. Example: \u003ccode\u003ejust().subscribeOn()\u003c/code\u003e is turned into \u003ccode\u003ejust().observeOn()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eb\u003c/code\u003e decides to apply a new custom operator, combining and inlining existing behavior. Example: \u003ccode\u003ejust().subscribeOn()\u003c/code\u003e internally goes to \u003ccode\u003eScalarScheduledPublisher\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ea\u003c/code\u003e is \u003ccode\u003eb\u003c/code\u003e and the two operator's parameter set can be combined into a single application. Example: \u003ccode\u003efilter(p1).filter(p2)\u003c/code\u003e combined into \u003ccode\u003efilter(p1 \u0026amp;\u0026amp; p2)\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eParticipating in the macro-fusion externally is possible by implementing a marker interface when extending \u003ccode\u003eFlowable\u003c/code\u003e. Two kinds of interfaces are available:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ejava.util.Callable\u003c/code\u003e: the Java standard, throwing interface, indicating the single value has to be extracted in subscription time (or later).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eScalarCallable\u003c/code\u003e: to indicate the single value can be safely extracted during assembly time and used/inlined in other operators:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"interface ScalarCallable\u0026lt;T\u0026gt; extends java.util.Callable\u0026lt;T\u0026gt; {\n @Override\n T call();\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eScalarCallable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ejava\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eutil\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eCallable\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ecall\u003c/span\u003e();\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eScalarCallable\u003c/code\u003e is also \u003ccode\u003eCallable\u003c/code\u003e and thus its value can be extracted practically anytime. For convenience (and for sense), \u003ccode\u003eScalarCallable\u003c/code\u003e overrides and hides the superclass' \u003ccode\u003ethrows Exception\u003c/code\u003e clause - throwing during assembly time is likely unreasonable for scalars.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSince Reactive-Streams doesn't allow \u003ccode\u003enull\u003c/code\u003es in the value flow, we have the opportunity to define \u003ccode\u003eScalarCallable\u003c/code\u003es and \u003ccode\u003eCallable\u003c/code\u003es returning \u003ccode\u003enull\u003c/code\u003e should be considered as an empty source - allowing operators to dispatch on the type \u003ccode\u003eCallable\u003c/code\u003e first then branch on the nullness of \u003ccode\u003ecall()\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eInteroperating with other libraries, at this level is possible. Reactor-Core uses the same pattern and the two libraries can work with each other's \u003ccode\u003ePublisher+Callable\u003c/code\u003e types. Unfortunately, this means subscription-time only fusion as \u003ccode\u003eScalarCallable\u003c/code\u003es live locally in each library.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMicro-fusion\u003c/h5\u003e\u003ca id=\"user-content-micro-fusion\" class=\"anchor\" aria-label=\"Permalink: Micro-fusion\" href=\"#micro-fusion\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMicro-fusion goes a step deeper and tries to reuse internal structures, mostly queues, in operator pairs, saving on allocation and sometimes on atomic operations. It's property is that, in a way, subverts the standard Reactive-Streams protocol between subsequent operators that both support fusion. However, from the outside world's view, they still work according to the RS protocol.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eCurrently, two main kinds of micro-fusion opportunities are available.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch6 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1) Conditional Subscriber\u003c/h6\u003e\u003ca id=\"user-content-1-conditional-subscriber\" class=\"anchor\" aria-label=\"Permalink: 1) Conditional Subscriber\" href=\"#1-conditional-subscriber\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 5C65 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis extends the RS \u003ccode\u003eSubscriber\u003c/code\u003einterface with an extra method: \u003ccode\u003eboolean tryOnNext(T value)\u003c/code\u003e and can help avoiding small request amounts in case an operator didn't forward but dropped the value. The canonical use is for the \u003ccode\u003efilter()\u003c/code\u003e operator where if the predicate returns false, the operator has to request 1 from upstream (since the downstream doesn't know there was a value dropped and thus not request itself). Operators wanting to participate in this fusion have to implement and subscribe with an extended Subscriber interface:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"interface ConditionalSubscriber\u0026lt;T\u0026gt; {\n boolean tryOnNext(T value);\n}\n\n//...\n@Override\nprotected void subscribeActual(Subscriber\u0026lt;? super T\u0026gt; s) {\n if (s instanceof ConditionalSubscriber) {\n source.subscribe(new FilterConditionalSubscriber\u0026lt;\u0026gt;(s, predicate));\n } else {\n source.subscribe(new FilterRegularSubscriber\u0026lt;\u0026gt;(s, predicate));\n }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eConditionalSubscriber\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; {\n \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e \u003cspan class=\"pl-en\"\u003etryOnNext\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-c\"\u003e//...\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003eprotected\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003esubscribeActual\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSubscriber\u003c/span\u003e\u0026lt;? \u003cspan class=\"pl-en\"\u003esuper\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e) {\n \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einstanceof\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eConditionalSubscriber\u003c/span\u003e) {\n \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFilterConditionalSubscriber\u003c/span\u003e\u0026lt;\u0026gt;(\u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003epredicate\u003c/span\u003e));\n } \u003cspan class=\"pl-k\"\u003eelse\u003c/span\u003e {\n \u003cspan class=\"pl-s1\"\u003esource\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esubscribe\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFilterRegularSubscriber\u003c/span\u003e\u0026lt;\u0026gt;(\u003cspan class=\"pl-s1\"\u003es\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003epredicate\u003c/span\u003e));\n }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e(Note that this may lead to extra case-implementations in operators that have some kind of queue-drain emission model.)\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch6 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2) Queue-fusion\u003c/h6\u003e\u003ca id=\"user-content-2-queue-fusion\" class=\"anchor\" aria-label=\"Permalink: 2) Queue-fusion\" href=\"#2-queue-fusion\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe second category is when two (or more) operators share the same underlying queue and each append activity at the exit point (i.e., poll()) of the queue. This can work in two modes: synchronous and asynchronous.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn synchronous mode, the elements of the sequence is already available (i.e., a fixed \u003ccode\u003erange()\u003c/code\u003e or \u003ccode\u003efromArray()\u003c/code\u003e, or can be synchronously calculated in a pull fashion in \u003ccode\u003efromIterable\u003c/code\u003e. In this mode, the requesting and regular onError-path is bypassed and is forbidden. Sources have to return null from \u003ccode\u003epull()\u003c/code\u003e and false from \u003ccode\u003eisEmpty()\u003c/code\u003e if they have no more values and throw from these methods if they want to indicate an exceptional case.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn asynchronous mode, elements may become available at any time, therefore, \u003ccode\u003epull\u003c/code\u003e returning null, as with regular queue-drain, is just the indication of temporary lack of source values. Completion and error still has to go through \u003ccode\u003eonComplete\u003c/code\u003e and \u003ccode\u003eonError\u003c/code\u003e as usual, requesting still happens as usual but when a value is available in the shared queue, it is indicated by an \u003ccode\u003eonNext(null)\u003c/code\u003e call. This can trigger a chain of \u003ccode\u003edrain\u003c/code\u003e calls without moving values in or out of different queues.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn both modes, \u003ccode\u003ecancel\u003c/code\u003e works and behaves as usual.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSince this fusion mode is an optional extension, the mode switch has to be negotiated and the shared queue interface established. Operators already working with internal queues then can, mostly, keep their current \u003ccode\u003edrain()\u003c/code\u003e algorithm. Queue-fusion has its own interface and protocol built on top of the existing \u003ccode\u003eonSubscribe\u003c/code\u003e-\u003ccode\u003eSubscription\u003c/code\u003e rail:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"interface QueueSubscription\u0026lt;T\u0026gt; implements Queue\u0026lt;T\u0026gt;, Subscription {\n int NONE = 0;\n int SYNC = 1;\n int ASYNC = 2;\n int ANY = SYNC | ASYNC;\n int BOUNDARY = 4;\n\n int requestFusion(int mode);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eQueueSubscription\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eQueue\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eT\u003c/span\u003e\u0026gt;, \u003cspan class=\"pl-s1\"\u003eSubscription\u003c/span\u003e {\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eNONE\u003c/span\u003e = \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eSYNC\u003c/span\u003e = \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e;\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eASYNC\u003c/span\u003e = \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e;\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eANY\u003c/span\u003e = \u003cspan class=\"pl-c1\"\u003eSYNC\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003eASYNC\u003c/span\u003e;\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eBOUNDARY\u003c/span\u003e = \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e;\n\n \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-en\"\u003erequestFusion\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emode\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor performance, the mode is an integer bitflags setup, called early during subscription time, and allows negotiating the fusion mode. Usually, producers can do only one mode and consumers can do both mode. Because fused, intermediate operators attach logic (which is many times user-callback) to the exit point of the queue interface (poll()), it may change the computation location of those callbacks in an unwanted way. The flag \u003ccode\u003eBOUNDARY\u003c/code\u003e is added by consumers indicating that they will consume the queue over an async boundary. Intermediate operators, such as \u003ccode\u003emap\u003c/code\u003e and \u003ccode\u003efilter\u003c/code\u003e then can reject the fusion in such sequences.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSince RxJava 2.x is still JDK 6 compatible, the \u003ccode\u003eQueueSubscription\u003c/code\u003e can't itself default unnecessary methods and implementations are required to throw \u003ccode\u003eUnsupportedOperationException\u003c/code\u003e for \u003ccode\u003eQueue\u003c/code\u003e methods other than the following:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003epoll()\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eisEmpty()\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eclear()\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esize()\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eEven though other modern libraries also define this interface, they live in local packages and thus non-reusable without dragging in the whole library. Therefore, until externalized and standardized, cross-library micro-fusion won't happen.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eA consequence of the extension of the \u003ccode\u003eonSubscribe\u003c/code\u003e-\u003ccode\u003eSubscription\u003c/code\u003e rail is that intermediate operators are no longer allowed to pass an upstream \u003ccode\u003eSubscription\u003c/code\u003e directly to its downstream \u003ccode\u003eSubscriber.onSubscribe\u003c/code\u003e. Doing so is likely to have the fused sequence skip the operator completely, losing behavior or causing runtime exceptions. Since RS \u003ccode\u003eSubscriber\u003c/code\u003e is an interface, operators can simply implement both \u003ccode\u003eSubscriber\u003c/code\u003e and \u003ccode\u003eSubscription\u003c/code\u003e on themselves, delegating the \u003ccode\u003erequest\u003c/code\u003e and \u003ccode\u003ecancel\u003c/code\u003e calls to the upstream and calling \u003ccode\u003echild.onSubscribe(this)\u003c/code\u003e.\u003c/p\u003e\n\u003c/article\u003e","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":8,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":null},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"csrf_tokens":{"/pedes/RxJava/branches":{"post":"FcCz9st_56OwXzHcuXPINrBuPW6sE5c0VRjH7mR_JROyOjMtL7OdSEbC5e0m4oD8392brqPpLqBmQhhBCnN3Yw"},"/repos/preferences":{"post":"XaKrsHteOno0rcTMBk37YTeGV_flL2zqe2OsPegsX2MLliqFkvV5YVsPf_eD6JY8f8APjEkd3EC6RCSausKJgg"}}},"title":"RxJava/DESIGN.md at 2.x · pedes/RxJava","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-263cab1760dd.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-b84e9496fc59.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"react_blob_overlay":false,"accessible_code_button":true}}}
0