<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P2300R6: `std::execution`</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in § N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *     -> ins/del.c### for candidate and proposed changes (amendments)
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *   - .correction for "candidate corrections"       (div, aside, details, section)
 *   - .addition   for "candidate additions"         (div, aside, details, section)
 *   - .correction.proposed for "proposed corrections" (div, aside, details, section)
 *   - .addition.proposed   for "proposed additions"   (div, aside, details, section)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Outdated warning for old specs
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/* color variables included separately for reliability */

/******************************************************************************/
/*                                    Body                                    */
/******************************************************************************/

	html {
	}

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;			  /* limit line length to 50em for readability   */
		margin: 0 auto;				/* center text within page                    */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag    */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		color: black;
		color: var(--text);
		background: white top left fixed no-repeat;
		background: var(--bg) top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em; }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border: solid var(--logo-bg);
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		background: var(--logo-bg);
		color: white;
		color: var(--logo-text);
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		background: var(--logo-active-bg);
		border-color: #c00;
		border-color: var(--logo-active-bg);
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small; }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 3;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;

			color: #707070;
			color: var(--tocnav-normal-text);
			background: white;
			background: var(--tocnav-normal-bg);
		}
		#toc-nav > a:hover,
		#toc-nav > a:focus {
			color: black;
			color: var(--tocnav-hover-text);
			background: #f8f8f8;
			background: var(--tocnav-hover-bg);
		}
		#toc-nav > a:active {
			color: #c00;
			color: var(--tocnav-active-text);
			background: white;
			background: var(--tocnav-active-bg);
		}

		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;	/* Inherit the font family. */
		line-height: 1.2;		/* Keep wrapped headings compact */
		hyphens: manual;		/* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		color: var(--heading-text);
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#profile-and-date {
		/* #profile-and-date is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > :not(.head) + hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		color: black;
		color: var(--hr-text);
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	border-left: 0.5em solid #DEF;
	border-left: 0.5em solid var(--algo-border);
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	 padding: .5em;
	 border: thin solid #ddd;
	 border: thin solid var(--algo-border);
	 border-radius: .5em;
	 margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	 margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	 margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	margin-left: -2em;
	}
	dl.switch {
	padding-left: 2em;
	}
	dl.switch > dt {
	text-indent: -1.5em;
	margin-top: 1em;
	}
	dl.switch > dt + dt {
	margin-top: 0;
	}
	dl.switch > dt::before {
	content: '\21AA';
	padding: 0 0.5em 0 0;
	display: inline-block;
	width: 1em;
	text-align: right;
	line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: inherit;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del {
		color: #aa0000;
		color: var(--del-text);
		background: transparent;
		background: var(--del-bg);
		text-decoration: line-through;
	}
	ins {
		color: #006100;
		color: var(--ins-text);
		background: transparent;
		background: var(--ins-bg);
		text-decoration: underline;
	}

	/* for amendments (candidate/proposed changes) */

	.amendment ins, .correction ins, .addition ins,
	ins[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment del, .correction del, .addition del,
	del[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment.proposed ins, .correction.proposed ins, .addition.proposed ins,
	ins[class^=c].proposed {
		text-decoration-style: double;
	}
	.amendment.proposed del, .correction.proposed del, .addition.proposed del,
	del[class^=c].proposed {
		text-decoration-style: double;
	}

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

	/* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		color: var(--a-normal-text);
		text-decoration: underline #707070;
		text-decoration: underline var(--a-normal-underline);
		text-decoration-skip-ink: none;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		text-decoration-color: #bbb;
		text-decoration-color: var(--a-visited-underline);
	}

	/* Indicate interaction with the link */
	a[href]:focus,
	a[href]:hover {
		text-decoration-thickness: 2px;
	}
	a[href]:active {
		color: #c00;
		color: var(--a-active-text);
		text-decoration-color: #c00;
		text-decoration-color: var(--a-active-underline);
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	img, svg {
		/* Intentionally not color-scheme aware. */
		background: white;
	}

	/* For autogen numbers, add
	  .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,	.sidefigure img,	figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
		height: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em;
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em; }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote,
	.amendment, .correction, .addition {
		margin: 1em auto;
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	blockquote > :first-child,
	.note  > p:first-child,
	.issue > p:first-child,
	.amendment > p:first-child,
	.correction > p:first-child,
	.addition > p:first-child {
		margin-top: 0;
	}
	blockquote > :last-child,
	.note  > p:last-child,
	.issue > p:last-child,
	.amendment > p:last-child,
	.correction > p:last-child,
	.addition > p:last-child {
		margin-bottom: 0;
	}


	.issue::before, .issue > .marker,
	.example::before, .example > .marker,
	.note::before, .note > .marker,
	details.note > summary > .marker,
	.amendment::before, .amendment > .marker,
	details.amendment > summary > .marker,
	.addition::before, .addition > .marker,
	addition.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	correction.amendment > summary > .marker
	{
		text-transform: uppercase;
		padding-right: 1em;
	}

	.example::before, .example > .marker {
		display: block;
		padding-right: 0em;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
		border-color: var(--blockquote-border);
		background: transparent;
		background: var(--blockquote-bg);
		color: currentcolor;
		color: var(--blockquote-text);
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	  or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #e0cb52;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	  or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52e052;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary {
		color: hsl(120, 70%, 30%);
		color: var(--noteheading-text);
	}
	/* Add .note::before { content: "Note "; } for autogen label,
	  or use class="marker" to mark up the label in source. */

	details.note[open] > summary {
		border-bottom: 1px silver solid;
		border-bottom: 1px var(--notesummary-underline) solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		border-color: var(--assertion-border);
		background: #EEE;
		background: var(--assertion-bg);
		color: black;
		color: var(--assertion-text);
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-color: var(--advisement-border);
		border-style: none solid;
		background: #fec;
		background: var(--advisement-bg);
		color: black;
		color: var(--advisement-text);
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement::before, .advisement > .marker {
		color: #b35f00;
		color: var(--advisementheading-text);
	}

/** Amendment Box *************************************************************/

	.amendment, .correction, .addition {
		border-color: #330099;
		border-color: var(--amendment-border);
		background: #F5F0FF;
		background: var(--amendment-bg);
		color: black;
		color: var(--amendment-text);
	}
	.amendment.proposed, .correction.proposed, .addition.proposed {
		border-style: solid;
		border-block-width: 0.25em;
	}
	.amendment::before, .amendment > .marker,
	details.amendment > summary::before, details.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	details.correction > summary::before, details.correction > summary > .marker,
	.addition::before, .addition > .marker,
	details.addition > summary::before, details.addition > summary > .marker {
		color: #220066;
		color: var(--amendmentheading-text);
	}
	.amendment.proposed::before, .amendment.proposed > .marker,
	details.amendment.proposed > summary::before, details.amendment.proposed > summary > .marker,
	.correction.proposed::before, .correction.proposed > .marker,
	details.correction.proposed > summary::before, details.correction.proposed > summary > .marker,
	.addition.proposed::before, .addition.proposed > .marker,
	details.addition.proposed > summary::before, details.addition.proposed > summary > .marker {
		font-weight: bold;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 2em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #def;
		background: var(--def-bg);
		margin: 1.2em 0;
		border-left: 0.5em solid #8ccbf2;
		border-left: 0.5em solid var(--def-border);
		color: black;
		color: var(--def-text);
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
		border-bottom: 1px solid var(--defrow-border);
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def td.footnote {
		padding-top: 0.6em;
	}
	table.def td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		<table class="data"> highlights structural relationships in a table
		when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		Use class="complex data" for particularly complicated tables --
		(This will draw more lines: busier, but clearer.)

		Use class="long" on table cells with paragraph-like contents
		(This will adjust text alignment accordingly.)
		Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-color: var(--datacell-border);
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		border-top: 1px solid var(--datacell-border);
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		border: 1px solid var(--datacell-border);
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
		vertical-align: baseline;
		text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding: 0.1rem 1px 0;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Switch to using border-bottom for underlines */
		text-decoration: none;
		border-bottom: 1px solid;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:focus,
	.toc a:hover {
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
	}
	.toc {
		line-height: 1.1em;
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li			{ font-weight: bold;   }
	.toc > li li		 { font-weight: normal; }
	.toc > li li li	  { font-size:   95%;	}
	.toc > li li li li	{ font-size:   90%;	}
	.toc > li li li li li { font-size:   85%;	}

	/* @supports not (display:grid) { */
		.toc > li			{ margin: 1.5rem 0;	}
		.toc > li li		 { margin: 0.3rem 0;	}
		.toc > li li li	  { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}
		.toc > li li li li .secno { font-size: 85%; }
		.toc > li li li li li .secno { font-size: 100%; }

		.toc li {
			clear: both;
		}

		:not(li) > .toc			 { margin-left:  5rem; }
		.toc .secno				 { margin-left: -5rem; }
		.toc > li li li .secno	  { margin-left: -7rem; }
		.toc > li li li li .secno	{ margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc			 { margin-left:  4rem; }
			.toc .secno				 { margin-left: -4rem; }
			.toc > li li li			 { margin-left:  1rem; }
			.toc > li li li .secno	  { margin-left: -5rem; }
			.toc > li li li li .secno	{ margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc			 { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno				 { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li			 { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno	  { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno	{ margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			  comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom: 3px solid #054572;
			border-bottom: 3px solid var(--toclink-underline);
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index	  { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li	{ margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em; }
	ul.index dl	{ margin-top: 0; }
	ul.index dt	{ margin: .2em 0 .2em 20px;}
	ul.index dd	{ margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li a + span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
			color: var(--indexinfo-text);
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/** Outdated warning **********************************************************/

.outdated-spec {
	color: black;
	color: var(--outdatedspec-text);
	background-color: rgba(0,0,0,0.5);
	background-color: var(--outdatedspec-bg);
}

.outdated-warning {
	position: fixed;
	bottom: 50%;
	left: 0;
	right: 0;
	margin: 0 auto;
	width: 50%;
	background: maroon;
	background: var(--outdated-bg);
	color: white;
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	position: absolute;
	top: 0;
	right:0;
	margin: 0;
	border: 0;
	padding: 0.25em 0.5em;
	background: transparent;
	color: white;
	color: var(--outdated-text);
	font:1em sans-serif;
	text-align:center;
}

.outdated-warning span {
	display: block;
}

.outdated-collapsed {
	bottom: 0;
	border-radius: 0;
	width: 100%;
	padding: 0;
}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}

		.outdated-warning {
			position: absolute;
			border-style: solid;
			border-color: red;
		}

		.outdated-warning input {
			display: none;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good item positioning:
		  "content column" is 50ems wide at max; less on smaller screens.
		  Extra space (after ToC + content) is empty on the right.

		  1. When item < content column, centers item in column.
		  2. When content < item < available, left-aligns.
		  3. When item > available, fills available + scroll bar.
		*/
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			* http://lea.verou.me/2012/04/background-attachment-local/
			*
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
						top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
						top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style>
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 44af0bf3e, updated Fri Jul 29 17:05:16 2022 -0700" name="generator">
  <link href="https://wg21.link/P2300" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="d732ca388fd7ad9a5d0debc797d870d7135f6266" name="document-revision">
<style>
pre {
  margin-top: 0px;
  margin-bottom: 0px;
}
table, th, tr, td {
  border: 2px solid black !important;
}
@media (prefers-color-scheme: dark) {
  table, th, tr, td {
    border: 2px solid white !important;
  }
}
.ins, ins, ins *, span.ins, span.ins * {
  background-color: rgb(200, 250, 200);
  color: rgb(0, 136, 0);
  text-decoration: none;
}
.del, del, del *, span.del, span.del * {
  background-color: rgb(250, 200, 200);
  color: rgb(255, 0, 0);
  text-decoration: line-through;
  text-decoration-color: rgb(255, 0, 0);
}
math, span.math {
  font-family: serif;
  font-style: italic;
}
ul {
  list-style-type: "— ";
}
blockquote {
  counter-reset: paragraph;
}
div.numbered, div.newnumbered {
  margin-left: 2em;
  margin-top: 1em;
  margin-bottom: 1em;
}
div.numbered:before, div.newnumbered:before {
  position: absolute;
  margin-left: -2em;
  display-style: block;
}
div.numbered:before {
  content: counter(paragraph);
  counter-increment: paragraph;
}
div.newnumbered:before {
  content: "�";
}
div.numbered ul, div.newnumbered ul {
  counter-reset: list_item;
}
div.numbered li, div.newnumbered li {
  margin-left: 3em;
}
div.numbered li:before, div.newnumbered li:before {
  position: absolute;
  margin-left: -4.8em;
  display-style: block;
}
div.numbered li:before {
  content: "(" counter(paragraph) "." counter(list_item) ")";
  counter-increment: list_item;
}
div.newnumbered li:before {
  content: "(�." counter(list_item) ")";
  counter-increment: list_item;
}
div.ed-note {
  color: blue !important;
  margin-left: 2em;
}
div.ed-note:before {
  content: "[Editorial note: ";
  font-style: italic;
}
div.ed-note:after {
  content: " -- end note]";
  font-style: italic;
}
div.ed-note * {
  color: blue !important;
  margin-top: 0em;
  margin-bottom: 0em;
}
div.ed-note blockquote {
  margin-left: 2em;
}
div.wg21note:before, span.wg21note:before {
  content: "[Note: ";
  font-style: italic;
}
div.wg21note:after, span.wg21note:after {
  content: " -- end note]";
  font-style: italic;
}
h5 {
  font-style: normal; /* turn off italics of h5 headers */
}
</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-colors */

/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
:root {
    color-scheme: light dark;

    --text: black;
    --bg: white;

    --unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark);

    --logo-bg: #1a5e9a;
    --logo-active-bg: #c00;
    --logo-text: white;

    --tocnav-normal-text: #707070;
    --tocnav-normal-bg: var(--bg);
    --tocnav-hover-text: var(--tocnav-normal-text);
    --tocnav-hover-bg: #f8f8f8;
    --tocnav-active-text: #c00;
    --tocnav-active-bg: var(--tocnav-normal-bg);

    --tocsidebar-text: var(--text);
    --tocsidebar-bg: #f7f8f9;
    --tocsidebar-shadow: rgba(0,0,0,.1);
    --tocsidebar-heading-text: hsla(203,20%,40%,.7);

    --toclink-text: var(--text);
    --toclink-underline: #3980b5;
    --toclink-visited-text: var(--toclink-text);
    --toclink-visited-underline: #054572;

    --heading-text: #005a9c;

    --hr-text: var(--text);

    --algo-border: #def;

    --del-text: red;
    --del-bg: transparent;
    --ins-text: #080;
    --ins-bg: transparent;

    --a-normal-text: #034575;
    --a-normal-underline: #bbb;
    --a-visited-text: var(--a-normal-text);
    --a-visited-underline: #707070;
    --a-hover-bg: rgba(75%, 75%, 75%, .25);
    --a-active-text: #c00;
    --a-active-underline: #c00;

    --blockquote-border: silver;
    --blockquote-bg: transparent;
    --blockquote-text: currentcolor;

    --issue-border: #e05252;
    --issue-bg: #fbe9e9;
    --issue-text: var(--text);
    --issueheading-text: #831616;

    --example-border: #e0cb52;
    --example-bg: #fcfaee;
    --example-text: var(--text);
    --exampleheading-text: #574b0f;

    --note-border: #52e052;
    --note-bg: #e9fbe9;
    --note-text: var(--text);
    --noteheading-text: hsl(120, 70%, 30%);
    --notesummary-underline: silver;

    --assertion-border: #aaa;
    --assertion-bg: #eee;
    --assertion-text: black;

    --advisement-border: orange;
    --advisement-bg: #fec;
    --advisement-text: var(--text);
    --advisementheading-text: #b35f00;

    --warning-border: red;
    --warning-bg: hsla(40,100%,50%,0.95);
    --warning-text: var(--text);

    --amendment-border: #330099;
    --amendment-bg: #F5F0FF;
    --amendment-text: var(--text);
    --amendmentheading-text: #220066;

    --def-border: #8ccbf2;
    --def-bg: #def;
    --def-text: var(--text);
    --defrow-border: #bbd7e9;

    --datacell-border: silver;

    --indexinfo-text: #707070;

    --indextable-hover-text: black;
    --indextable-hover-bg: #f7f8f9;

    --outdatedspec-bg: rgba(0, 0, 0, .5);
    --outdatedspec-text: black;
    --outdated-bg: maroon;
    --outdated-text: white;
    --outdated-shadow: red;

    --editedrec-bg: darkorange;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-dfn-panel */

:root {
    --dfnpanel-bg: #ddd;
    --dfnpanel-text: var(--text);
}
.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: var(--dfnpanel-bg);
    color: var(--dfnpanel-text);
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: var(--dfnpanel-text); }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</style>
<style>/* style-issues */

a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* style-syntax-highlighting */

code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

.highlight:not(.idl) { background: rgba(0, 0, 0, .03); }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-darkmode */

@media (prefers-color-scheme: dark) {
    :root {
        --text: #ddd;
        --bg: black;

        --unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E");

        --logo-bg: #1a5e9a;
        --logo-active-bg: #c00;
        --logo-text: white;

        --tocnav-normal-text: #999;
        --tocnav-normal-bg: var(--bg);
        --tocnav-hover-text: var(--tocnav-normal-text);
        --tocnav-hover-bg: #080808;
        --tocnav-active-text: #f44;
        --tocnav-active-bg: var(--tocnav-normal-bg);

        --tocsidebar-text: var(--text);
        --tocsidebar-bg: #080808;
        --tocsidebar-shadow: rgba(255,255,255,.1);
        --tocsidebar-heading-text: hsla(203,20%,40%,.7);

        --toclink-text: var(--text);
        --toclink-underline: #6af;
        --toclink-visited-text: var(--toclink-text);
        --toclink-visited-underline: #054572;

        --heading-text: #8af;

        --hr-text: var(--text);

        --algo-border: #456;

        --del-text: #f44;
        --del-bg: transparent;
        --ins-text: #4a4;
        --ins-bg: transparent;

        --a-normal-text: #6af;
        --a-normal-underline: #555;
        --a-visited-text: var(--a-normal-text);
        --a-visited-underline: var(--a-normal-underline);
        --a-hover-bg: rgba(25%, 25%, 25%, .2);
        --a-active-text: #f44;
        --a-active-underline: var(--a-active-text);

        --borderedblock-bg: rgba(255, 255, 255, .05);

        --blockquote-border: silver;
        --blockquote-bg: var(--borderedblock-bg);
        --blockquote-text: currentcolor;

        --issue-border: #e05252;
        --issue-bg: var(--borderedblock-bg);
        --issue-text: var(--text);
        --issueheading-text: hsl(0deg, 70%, 70%);

        --example-border: hsl(50deg, 90%, 60%);
        --example-bg: var(--borderedblock-bg);
        --example-text: var(--text);
        --exampleheading-text: hsl(50deg, 70%, 70%);

        --note-border: hsl(120deg, 100%, 35%);
        --note-bg: var(--borderedblock-bg);
        --note-text: var(--text);
        --noteheading-text: hsl(120, 70%, 70%);
        --notesummary-underline: silver;

        --assertion-border: #444;
        --assertion-bg: var(--borderedblock-bg);
        --assertion-text: var(--text);

        --advisement-border: orange;
        --advisement-bg: #222218;
        --advisement-text: var(--text);
        --advisementheading-text: #f84;

        --warning-border: red;
        --warning-bg: hsla(40,100%,20%,0.95);
        --warning-text: var(--text);

        --amendment-border: #330099;
        --amendment-bg: #080010;
        --amendment-text: var(--text);
        --amendmentheading-text: #cc00ff;

        --def-border: #8ccbf2;
        --def-bg: #080818;
        --def-text: var(--text);
        --defrow-border: #136;

        --datacell-border: silver;

        --indexinfo-text: #aaa;

        --indextable-hover-text: var(--text);
        --indextable-hover-bg: #181818;

        --outdatedspec-bg: rgba(255, 255, 255, .5);
        --outdatedspec-text: black;
        --outdated-bg: maroon;
        --outdated-text: white;
        --outdated-shadow: red;

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}

@media (prefers-color-scheme: dark) {
    .highlight:not(.idl) { background: rgba(255, 255, 255, .05); }

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P2300R6<br><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code></h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2023-01-19">2023-01-19</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt class="editor">Authors:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:griwes@griwes.info">Michał Dominiak</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:evtushenko.georgy@gmail.com">Georgy Evtushenko</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:lewissbaker@gmail.com">Lewis Baker</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:lucteo@lucteo.ro">Lucian Radu Teodorescu</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:xrikcus@gmail.com">Lee Howes</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:kirk.shoop@gmail.com">Kirk Shoop</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:mgarland@nvidia.com">Michael Garland</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:eric.niebler@gmail.com">Eric Niebler</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:brycelelbach@gmail.com">Bryce Adelstein Lelbach</a>
     <dt>Source:
     <dd><a href="https://github.com/brycelelbach/wg21_p2300_execution/blob/main/execution.bs">GitHub</a>
     <dt>Issue Tracking:
     <dd><a href="https://github.com/brycelelbach/wg21_p2300_execution/issues">GitHub</a>
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Audience:
     <dd>SG1, LEWG
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#motivation"><span class="secno">1.1</span> <span class="content">Motivation</span></a>
      <li><a href="#priorities"><span class="secno">1.2</span> <span class="content">Priorities</span></a>
      <li>
       <a href="#example-end-user"><span class="secno">1.3</span> <span class="content">Examples: End User</span></a>
       <ol class="toc">
        <li><a href="#example-hello-world"><span class="secno">1.3.1</span> <span class="content">Hello world</span></a>
        <li><a href="#example-async-inclusive-scan"><span class="secno">1.3.2</span> <span class="content">Asynchronous inclusive scan</span></a>
        <li><a href="#example-async-dynamically-sized-read"><span class="secno">1.3.3</span> <span class="content">Asynchronous dynamically-sized read</span></a>
       </ol>
      <li>
       <a href="#example-async-windows-socket-recv"><span class="secno">1.4</span> <span class="content">Asynchronous Windows socket <code class="highlight"><c- n>recv</c-></code></span></a>
       <ol class="toc">
        <li>
         <a href="#example-moar"><span class="secno">1.4.1</span> <span class="content">More end-user examples</span></a>
         <ol class="toc">
          <li><a href="#example-sudoku"><span class="secno">1.4.1.1</span> <span class="content">Sudoku solver</span></a>
          <li><a href="#example-file-copy"><span class="secno">1.4.1.2</span> <span class="content">File copy</span></a>
          <li><a href="#example-echo-server"><span class="secno">1.4.1.3</span> <span class="content">Echo server</span></a>
         </ol>
       </ol>
      <li>
       <a href="#example-algorithm"><span class="secno">1.5</span> <span class="content">Examples: Algorithms</span></a>
       <ol class="toc">
        <li><a href="#example-then"><span class="secno">1.5.1</span> <span class="content"><code class="highlight"><c- n>then</c-></code></span></a>
        <li><a href="#example-retry"><span class="secno">1.5.2</span> <span class="content"><code class="highlight"><c- n>retry</c-></code></span></a>
       </ol>
      <li>
       <a href="#example-schedulers"><span class="secno">1.6</span> <span class="content">Examples: Schedulers</span></a>
       <ol class="toc">
        <li><a href="#example-schedulers-inline"><span class="secno">1.6.1</span> <span class="content">Inline scheduler</span></a>
        <li><a href="#example-single-thread"><span class="secno">1.6.2</span> <span class="content">Single thread scheduler</span></a>
       </ol>
      <li>
       <a href="#example-server"><span class="secno">1.7</span> <span class="content">Examples: Server theme</span></a>
       <ol class="toc">
        <li><a href="#example-server-let"><span class="secno">1.7.1</span> <span class="content">Composability with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span></a>
        <li><a href="#example-server-on"><span class="secno">1.7.2</span> <span class="content">Moving between execution contexts with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span></a>
       </ol>
      <li><a href="#intro-is-not"><span class="secno">1.8</span> <span class="content">What this proposal is <strong>not</strong></span></a>
      <li><a href="#intro-compare"><span class="secno">1.9</span> <span class="content">Design changes from P0443</span></a>
      <li>
       <a href="#intro-prior-art"><span class="secno">1.10</span> <span class="content">Prior art</span></a>
       <ol class="toc">
        <li><a href="#intro-prior-art-futures"><span class="secno">1.10.1</span> <span class="content">Futures</span></a>
        <li><a href="#intro-prior-art-coroutines"><span class="secno">1.10.2</span> <span class="content">Coroutines</span></a>
        <li><a href="#intro-prior-art-callbacks"><span class="secno">1.10.3</span> <span class="content">Callbacks</span></a>
       </ol>
      <li>
       <a href="#intro-field-experience"><span class="secno">1.11</span> <span class="content">Field experience</span></a>
       <ol class="toc">
        <li><a href="#intro-field-experience-libunifex"><span class="secno">1.11.1</span> <span class="content">libunifex</span></a>
        <li><a href="#intro-field-experience-other-implementations"><span class="secno">1.11.2</span> <span class="content">Other implementations</span></a>
        <li><a href="#intro-field-experience-inspirations"><span class="secno">1.11.3</span> <span class="content">Inspirations</span></a>
       </ol>
     </ol>
    <li>
     <a href="#revisions"><span class="secno">2</span> <span class="content">Revision history</span></a>
     <ol class="toc">
      <li>
       <a href="#r6"><span class="secno">2.1</span> <span class="content">R6</span></a>
       <ol class="toc">
        <li><a href="#environments-and-attributes"><span class="secno">2.1.1</span> <span class="content">Environments and attributes</span></a>
       </ol>
      <li><a href="#r5"><span class="secno">2.2</span> <span class="content">R5</span></a>
      <li>
       <a href="#r4"><span class="secno">2.3</span> <span class="content">R4</span></a>
       <ol class="toc">
        <li><a href="#dependently-typed-senders"><span class="secno">2.3.1</span> <span class="content">Dependently-typed senders</span></a>
       </ol>
      <li><a href="#r3"><span class="secno">2.4</span> <span class="content">R3</span></a>
      <li><a href="#r2"><span class="secno">2.5</span> <span class="content">R2</span></a>
      <li><a href="#r1"><span class="secno">2.6</span> <span class="content">R1</span></a>
      <li><a href="#r0"><span class="secno">2.7</span> <span class="content">R0</span></a>
     </ol>
    <li>
     <a href="#design-intro"><span class="secno">3</span> <span class="content">Design - introduction</span></a>
     <ol class="toc">
      <li><a href="#design-conventions"><span class="secno">3.1</span> <span class="content">Conventions</span></a>
      <li><a href="#design-queries-and-algorithms"><span class="secno">3.2</span> <span class="content">Queries and algorithms</span></a>
     </ol>
    <li>
     <a href="#design-user"><span class="secno">4</span> <span class="content">Design - user side</span></a>
     <ol class="toc">
      <li><a href="#design-contexts"><span class="secno">4.1</span> <span class="content">Execution contexts describe the place of execution</span></a>
      <li><a href="#design-schedulers"><span class="secno">4.2</span> <span class="content">Schedulers represent execution contexts</span></a>
      <li><a href="#design-senders"><span class="secno">4.3</span> <span class="content">Senders describe work</span></a>
      <li><a href="#design-composable"><span class="secno">4.4</span> <span class="content">Senders are composable through sender algorithms</span></a>
      <li>
       <a href="#design-propagation"><span class="secno">4.5</span> <span class="content">Senders can propagate completion schedulers</span></a>
       <ol class="toc">
        <li><a href="#design-sender-query-get_completion_scheduler"><span class="secno">4.5.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code></span></a>
       </ol>
      <li><a href="#design-transitions"><span class="secno">4.6</span> <span class="content">Execution context transitions are explicit</span></a>
      <li><a href="#design-shot"><span class="secno">4.7</span> <span class="content">Senders can be either multi-shot or single-shot</span></a>
      <li><a href="#design-forkable"><span class="secno">4.8</span> <span class="content">Senders are forkable</span></a>
      <li><a href="#design-join"><span class="secno">4.9</span> <span class="content">Senders are joinable</span></a>
      <li>
       <a href="#design-cancellation"><span class="secno">4.10</span> <span class="content">Senders support cancellation</span></a>
       <ol class="toc">
        <li><a href="#design-cancellation-summary"><span class="secno">4.10.1</span> <span class="content">Cancellation design summary</span></a>
        <li><a href="#design-cancellation-optional"><span class="secno">4.10.2</span> <span class="content">Support for cancellation is optional</span></a>
        <li><a href="#design-cancellation-racy"><span class="secno">4.10.3</span> <span class="content">Cancellation is inherently racy</span></a>
        <li><a href="#design-cancellation-status"><span class="secno">4.10.4</span> <span class="content">Cancellation design status</span></a>
       </ol>
      <li>
       <a href="#design-lazy-algorithms"><span class="secno">4.11</span> <span class="content">Sender factories and adaptors are lazy</span></a>
       <ol class="toc">
        <li><a href="#design-lazy-algorithms-detached"><span class="secno">4.11.1</span> <span class="content">Eager execution leads to detached work or worse</span></a>
        <li><a href="#design-lazy-algorithms-complexity"><span class="secno">4.11.2</span> <span class="content">Eager senders complicate algorithm implementations</span></a>
        <li><a href="#design-lazy-algorithms-runtime"><span class="secno">4.11.3</span> <span class="content">Eager senders incur cancellation-related overhead</span></a>
        <li><a href="#design-lazy-algorithms-context"><span class="secno">4.11.4</span> <span class="content">Eager senders cannot access execution context from the receiver</span></a>
       </ol>
      <li><a href="#design-fpg"><span class="secno">4.12</span> <span class="content">Schedulers advertise their forward progress guarantees</span></a>
      <li><a href="#design-pipeable"><span class="secno">4.13</span> <span class="content">Most sender adaptors are pipeable</span></a>
      <li><a href="#design-range-of-senders"><span class="secno">4.14</span> <span class="content">A range of senders represents an async sequence of data</span></a>
      <li><a href="#design-partial-success"><span class="secno">4.15</span> <span class="content">Senders can represent partial success</span></a>
      <li><a href="#design-awaitables-are-senders"><span class="secno">4.16</span> <span class="content">All awaitables are senders</span></a>
      <li><a href="#design-senders-are-awaitable"><span class="secno">4.17</span> <span class="content">Many senders can be trivially made awaitable</span></a>
      <li><a href="#design-native-coro-unwind"><span class="secno">4.18</span> <span class="content">Cancellation of a sender can unwind a stack of coroutines</span></a>
      <li><a href="#design-parallel-algorithms"><span class="secno">4.19</span> <span class="content">Composition with parallel algorithms</span></a>
      <li>
       <a href="#design-sender-factories"><span class="secno">4.20</span> <span class="content">User-facing sender factories</span></a>
       <ol class="toc">
        <li><a href="#design-sender-factory-schedule"><span class="secno">4.20.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code></span></a>
        <li><a href="#design-sender-factory-just"><span class="secno">4.20.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code></span></a>
        <li><a href="#design-sender-factory-transfer_just"><span class="secno">4.20.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code></span></a>
        <li><a href="#design-sender-factory-just_error"><span class="secno">4.20.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code></span></a>
        <li><a href="#design-sender-factory-just_stopped"><span class="secno">4.20.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code></span></a>
        <li><a href="#design-sender-factory-read"><span class="secno">4.20.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code></span></a>
       </ol>
      <li>
       <a href="#design-sender-adaptors"><span class="secno">4.21</span> <span class="content">User-facing sender adaptors</span></a>
       <ol class="toc">
        <li><a href="#design-sender-adaptor-transfer"><span class="secno">4.21.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span></a>
        <li><a href="#design-sender-adaptor-then"><span class="secno">4.21.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code></span></a>
        <li><a href="#design-sender-adaptor-upon"><span class="secno">4.21.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_</c-><c- o>*</c-></code></span></a>
        <li><a href="#design-sender-adaptor-let"><span class="secno">4.21.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span></a>
        <li><a href="#design-sender-adaptor-on"><span class="secno">4.21.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code></span></a>
        <li><a href="#design-sender-adaptor-into_variant"><span class="secno">4.21.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code></span></a>
        <li><a href="#design-sender-adaptor-stopped_as_optional"><span class="secno">4.21.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code></span></a>
        <li><a href="#design-sender-adaptor-stopped_as_error"><span class="secno">4.21.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code></span></a>
        <li><a href="#design-sender-adaptor-bulk"><span class="secno">4.21.9</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code></span></a>
        <li><a href="#design-sender-adaptor-split"><span class="secno">4.21.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code></span></a>
        <li><a href="#design-sender-adaptor-when_all"><span class="secno">4.21.11</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code></span></a>
        <li><a href="#design-sender-adaptor-transfer_when_all"><span class="secno">4.21.12</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code></span></a>
        <li><a href="#design-sender-adaptor-ensure_started"><span class="secno">4.21.13</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code></span></a>
       </ol>
      <li>
       <a href="#design-sender-consumers"><span class="secno">4.22</span> <span class="content">User-facing sender consumers</span></a>
       <ol class="toc">
        <li><a href="#design-sender-consumer-start_detached"><span class="secno">4.22.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code></span></a>
        <li><a href="#design-sender-consumer-sync_wait"><span class="secno">4.22.2</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code></span></a>
       </ol>
      <li><a href="#design-execute"><span class="secno">4.23</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code></span></a>
     </ol>
    <li>
     <a href="#design-implementer"><span class="secno">5</span> <span class="content">Design - implementer side</span></a>
     <ol class="toc">
      <li><a href="#design-receivers"><span class="secno">5.1</span> <span class="content">Receivers serve as glue between senders</span></a>
      <li><a href="#design-states"><span class="secno">5.2</span> <span class="content">Operation states represent work</span></a>
      <li><a href="#design-connect"><span class="secno">5.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code></span></a>
      <li><a href="#design-customization"><span class="secno">5.4</span> <span class="content">Sender algorithms are customizable</span></a>
      <li><a href="#design-laziness"><span class="secno">5.5</span> <span class="content">Sender adaptors are lazy</span></a>
      <li><a href="#design-fusion"><span class="secno">5.6</span> <span class="content">Lazy senders provide optimization opportunities</span></a>
      <li><a href="#design-transition-details"><span class="secno">5.7</span> <span class="content">Execution context transitions are two-step</span></a>
      <li><a href="#design-typed"><span class="secno">5.8</span> <span class="content">All senders are typed</span></a>
      <li><a href="#design-dispatch"><span class="secno">5.9</span> <span class="content">Ranges-style CPOs vs <code class="highlight"><c- n>tag_invoke</c-></code></span></a>
     </ol>
    <li><a href="#spec"><span class="secno">6</span> <span class="content">Specification</span></a>
    <li>
     <a href="#spec-except"><span class="secno">7</span> <span class="content">Exception handling [except]</span></a>
     <ol class="toc">
      <li>
       <a href="#spec-except.special"><span class="secno">7.1</span> <span class="content">Special functions [except.special]</span></a>
       <ol class="toc">
        <li>
         <a href="#spec-except.special.general"><span class="secno">7.1.1</span> <span class="content">General [except.special.general]</span></a>
         <ol class="toc">
          <li><a href="#spec-except.terminate"><span class="secno">7.1.1.1</span> <span class="content">The <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> function [except.terminate]</span></a>
         </ol>
       </ol>
     </ol>
    <li><a href="#spec-library"><span class="secno">8</span> <span class="content">Library introduction <b>[library]</b></span></a>
    <li>
     <a href="#spec-utilities"><span class="secno">9</span> <span class="content">General utilities library <b>[utilities]</b></span></a>
     <ol class="toc">
      <li>
       <a href="#spec-function.objects"><span class="secno">9.1</span> <span class="content">Function objects <b>[function.objects]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-functional.syn"><span class="secno">9.1.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>functional</c-><c- o>></c-></code> synopsis <b>[functional.syn]</b></span></a>
        <li><a href="#spec-func.tag_invoke"><span class="secno">9.1.2</span> <span class="content"><code class="highlight"><c- n>tag_invoke</c-></code> <b>[func.tag_invoke]</b></span></a>
       </ol>
     </ol>
    <li>
     <a href="#spec-thread"><span class="secno">10</span> <span class="content">Thread support library <b>[thread]</b></span></a>
     <ol class="toc">
      <li>
       <a href="#spec-thread.stoptoken"><span class="secno">10.1</span> <span class="content">Stop tokens <b>[thread.stoptoken]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-thread.stoptoken.syn"><span class="secno">10.1.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b></span></a>
        <li><a href="#spec-thread.stoptoken.concepts"><span class="secno">10.1.2</span> <span class="content">Stop token concepts <b>[thread.stoptoken.concepts]</b></span></a>
        <li>
         <a href="#spec-stoptoken"><span class="secno">10.1.3</span> <span class="content">Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.general"><span class="secno">10.1.3.1</span> <span class="content">General <b>[stoptoken.general]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stoptoken.never"><span class="secno">10.1.4</span> <span class="content">Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.never.general"><span class="secno">10.1.4.1</span> <span class="content">General <b>[stoptoken.never.general]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stoptoken.inplace"><span class="secno">10.1.5</span> <span class="content">Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.inplace.general"><span class="secno">10.1.5.1</span> <span class="content">General <b>[stoptoken.inplace.general]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.cons"><span class="secno">10.1.5.2</span> <span class="content">Constructors, copy, and assignment <b>[stoptoken.inplace.cons]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.mem"><span class="secno">10.1.5.3</span> <span class="content">Members <b>[stoptoken.inplace.mem]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.nonmembers"><span class="secno">10.1.5.4</span> <span class="content">Non-member functions <b>[stoptoken.inplace.nonmembers]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stopsource.inplace"><span class="secno">10.1.6</span> <span class="content">Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stopsource.inplace.general"><span class="secno">10.1.6.1</span> <span class="content">General <b>[stopsource.inplace.general]</b></span></a>
          <li><a href="#spec-stopsource.inplace.cons"><span class="secno">10.1.6.2</span> <span class="content">Constructors, copy, and assignment <b>[stopsource.inplace.cons]</b></span></a>
          <li><a href="#spec-stopsource.inplace.mem"><span class="secno">10.1.6.3</span> <span class="content">Members <b>[stopsource.inplace.mem]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stopcallback.inplace"><span class="secno">10.1.7</span> <span class="content">Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stopcallback.inplace.general"><span class="secno">10.1.7.1</span> <span class="content">General <b>[stopcallback.inplace.general]</b></span></a>
          <li><a href="#spec-stopcallback.inplace.cons"><span class="secno">10.1.7.2</span> <span class="content">Constructors and destructor <b>[stopcallback.inplace.cons]</b></span></a>
         </ol>
       </ol>
     </ol>
    <li>
     <a href="#spec-execution"><span class="secno">11</span> <span class="content">Execution control library <b>[exec]</b></span></a>
     <ol class="toc">
      <li><a href="#spec-execution.syn"><span class="secno">11.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis <b>[exec.syn]</b></span></a>
      <li><a href="#spec-execution.helpers"><span class="secno">11.2</span> <span class="content">Helper concepts <b>[exec.helpers]</b></span></a>
      <li>
       <a href="#spec-execution.queries"><span class="secno">11.3</span> <span class="content">Queries <b>[exec.queries]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.queries.queryable"><span class="secno">11.3.1</span> <span class="content"><code class="highlight"><c- n>queryable</c-></code> concept <b>[exec.queries.queryable]</b></span></a>
        <li><a href="#spec-execution.queries.forwarding_query"><span class="secno">11.3.2</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> <b>[exec.fwd_env]</b></span></a>
        <li><a href="#spec-execution.queries.get_allocator"><span class="secno">11.3.3</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> <b>[exec.queries.get_allocator]</b></span></a>
        <li><a href="#spec-execution.queries.get_stop_token"><span class="secno">11.3.4</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> <b>[exec.queries.get_stop_token]</b></span></a>
        <li><a href="#spec-execution.queries.get_scheduler"><span class="secno">11.3.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> <b>[exec.queries.get_scheduler]</b></span></a>
        <li><a href="#spec-execution.queries.get_delegatee_scheduler"><span class="secno">11.3.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> <b>[exec.queries.get_delegatee_scheduler]</b></span></a>
        <li><a href="#spec-execution.queries.get_forward_progress_guarantee"><span class="secno">11.3.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> <b>[exec.queries.get_forward_progress_guarantee]</b></span></a>
        <li>
         <a href="#spec-execution.queries.execute_may_block_caller"><span class="secno">11.3.8</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> <b>[exec.queries.execute_may_block_caller]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.queries.get_completion_scheduler"><span class="secno">11.3.8.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> <b>[exec.queries.completion_scheduler]</b></span></a>
         </ol>
       </ol>
      <li>
       <a href="#spec-execution.environment"><span class="secno">11.4</span> <span class="content">Execution environments <b>[exec.env]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.environment.get_env"><span class="secno">11.4.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-></code> <b>[exec.get_env]</b></span></a>
       </ol>
      <li><a href="#spec-execution.schedulers"><span class="secno">11.5</span> <span class="content">Schedulers <b>[exec.sched] </b></span></a>
      <li>
       <a href="#spec-execution.receivers"><span class="secno">11.6</span> <span class="content">Receivers <b>[exec.recv]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.receivers.set_value"><span class="secno">11.6.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> <b>[exec.set_value]</b></span></a>
        <li><a href="#spec-execution.receivers.set_error"><span class="secno">11.6.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> <b>[exec.set_error]</b></span></a>
        <li><a href="#spec-execution.receivers.set_stopped"><span class="secno">11.6.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> <b>[exec.set_stopped]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.op_state"><span class="secno">11.7</span> <span class="content">Operation states <b>[exec.op_state]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.op_state.start"><span class="secno">11.7.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> <b>[exec.op_state.start]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.senders"><span class="secno">11.8</span> <span class="content">Senders <b>[exec.snd]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.environment.get_attrs"><span class="secno">11.8.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-></code> <b>[exec.get_attrs]</b></span></a>
        <li><a href="#spec-execution.environment.snd_concepts"><span class="secno">11.8.2</span> <span class="content">Sender concepts <b>[exec.snd_concepts]</b></span></a>
        <li>
         <a href="#spec-exec.sndtraits"><span class="secno">11.8.3</span> <span class="content">Completion signatures <b>[exec.sndtraits]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-exec.complsigs"><span class="secno">11.8.3.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures_of_t</c-></code> <b>[exec.complsigs]</b></span></a>
         </ol>
        <li><a href="#spec-execution.senders.connect"><span class="secno">11.8.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> <b>[exec.connect]</b></span></a>
        <li>
         <a href="#spec-execution.senders.factories"><span class="secno">11.8.5</span> <span class="content">Sender factories <b>[exec.factories]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.factories.general"><span class="secno">11.8.5.1</span> <span class="content">General <b>[exec.factories.general]</b></span></a>
          <li><a href="#spec-execution.senders.schedule"><span class="secno">11.8.5.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> <b>[exec.schedule]</b></span></a>
          <li><a href="#spec-execution.senders.just"><span class="secno">11.8.5.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> <b>[exec.just]</b></span></a>
          <li><a href="#spec-execution.senders.transfer_just"><span class="secno">11.8.5.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code> <b>[exec.transfer_just]</b></span></a>
          <li><a href="#spec-execution.senders.read"><span class="secno">11.8.5.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> <b>[exec.read]</b></span></a>
         </ol>
        <li>
         <a href="#spec-execution.senders.adapt"><span class="secno">11.8.6</span> <span class="content">Sender adaptors <b>[exec.adapt]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.adapt.general"><span class="secno">11.8.6.1</span> <span class="content">General <b>[exec.adapt.general]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.objects"><span class="secno">11.8.6.2</span> <span class="content">Sender adaptor closure objects <b>[exec.adapt.objects]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.on"><span class="secno">11.8.6.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> <b>[exec.on]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.transfer"><span class="secno">11.8.6.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> <b>[exec.transfer]</b></span></a>
          <li><a href="#spec-execution.senders.adaptors.schedule_from"><span class="secno">11.8.6.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> <b>[exec.schedule_from]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.then"><span class="secno">11.8.6.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> <b>[exec.then]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.upon_error"><span class="secno">11.8.6.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code> <b>[exec.upon_error]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.upon_stopped"><span class="secno">11.8.6.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> <b>[exec.upon_stopped]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.let"><span class="secno">11.8.6.9</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <b>[exec.let]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.bulk"><span class="secno">11.8.6.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> <b>[exec.bulk]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.split"><span class="secno">11.8.6.11</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> <b>[exec.split]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.when_all"><span class="secno">11.8.6.12</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> <b>[exec.when_all]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.transfer_when_all"><span class="secno">11.8.6.13</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code> <b>[exec.transfer_when_all]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.into_variant"><span class="secno">11.8.6.14</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> <b>[exec.into_variant]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.stopped_as_optional"><span class="secno">11.8.6.15</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> <b>[exec.stopped_as_optional]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.stopped_as_error"><span class="secno">11.8.6.16</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> <b>[exec.stopped_as_error]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.ensure_started"><span class="secno">11.8.6.17</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> <b>[exec.ensure_started]</b></span></a>
         </ol>
        <li>
         <a href="#spec-execution.senders.consumers"><span class="secno">11.8.7</span> <span class="content">Sender consumers <b>[exec.consumers]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.consumers.start_detached"><span class="secno">11.8.7.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> <b>[exec.start_detached]</b></span></a>
          <li><a href="#spec-execution.senders.consumers.sync_wait"><span class="secno">11.8.7.2</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> <b>[exec.sync_wait]</b></span></a>
         </ol>
       </ol>
      <li><a href="#spec-execution.execute"><span class="secno">11.9</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> <b>[exec.execute]</b></span></a>
      <li>
       <a href="#spec-execution.snd_rec_utils"><span class="secno">11.10</span> <span class="content">Sender/receiver utilities <b>[exec.utils]</b></span></a>
       <ol class="toc">
        <li>
         <a href="#spec-execution.snd_rec_utils.rcvr_adptr"><span class="secno">11.10.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> <b>[exec.utils.rcvr_adptr]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"><span class="secno">11.10.1.1</span> <span class="content">Non-member functions <b>[exec.utils.rcvr_adptr.nonmembers]</b></span></a>
         </ol>
        <li><a href="#spec-execution.snd_rec_utils.completion_sigs"><span class="secno">11.10.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> <b>[exec.utils.cmplsigs]</b></span></a>
        <li><a href="#spec-execution.snd_rec_utils.make_completion_sigs"><span class="secno">11.10.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>make_completion_signatures</c-></code> <b>[exec.utils.mkcmplsigs]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.contexts"><span class="secno">11.11</span> <span class="content">Execution contexts <b>[exec.ctx]</b></span></a>
       <ol class="toc">
        <li>
         <a href="#spec-execution.contexts.run_loop"><span class="secno">11.11.1</span> <span class="content"><code class="highlight"><c- n>run_loop</c-></code> <b>[exec.run_loop]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.contexts.run_loop.types"><span class="secno">11.11.1.1</span> <span class="content">Associated types <b>[exec.run_loop.types]</b></span></a>
          <li><a href="#spec-execution.contexts.run_loop.ctor"><span class="secno">11.11.1.2</span> <span class="content">Constructor and destructor <b>[exec.run_loop.ctor]</b></span></a>
          <li><a href="#spec-execution.contexts.run_loop.members"><span class="secno">11.11.1.3</span> <span class="content">Member functions <b>[exec.run_loop.members]</b></span></a>
         </ol>
       </ol>
      <li>
       <a href="#spec-execution.coro_utils"><span class="secno">11.12</span> <span class="content">Coroutine utilities <b>[exec.coro_utils]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.coro_utils.as_awaitable"><span class="secno">11.12.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>as_awaitable</c-></code> <b>[exec.as_awaitable]</b></span></a>
        <li><a href="#spec-execution.coro_utils.with_awaitable_senders"><span class="secno">11.12.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> <b>[exec.with_awaitable_senders]</b></span></a>
       </ol>
     </ol>
    <li>
     <a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
     </ol>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>This paper proposes a self-contained design for a Standard C++ framework for managing asynchronous execution on generic execution contexts. It is based on the ideas in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> and its companion papers.</p>
   <h3 class="heading settled" data-level="1.1" id="motivation"><span class="secno">1.1. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h3>
   <p>Today, C++ software is increasingly asynchronous and parallel, a trend that is likely to only continue going forward.
Asynchrony and parallelism appears everywhere, from processor hardware interfaces, to networking, to file I/O, to GUIs, to accelerators.
Every C++ domain and every platform needs to deal with asynchrony and parallelism, from scientific computing to video games to financial services, from the smallest mobile devices to your laptop to GPUs in the world’s fastest supercomputer.</p>
   <p>While the C++ Standard Library has a rich set of concurrency primitives (<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>atomic</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>mutex</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>counting_semaphore</c-></code>, etc) and lower level building blocks (<code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code>, etc), we lack a Standard vocabulary and framework for asynchrony and parallelism that C++ programmers desperately need. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>async</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>future</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>promise</c-></code>, C++11’s intended exposure for asynchrony, is inefficient, hard to use correctly, and severely lacking in genericity, making it unusable in many contexts.
We introduced parallel algorithms to the C++ Standard Library in C++17, and while they are an excellent start, they are all inherently synchronous and not composable.</p>
   <p>This paper proposes a Standard C++ model for asynchrony, based around three key abstractions: schedulers, senders, and receivers, and a set of customizable asynchronous algorithms.</p>
   <h3 class="heading settled" data-level="1.2" id="priorities"><span class="secno">1.2. </span><span class="content">Priorities</span><a class="self-link" href="#priorities"></a></h3>
   <ul>
    <li data-md>
     <p>Be composable and generic, allowing users to write code that can be used with many different types of execution contexts.</p>
    <li data-md>
     <p>Encapsulate common asynchronous patterns in customizable and reusable algorithms, so users don’t have to invent things themselves.</p>
    <li data-md>
     <p>Make it easy to be correct by construction.</p>
    <li data-md>
     <p>Support the diversity of execution contexts and execution agents, because not all execution agents are created equal; some are less capable than others, but not less important.</p>
    <li data-md>
     <p>Allow everything to be customized by an execution context, including transfer to other execution contexts, but don’t require that execution contexts customize everything.</p>
    <li data-md>
     <p>Care about all reasonable use cases, domains and platforms.</p>
    <li data-md>
     <p>Errors must be propagated, but error handling must not present a burden.</p>
    <li data-md>
     <p>Support cancellation, which is not an error.</p>
    <li data-md>
     <p>Have clear and concise answers for where things execute.</p>
    <li data-md>
     <p>Be able to manage and terminate the lifetimes of objects asynchronously.</p>
   </ul>
   <h3 class="heading settled" data-level="1.3" id="example-end-user"><span class="secno">1.3. </span><span class="content">Examples: End User</span><a class="self-link" href="#example-end-user"></a></h3>
   <p>In this section we demonstrate the end-user experience of asynchronous programming directly with the sender algorithms presented in this paper. See <a href="#design-sender-factories">§ 4.20 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.21 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.22 User-facing sender consumers</a> for short explanations of the algorithms used in these code examples.</p>
   <h4 class="heading settled" data-level="1.3.1" id="example-hello-world"><span class="secno">1.3.1. </span><span class="content">Hello world</span><a class="self-link" href="#example-hello-world"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->                                 <c- c1>// 1</c->

<c- n>sender</c-> <c- k>auto</c-> <c- n>begin</c-> <c- o>=</c-> <c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->                                            <c- c1>// 2</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>hi</c-> <c- o>=</c-> <c- n>then</c-><c- p>(</c-><c- n>begin</c-><c- p>,</c-> <c- p>[]{</c->                                              <c- c1>// 3</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Hello world! Have an int."</c-><c- p>;</c->                                 <c- c1>// 3</c->
    <c- k>return</c-> <c- mi>13</c-><c- p>;</c->                                                                <c- c1>// 3</c->
<c- p>});</c->                                                                           <c- c1>// 3</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>add_42</c-> <c- o>=</c-> <c- n>then</c-><c- p>(</c-><c- n>hi</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>arg</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>arg</c-> <c- o>+</c-> <c- mi>42</c-><c- p>;</c-> <c- p>});</c->              <c- c1>// 4</c->

<c- k>auto</c-> <c- p>[</c-><c- n>i</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>add_42</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->                            <c- c1>// 5</c->
</pre>
   <p>This example demonstrates the basics of schedulers, senders, and receivers:</p>
   <ol>
    <li data-md>
     <p>First we need to get a scheduler from somewhere, such as a thread pool. A scheduler is a lightweight handle to an execution resource.</p>
    <li data-md>
     <p>To start a chain of work on a scheduler, we call <a href="#design-sender-factory-schedule">§ 4.20.1 execution::schedule</a>, which returns a sender that completes on the scheduler. A sender describes asynchronous work and sends a signal (value, error, or stopped) to some recipient(s) when that work completes.</p>
    <li data-md>
     <p>We use sender algorithms to produce senders and compose asynchronous work. <a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a> is a sender adaptor that takes an input sender and a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, and calls the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> on the signal sent by the input sender. The sender returned by <code class="highlight"><c- n>then</c-></code> sends the result of that invocation. In this case, the input sender came from <code class="highlight"><c- n>schedule</c-></code>, so its <code class="highlight"><c- b>void</c-></code>, meaning it won’t send us a value, so our <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> takes no parameters. But we return an <code class="highlight"><c- b>int</c-></code>, which will be sent to the next recipient.</p>
    <li data-md>
     <p>Now, we add another operation to the chain, again using <a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a>. This time, we get sent a value - the <code class="highlight"><c- b>int</c-></code> from the previous step. We add <code class="highlight"><c- mi>42</c-></code> to it, and then return the result.</p>
    <li data-md>
     <p>Finally, we’re ready to submit the entire asynchronous pipeline and wait for its completion. Everything up until this point has been completely asynchronous; the work may not have even started yet. To ensure the work has started and then block pending its completion, we use <a href="#design-sender-consumer-sync_wait">§ 4.22.2 this_thread::sync_wait</a>, which will either return a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- p>...</c-><c- o>>></c-></code> with the value sent by the last sender, or an empty <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> if the last sender sent a stopped signal, or it throws an exception if the last sender sent an error.</p>
   </ol>
   <h4 class="heading settled" data-level="1.3.2" id="example-async-inclusive-scan"><span class="secno">1.3.2. </span><span class="content">Asynchronous inclusive scan</span><a class="self-link" href="#example-async-inclusive-scan"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>sender</c-> <c- k>auto</c-> <c- n>async_inclusive_scan</c-><c- p>(</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-><c- p>,</c->                          <c- c1>// 2</c->
                                 <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>double</c-><c- o>></c-> <c- n>input</c-><c- p>,</c->               <c- c1>// 1</c->
                                 <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-> <c- n>output</c-><c- p>,</c->                    <c- c1>// 1</c->
                                 <c- b>double</c-> <c- n>init</c-><c- p>,</c->                                 <c- c1>// 1</c->
                                 <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>tile_count</c-><c- p>)</c->                      <c- c1>// 3</c->
<c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- k>const</c-> <c- n>tile_size</c-> <c- o>=</c-> <c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>()</c-> <c- o>+</c-> <c- n>tile_count</c-> <c- o>-</c-> <c- mi>1</c-><c- p>)</c-> <c- o>/</c-> <c- n>tile_count</c-><c- p>;</c->

  <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-> <c- n>partials</c-><c- p>(</c-><c- n>tile_count</c-> <c- o>+</c-> <c- mi>1</c-><c- p>);</c->                               <c- c1>// 4</c->
  <c- n>partials</c-><c- p>[</c-><c- mi>0</c-><c- p>]</c-> <c- o>=</c-> <c- n>init</c-><c- p>;</c->                                                         <c- c1>// 4</c->

  <c- k>return</c-> <c- n>transfer_just</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>partials</c-><c- p>))</c->                              <c- c1>// 5</c->
       <c- o>|</c-> <c- n>bulk</c-><c- p>(</c-><c- n>tile_count</c-><c- p>,</c->                                                     <c- c1>// 6</c->
           <c- p>[</c-><c- o>=</c-><c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->                <c- c1>// 7</c->
             <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>i</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>;</c->                                      <c- c1>// 8</c->
             <c- k>auto</c-> <c- n>end</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>min</c-><c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>(),</c-> <c- p>(</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>)</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>);</c->        <c- c1>// 8</c->
             <c- n>partials</c-><c- p>[</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>]</c-> <c- o>=</c-> <c- o>*--</c-><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>,</c->   <c- c1>// 9</c->
                                                      <c- n>begin</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-> <c- o>+</c-> <c- n>end</c-><c- p>,</c->     <c- c1>// 9</c->
                                                      <c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>);</c-> <c- c1>// 9</c->
           <c- p>})</c->                                                                 <c- c1>// 10</c->
       <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                                <c- c1>// 11</c->
           <c- p>[](</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->
             <c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>partials</c-><c- p>),</c-> <c- n>end</c-><c- p>(</c-><c- n>partials</c-><c- p>),</c->              <c- c1>// 12</c->
                                 <c- n>begin</c-><c- p>(</c-><c- n>partials</c-><c- p>));</c->                            <c- c1>// 12</c->
             <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>partials</c-><c- p>);</c->                                      <c- c1>// 13</c->
           <c- p>})</c->
       <c- o>|</c-> <c- n>bulk</c-><c- p>(</c-><c- n>tile_count</c-><c- p>,</c->                                                     <c- c1>// 14</c->
           <c- p>[</c-><c- o>=</c-><c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->                <c- c1>// 14</c->
             <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>i</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>;</c->                                      <c- c1>// 14</c->
             <c- k>auto</c-> <c- n>end</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>min</c-><c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>(),</c-> <c- p>(</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>)</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>);</c->        <c- c1>// 14</c->
             <c- n>std</c-><c- o>::</c-><c- n>for_each</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>,</c-> <c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>end</c-><c- p>,</c->        <c- c1>// 14</c->
               <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-> <c- p>(</c-><c- b>double</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>=</c-> <c- n>partials</c-><c- p>[</c-><c- n>i</c-><c- p>]</c-> <c- o>+</c-> <c- n>e</c-><c- p>;</c-> <c- p>}</c->                       <c- c1>// 14</c->
             <c- p>);</c->
           <c- p>})</c->
       <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                                <c- c1>// 15</c->
           <c- p>[</c-><c- o>=</c-><c- p>](</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->                              <c- c1>// 15</c->
             <c- k>return</c-> <c- n>output</c-><c- p>;</c->                                                   <c- c1>// 15</c->
           <c- p>});</c->                                                                <c- c1>// 15</c->
<c- p>}</c->
</pre>
   <p>This example builds an asynchronous computation of an inclusive scan:</p>
   <ol>
    <li data-md>
     <p>It scans a sequence of <code class="highlight"><c- b>double</c-></code>s (represented as the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>double</c-><c- o>></c-></code> <code class="highlight"><c- n>input</c-></code>) and stores the result in another sequence of <code class="highlight"><c- b>double</c-></code>s (represented as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-></code> <code class="highlight"><c- n>output</c-></code>).</p>
    <li data-md>
     <p>It takes a scheduler, which specifies what execution context the scan should be launched on.</p>
    <li data-md>
     <p>It also takes a <code class="highlight"><c- n>tile_count</c-></code> parameter that controls the number of execution agents that will be spawned.</p>
    <li data-md>
     <p>First we need to allocate temporary storage needed for the algorithm, which we’ll do with a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code>, <code class="highlight"><c- n>partials</c-></code>. We need one <code class="highlight"><c- b>double</c-></code> of temporary storage for each execution agent we create.</p>
    <li data-md>
     <p>Next we’ll create our initial sender with <a href="#design-sender-factory-transfer_just">§ 4.20.3 execution::transfer_just</a>. This sender will send the temporary storage, which we’ve moved into the sender. The sender has a completion scheduler of <code class="highlight"><c- n>sch</c-></code>, which means the next item in the chain will use <code class="highlight"><c- n>sch</c-></code>.</p>
    <li data-md>
     <p>Senders and sender adaptors support composition via <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>, similar to C++ ranges. We’ll use <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> to attach the next piece of work, which will spawn <code class="highlight"><c- n>tile_count</c-></code> execution agents using <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a> (see <a href="#design-pipeable">§ 4.13 Most sender adaptors are pipeable</a> for details).</p>
    <li data-md>
     <p>Each agent will call a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, passing it two arguments. The first is the agent’s index (<code class="highlight"><c- n>i</c-></code>) in the <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a> operation, in this case a unique integer in <code class="highlight"><c- p>[</c-><c- mi>0</c-><c- p>,</c-> <c- n>tile_count</c-><c- p>)</c-></code>. The second argument is what the input sender sent - the temporary storage.</p>
    <li data-md>
     <p>We start by computing the start and end of the range of input and output elements that this agent is responsible for, based on our agent index.</p>
    <li data-md>
     <p>Then we do a sequential <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-></code> over our elements. We store the scan result for our last element, which is the sum of all of our elements, in our temporary storage <code class="highlight"><c- n>partials</c-></code>.</p>
    <li data-md>
     <p>After all computation in that initial <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a> pass has completed, every one of the spawned execution agents will have written the sum of its elements into its slot in <code class="highlight"><c- n>partials</c-></code>.</p>
    <li data-md>
     <p>Now we need to scan all of the values in <code class="highlight"><c- n>partials</c-></code>. We’ll do that with a single execution agent which will execute after the <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a> completes. We create that execution agent with <a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a>.</p>
    <li data-md>
     <p><a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a> takes an input sender and an <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> and calls the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> with the value sent by the input sender. Inside our <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, we call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-></code> on <code class="highlight"><c- n>partials</c-></code>, which the input senders will send to us.</p>
    <li data-md>
     <p>Then we return <code class="highlight"><c- n>partials</c-></code>, which the next phase will need.</p>
    <li data-md>
     <p>Finally we do another <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a> of the same shape as before. In this <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a>, we will use the scanned values in <code class="highlight"><c- n>partials</c-></code> to integrate the sums from other tiles into our elements, completing the inclusive scan.</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_inclusive_scan</c-></code> returns a sender that sends the output <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-></code>. A consumer of the algorithm can chain additional work that uses the scan result. At the point at which <code class="highlight"><c- n>async_inclusive_scan</c-></code> returns, the computation may not have completed. In fact, it may not have even started.</p>
   </ol>
   <h4 class="heading settled" data-level="1.3.3" id="example-async-dynamically-sized-read"><span class="secno">1.3.3. </span><span class="content">Asynchronous dynamically-sized read</span><a class="self-link" href="#example-async-dynamically-sized-read"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>sender_of</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-><c- p>)</c-><c- o>></c-> <c- k>auto</c-> <c- n>async_read</c-><c- p>(</c->                          <c- c1>// 1</c->
    <c- n>sender_of</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>></c-><c- p>)</c-><c- o>></c-> <c- k>auto</c-> <c- n>buffer</c-><c- p>,</c->                 <c- c1>// 1</c->
    <c- k>auto</c-> <c- n>handle</c-><c- p>);</c->                                                             <c- c1>// 1</c->

<c- k>struct</c-> <c- nc>dynamic_buffer</c-> <c- p>{</c->                                                       <c- c1>// 3</c->
  <c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-> <c- n>data</c-><c- p>;</c->                                          <c- c1>// 3</c->
  <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-><c- p>;</c->                                                           <c- c1>// 3</c->
<c- p>};</c->                                                                            <c- c1>// 3</c->

<c- n>sender_of</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>dynamic_buffer</c-><c- p>)</c-><c- o>></c-> <c- k>auto</c-> <c- n>async_read_array</c-><c- p>(</c-><c- k>auto</c-> <c- n>handle</c-><c- p>)</c-> <c- p>{</c->   <c- c1>// 2</c->
  <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>dynamic_buffer</c-><c- p>{})</c->                                               <c- c1>// 4</c->
       <c- o>|</c-> <c- n>let_value</c-><c- p>([</c-><c- n>handle</c-><c- p>]</c-> <c- p>(</c-><c- n>dynamic_buffer</c-><c- o>&amp;</c-> <c- n>buf</c-><c- p>)</c-> <c- p>{</c->                           <c- c1>// 5</c->
           <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>as_writeable_bytes</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- p>(</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>,</c-> <c- mi>1</c-><c- p>))</c->       <c- c1>// 6</c->
                <c- o>|</c-> <c- n>async_read</c-><c- p>(</c-><c- n>handle</c-><c- p>)</c->                                          <c- c1>// 7</c->
                <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                       <c- c1>// 8</c->
                    <c- p>[</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->                         <c- c1>// 9</c->
                      <c- n>assert</c-><c- p>(</c-><c- n>bytes_read</c-> <c- o>==</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>));</c->                 <c- c1>// 10</c->
                      <c- n>buf</c-><c- p>.</c-><c- n>data</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>make_unique</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->     <c- c1>// 11</c->
                      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>data</c-><c- p>.</c-><c- n>get</c-><c- p>(),</c-> <c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->             <c- c1>// 12</c->
                    <c- p>})</c->
                <c- o>|</c-> <c- n>async_read</c-><c- p>(</c-><c- n>handle</c-><c- p>)</c->                                          <c- c1>// 13</c->
                <c- o>|</c-> <c- n>then</c-><c- p>(</c->
                    <c- p>[</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->
                      <c- n>assert</c-><c- p>(</c-><c- n>bytes_read</c-> <c- o>==</c-> <c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->                         <c- c1>// 14</c->
                      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>buf</c-><c- p>);</c->                                  <c- c1>// 15</c->
                    <c- p>});</c->
       <c- p>});</c->
<c- p>}</c->
</pre>
   <p>This example demonstrates a common asynchronous I/O pattern - reading a payload of a dynamic size by first reading the size, then reading the number of bytes specified by the size:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>async_read</c-></code> is a pipeable sender adaptor. It’s a customization point object, but this is what it’s call signature looks like. It takes a sender parameter which must send an input buffer in the form of a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>></c-></code>, and a handle to an I/O context. It will asynchronously read into the input buffer, up to the size of the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-></code>. It returns a sender which will send the number of bytes read once the read completes.</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_read_array</c-></code> takes an I/O handle and reads a size from it, and then a buffer of that many bytes. It returns a sender that sends a <code class="highlight"><c- n>dynamic_buffer</c-></code> object that owns the data that was sent.</p>
    <li data-md>
     <p><code class="highlight"><c- n>dynamic_buffer</c-></code> is an aggregate struct that contains a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-></code> and a size.</p>
    <li data-md>
     <p>The first thing we do inside of <code class="highlight"><c- n>async_read_array</c-></code> is create a sender that will send a new, empty <code class="highlight"><c- n>dynamic_array</c-></code> object using <a href="#design-sender-factory-just">§ 4.20.2 execution::just</a>. We can attach more work to the pipeline using <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> composition (see <a href="#design-pipeable">§ 4.13 Most sender adaptors are pipeable</a> for details).</p>
    <li data-md>
     <p>We need the lifetime of this <code class="highlight"><c- n>dynamic_array</c-></code> object to last for the entire pipeline. So, we use <code class="highlight"><c- n>let_value</c-></code>, which takes an input sender and a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that must return a sender itself (see <a href="#design-sender-adaptor-let">§ 4.21.4 execution::let_*</a> for details). <code class="highlight"><c- n>let_value</c-></code> sends the value from the input sender to the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>. Critically, the lifetime of the sent object will last until the sender returned by the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> completes.</p>
    <li data-md>
     <p>Inside of the <code class="highlight"><c- n>let_value</c-></code> <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, we have the rest of our logic. First, we want to initiate an <code class="highlight"><c- n>async_read</c-></code> of the buffer size. To do that, we need to send a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-></code> pointing to <code class="highlight"><c- n>buf</c-><c- p>.</c-><c- n>size</c-></code>. We can do that with <a href="#design-sender-factory-just">§ 4.20.2 execution::just</a>.</p>
    <li data-md>
     <p>We chain the <code class="highlight"><c- n>async_read</c-></code> onto the <a href="#design-sender-factory-just">§ 4.20.2 execution::just</a> sender with <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>.</p>
    <li data-md>
     <p>Next, we pipe a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that will be invoked after the <code class="highlight"><c- n>async_read</c-></code> completes using <a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a>.</p>
    <li data-md>
     <p>That <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> gets sent the number of bytes read.</p>
    <li data-md>
     <p>We need to check that the number of bytes read is what we expected.</p>
    <li data-md>
     <p>Now that we have read the size of the data, we can allocate storage for it.</p>
    <li data-md>
     <p>We return a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>></c-></code> to the storage for the data from the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>. This will be sent to the next recipient in the pipeline.</p>
    <li data-md>
     <p>And that recipient will be another <code class="highlight"><c- n>async_read</c-></code>, which will read the data.</p>
    <li data-md>
     <p>Once the data has been read, in another <a href="#design-sender-adaptor-then">§ 4.21.2 execution::then</a>, we confirm that we read the right number of bytes.</p>
    <li data-md>
     <p>Finally, we move out of and return our <code class="highlight"><c- n>dynamic_buffer</c-></code> object. It will get sent by the sender returned by <code class="highlight"><c- n>async_read_array</c-></code>. We can attach more things to that sender to use the data in the buffer.</p>
   </ol>
   <h3 class="heading settled" data-level="1.4" id="example-async-windows-socket-recv"><span class="secno">1.4. </span><span class="content">Asynchronous Windows socket <code class="highlight"><c- n>recv</c-></code></span><a class="self-link" href="#example-async-windows-socket-recv"></a></h3>
   <p>To get a better feel for how this interface might be used by low-level operations see this example implementation
of a cancellable <code class="highlight"><c- n>async_recv</c-><c- p>()</c-></code> operation for a Windows Socket.</p>
<pre class="language-c++ highlight"><c- k>struct</c-> <c- nc>operation_base</c-> <c- o>:</c-> <c- n>WSAOVERALAPPED</c-> <c- p>{</c->
    <c- n>using</c-> <c- n>completion_fn</c-> <c- o>=</c-> <c- b>void</c-><c- p>(</c-><c- n>operation_base</c-><c- o>*</c-> <c- n>op</c-><c- p>,</c-> <c- n>DWORD</c-> <c- n>bytesTransferred</c-><c- p>,</c-> <c- b>int</c-> <c- n>errorCode</c-><c- p>)</c-> <c- n>noexcept</c-><c- p>;</c->

    <c- c1>// Assume IOCP event loop will call this when this OVERLAPPED structure is dequeued.</c->
    <c- n>completion_fn</c-><c- o>*</c-> <c- n>completed</c-><c- p>;</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>Receiver</c-><c- o>></c->
<c- k>struct</c-> <c- nc>recv_op</c-> <c- o>:</c-> <c- n>operation_base</c-> <c- p>{</c->
    <c- n>recv_op</c-><c- p>(</c-><c- n>SOCKET</c-> <c- n>s</c-><c- p>,</c-> <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>len</c-><c- p>,</c-> <c- n>Receiver</c-> <c- n>r</c-><c- p>)</c->
    <c- o>:</c-> <c- n>receiver</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>))</c->
    <c- p>,</c-> <c- n>sock</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-> <c- p>{</c->
        <c- n>this</c-><c- o>-></c-><c- n>Internal</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>InternalHigh</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>Offset</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>OffsetHigh</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>hEvent</c-> <c- o>=</c-> NULL<c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>completed</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>recv_op</c-><c- o>::</c-><c- n>on_complete</c-><c- p>;</c->
        <c- n>buffer</c-><c- p>.</c-><c- n>len</c-> <c- o>=</c-> <c- n>len</c-><c- p>;</c->
        <c- n>buffer</c-><c- p>.</c-><c- n>buf</c-> <c- o>=</c-> <c- n>static_cast</c-><c- o>&lt;</c-><c- n>CHAR</c-><c- o>*></c-><c- p>(</c-><c- n>data</c-><c- p>);</c->
    <c- p>}</c->

    <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>tag_t</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- o>></c-><c- p>,</c-> <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- c1>// Avoid even calling WSARecv() if operation already cancelled</c->
        <c- k>auto</c-> <c- n>st</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c->
          <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
        <c- k>if</c-> <c- p>(</c-><c- n>st</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>())</c-> <c- p>{</c->
            <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
            <c- k>return</c-><c- p>;</c->
        <c- p>}</c->

        <c- c1>// Store and cache result here in case it changes during execution</c->
        <c- k>const</c-> <c- b>bool</c-> <c- n>stopPossible</c-> <c- o>=</c-> <c- n>st</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>();</c->
        <c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>stopPossible</c-><c- p>)</c-> <c- p>{</c->
            <c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>store</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_relaxed</c-><c- p>);</c->
        <c- p>}</c->

        <c- c1>// Launch the operation</c->
        <c- n>DWORD</c-> <c- n>bytesTransferred</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>DWORD</c-> <c- n>flags</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- b>int</c-> <c- n>result</c-> <c- o>=</c-> <c- n>WSARecv</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>self</c-><c- p>.</c-><c- n>buffer</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>bytesTransferred</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>flags</c-><c- p>,</c->
                             <c- n>static_cast</c-><c- o>&lt;</c-><c- n>WSAOVERLAPPED</c-><c- o>*></c-><c- p>(</c-><c- o>&amp;</c-><c- n>self</c-><c- p>),</c-> NULL<c- p>);</c->
        <c- k>if</c-> <c- p>(</c-><c- n>result</c-> <c- o>==</c-> <c- n>SOCKET_ERROR</c-><c- p>)</c-> <c- p>{</c->
            <c- b>int</c-> <c- n>errorCode</c-> <c- o>=</c-> <c- n>WSAGetLastError</c-><c- p>();</c->
            <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>!=</c-> <c- n>WSA_IO_PENDING</c-><c- p>))</c-> <c- p>{</c->
                <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>==</c-> <c- n>WSA_OPERATION_ABORTED</c-><c- p>)</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
                <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c->
                                              <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
                <c- p>}</c->
                <c- k>return</c-><c- p>;</c->
            <c- p>}</c->
        <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
            <c- c1>// Completed synchronously (assuming FILE_SKIP_COMPLETION_PORT_ON_SUCCESS has been set)</c->
            <c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
            <c- k>return</c-><c- p>;</c->
        <c- p>}</c->

        <c- c1>// If we get here then operation has launched successfully and will complete asynchronously.</c->
        <c- c1>// May be completing concurrently on another thread already.</c->
        <c- k>if</c-> <c- p>(</c-><c- n>stopPossible</c-><c- p>)</c-> <c- p>{</c->
            <c- c1>// Register the stop callback</c->
            <c- n>self</c-><c- p>.</c-><c- n>stopCallback</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>st</c-><c- p>),</c-> <c- n>cancel_cb</c-><c- p>{</c-><c- n>self</c-><c- p>});</c->

            <c- c1>// Mark as 'completed'</c->
            <c- k>if</c-> <c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>load</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>memory_order_acquire</c-><c- p>)</c-> <c- o>||</c->
                <c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>exchange</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_acq_rel</c-><c- p>))</c-> <c- p>{</c->
                <c- c1>// Already completed on another thread</c->
                <c- n>self</c-><c- p>.</c-><c- n>stopCallback</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->

                <c- n>BOOL</c-> <c- n>ok</c-> <c- o>=</c-> <c- n>WSAGetOverlappedResult</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- p>(</c-><c- n>WSAOVERLAPPED</c-><c- o>*</c-><c- p>)</c-><c- o>&amp;</c-><c- n>self</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>bytesTransferred</c-><c- p>,</c-> <c- n>FALSE</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>flags</c-><c- p>);</c->
                <c- k>if</c-> <c- p>(</c-><c- n>ok</c-><c- p>)</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
                <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                    <c- b>int</c-> <c- n>errorCode</c-> <c- o>=</c-> <c- n>WSAGetLastError</c-><c- p>();</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c->
                                              <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
                <c- p>}</c->
            <c- p>}</c->
        <c- p>}</c->
    <c- p>}</c->

    <c- k>struct</c-> <c- nc>cancel_cb</c-> <c- p>{</c->
        <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>op</c-><c- p>;</c->

        <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- n>noexcept</c-> <c- p>{</c->
            <c- n>CancelIoEx</c-><c- p>((</c-><c- n>HANDLE</c-><c- p>)</c-><c- n>op</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- p>(</c-><c- n>OVERLAPPED</c-><c- o>*</c-><c- p>)(</c-><c- n>WSAOVERLAPPED</c-><c- o>*</c-><c- p>)</c-><c- o>&amp;</c-><c- n>op</c-><c- p>);</c->
        <c- p>}</c->
    <c- p>};</c->

    <c- k>static</c-> <c- b>void</c-> <c- nf>on_complete</c-><c- p>(</c-><c- n>operation_base</c-><c- o>*</c-> <c- n>op</c-><c- p>,</c-> <c- n>DWORD</c-> <c- n>bytesTransferred</c-><c- p>,</c-> <c- b>int</c-> <c- n>errorCode</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>self</c-> <c- o>=</c-> <c- o>*</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- n>recv_op</c-><c- o>*></c-><c- p>(</c-><c- n>op</c-><c- p>);</c->

        <c- k>if</c-> <c- p>(</c-><c- n>ready</c-><c- p>.</c-><c- n>load</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>memory_order_acquire</c-><c- p>)</c-> <c- o>||</c->
            <c- n>ready</c-><c- p>.</c-><c- n>exchange</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_acq_rel</c-><c- p>))</c-> <c- p>{</c->
            <c- c1>// Unsubscribe any stop-callback so we know that CancelIoEx() is not accessing 'op'</c->
            <c- c1>// any more</c->
            <c- n>stopCallback</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->

            <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>==</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
                <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
            <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>receiver</c-><c- p>),</c->
                                          <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
            <c- p>}</c->
        <c- p>}</c->
    <c- p>}</c->

    <c- n>Receiver</c-> <c- n>receiver</c-><c- p>;</c->
    <c- n>SOCKET</c-> <c- n>sock</c-><c- p>;</c->
    <c- n>WSABUF</c-> <c- n>buffer</c-><c- p>;</c->
    <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>stop_callback_type_t</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c->
        <c- o>::</c-><c- n>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><c- n>cancel_cb</c-><c- o>>></c-> <c- n>stopCallback</c-><c- p>;</c->
    <c- n>std</c-><c- o>::</c-><c- n>atomic</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-> <c- n>ready</c-><c- p>{</c->false<c- p>};</c->
<c- p>};</c->

<c- k>struct</c-> <c- nc>recv_sender</c-> <c- p>{</c->
    <c- n>SOCKET</c-> <c- n>sock</c-><c- p>;</c->
    <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>;</c->
    <c- b>size_t</c-> <c- n>len</c-><c- p>;</c->

    <c- n>template</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>Receiver</c-><c- o>></c->
    <c- n>friend</c-> <c- n>recv_op</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>tag_t</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- o>></c->
                                        <c- k>const</c-> <c- n>recv_sender</c-><c- o>&amp;</c-> <c- n>s</c-><c- p>,</c->
                                        <c- n>Receiver</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>recv_op</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c-><c- p>{</c-><c- n>s</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- n>s</c-><c- p>.</c-><c- n>data</c-><c- p>,</c-> <c- n>s</c-><c- p>.</c-><c- n>len</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>)};</c->
    <c- p>}</c->
<c- p>};</c->

<c- n>recv_sender</c-> <c- nf>async_recv</c-><c- p>(</c-><c- n>SOCKET</c-> <c- n>s</c-><c- p>,</c-> <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>len</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>recv_sender</c-><c- p>{</c-><c- n>s</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>len</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="1.4.1" id="example-moar"><span class="secno">1.4.1. </span><span class="content">More end-user examples</span><a class="self-link" href="#example-moar"></a></h4>
   <h5 class="heading settled" data-level="1.4.1.1" id="example-sudoku"><span class="secno">1.4.1.1. </span><span class="content">Sudoku solver</span><a class="self-link" href="#example-sudoku"></a></h5>
   <p>This example comes from Kirk Shoop, who ported an example from TBB’s documentation to sender/receiver in his fork of the libunifex repo. It is a Sudoku solver that uses a configurable number of threads to explore the search space for solutions.</p>
   <p>The sender/receiver-based Sudoku solver can be found <a href="https://github.com/kirkshoop/libunifex/blob/sudoku/examples/sudoku.cpp">here</a>. Some things that are worth noting about Kirk’s solution:</p>
   <ol>
    <li data-md>
     <p>Although it schedules asychronous work onto a thread pool, and each unit of work will schedule more work, its use of structured concurrency patterns make reference counting unnecessary. The solution does not make use of <code class="highlight"><c- n>shared_ptr</c-></code>.</p>
    <li data-md>
     <p>In addition to eliminating the need for reference counting, the use of structured concurrency makes it easy to ensure that resources are cleaned up on all code paths. In contrast, the TBB example that inspired this one <a href="https://github.com/oneapi-src/oneTBB/issues/568">leaks memory</a>.</p>
   </ol>
   <p>For comparison, the TBB-based Sudoku solver can be found <a href="https://github.com/oneapi-src/oneTBB/blob/40a9a1060069d37d5f66912c6ee4cf165144774b/examples/task_group/sudoku/sudoku.cpp">here</a>.</p>
   <h5 class="heading settled" data-level="1.4.1.2" id="example-file-copy"><span class="secno">1.4.1.2. </span><span class="content">File copy</span><a class="self-link" href="#example-file-copy"></a></h5>
   <p>This example also comes from Kirk Shoop which uses sender/receiver to recursively copy the files a directory tree. It demonstrates how sender/receiver can be used to do IO, using a scheduler that schedules work on Linux’s io_uring.</p>
   <p>As with the Sudoku example, this example obviates the need for reference counting by employing structured concurrency. It uses iteration with an upper limit to avoid having too many open file handles.</p>
   <p>You can find the example <a href="https://github.com/kirkshoop/libunifex/blob/filecopy/examples/file_copy.cpp">here</a>.</p>
   <h5 class="heading settled" data-level="1.4.1.3" id="example-echo-server"><span class="secno">1.4.1.3. </span><span class="content">Echo server</span><a class="self-link" href="#example-echo-server"></a></h5>
   <p>Dietmar Kuehl has a hobby project that implements networking APIs on top of sender/receiver. He recently implemented an echo server as a demo. His echo server code can be found <a href="https://github.com/dietmarkuehl/kuhllib/blob/main/src/examples/echo_server.cpp">here</a>.</p>
   <p>Below, I show the part of the echo server code. This code is executed for each client that connects to the echo server. In a loop, it reads input from a socket and echos the input back to the same socket. All of this, including the loop, is implemented with generic async algorithms.</p>
<pre class="highlight"><c- n>outstanding</c-><c- p>.</c-><c- n>start</c-><c- p>(</c->
    <c- n>EX</c-><c- o>::</c-><c- n>repeat_effect_until</c-><c- p>(</c->
          <c- n>EX</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c->
              <c- n>NN</c-><c- o>::</c-><c- n>async_read_some</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_socket</c-><c- p>,</c->
                                  <c- n>context</c-><c- p>.</c-><c- n>scheduler</c-><c- p>(),</c->
                                  <c- n>NN</c-><c- o>::</c-><c- n>buffer</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>))</c->
        <c- o>|</c-> <c- n>EX</c-><c- o>::</c-><c- n>then</c-><c- p>([</c-><c- n>ptr</c-><c- p>](</c-><c- o>::</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>n</c-><c- p>){</c->
            <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"read='"</c-> <c- o>&lt;&lt;</c-> <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>string_view</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>,</c-> <c- n>n</c-><c- p>)</c-> <c- o>&lt;&lt;</c-> <c- s>"'</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
            <c- n>ptr</c-><c- o>-></c-><c- n>d_done</c-> <c- o>=</c-> <c- n>n</c-> <c- o>==</c-> <c- mi>0</c-><c- p>;</c->
            <c- k>return</c-> <c- n>n</c-><c- p>;</c->
        <c- p>}),</c->
          <c- p>[</c-><c- o>&amp;</c-><c- n>context</c-><c- p>,</c-> <c- n>ptr</c-><c- p>](</c-><c- o>::</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>n</c-><c- p>){</c->
            <c- k>return</c-> <c- n>NN</c-><c- o>::</c-><c- n>async_write_some</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_socket</c-><c- p>,</c->
                                        <c- n>context</c-><c- p>.</c-><c- n>scheduler</c-><c- p>(),</c->
                                        <c- n>NN</c-><c- o>::</c-><c- n>buffer</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>,</c-> <c- n>n</c-><c- p>));</c->
          <c- p>})</c->
        <c- o>|</c-> <c- n>EX</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>...){})</c->
        <c- p>,</c-> <c- p>[</c-><c- n>owner</c-> <c- o>=</c-> <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>owner</c-><c- p>)]{</c-> <c- k>return</c-> <c- n>owner</c-><c- o>-></c-><c- n>d_done</c-><c- p>;</c-> <c- p>}</c->
    <c- p>)</c->
<c- p>);</c->
</pre>
   <p>In this code, <code class="highlight"><c- n>NN</c-><c- o>::</c-><c- n>async_read_some</c-></code> and <code class="highlight"><c- n>NN</c-><c- o>::</c-><c- n>async_write_some</c-></code> are asynchronous socket-based networking APIs that return senders. <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>repeat_effect_until</c-></code>, <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>let_value</c-></code>, and <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>then</c-></code> are fully generic sender adaptor algorithms that accept and return senders.</p>
   <p>This is a good example of seamless composition of async IO functions with non-IO operations. And by composing the senders in this structured way, all the state for the composite operation -- the <code class="highlight"><c- n>repeat_effect_until</c-></code> expression and all its child operations -- is stored altogether in a single object.</p>
   <h3 class="heading settled" data-level="1.5" id="example-algorithm"><span class="secno">1.5. </span><span class="content">Examples: Algorithms</span><a class="self-link" href="#example-algorithm"></a></h3>
   <p>In this section we show a few simple sender/receiver-based algorithm implementations.</p>
   <h4 class="heading settled" data-level="1.5.1" id="example-then"><span class="secno">1.5.1. </span><span class="content"><code class="highlight"><c- n>then</c-></code></span><a class="self-link" href="#example-then"></a></h4>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>exec</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- n>class</c-> <c- n>_then_receiver</c->
    <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>,</c-> <c- n>R</c-><c- o>></c-> <c- p>{</c->
  <c- n>friend</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>;</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->

  <c- c1>// Customize set_value by invoking the callable and passing the result to the inner receiver</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- b>void</c-> <c- n>set_value</c-><c- p>(</c-><c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- n>try</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>invoke</c-><c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f_</c-><c- p>,</c-> <c- p>(</c-><c- n>As</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>as</c-><c- p>...));</c->
  <c- p>}</c-> <c- n>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>current_exception</c-><c- p>());</c->
  <c- p>}</c->

 <c- n>public</c-><c- o>:</c->
  <c- n>_then_receiver</c-><c- p>(</c-><c- n>R</c-> <c- n>r</c-><c- p>,</c-> <c- n>F</c-> <c- n>f</c-><c- p>)</c->
   <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>)}</c->
   <c- p>,</c-> <c- n>f_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>f</c-><c- p>))</c-> <c- p>{}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_then_sender</c-> <c- p>{</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->

  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- n>using</c-> <c- n>_set_value_t</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>exec</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>)</c-><c- o>></c-><c- p>;</c->

  <c- c1>// Compute the completion signatures</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>Env</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>_then_sender</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>make_completion_signatures</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c->
        <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>_set_value_t</c-><c- o>></c-><c- p>;</c->

  <c- c1>// Connect:</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>receiver</c-> <c- n>R</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_then_sender</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>>></c-> <c- p>{</c->
      <c- k>return</c-> <c- n>exec</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c->
        <c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>,</c-> <c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>{(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r</c-><c- p>,</c-> <c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>f_</c-><c- p>});</c->
  <c- p>}</c->

  <c- n>friend</c-> <c- n>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_attrs_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_then_sender</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- n>retturn</c-> <c- nf>get_attrs</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>,</c-> <c- n>F</c-> <c- n>f</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>_then_sender</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>,</c-> <c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <p>This code builds a <code class="highlight"><c- n>then</c-></code> algorithm that transforms the value(s) from the input sender
with a transformation function. The result of the transformation becomes the new value.
The other receiver functions (<code class="highlight"><c- n>set_error</c-></code> and <code class="highlight"><c- n>set_stopped</c-></code>), as well as all receiver queries,
are passed through unchanged.</p>
   <p>In detail, it does the following:</p>
   <ol>
    <li data-md>
     <p>Defines a receiver in terms of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> that aggregates
another receiver and an invocable that:</p>
     <ul>
      <li data-md>
       <p>Defines a constrained <code class="highlight"><c- n>tag_invoke</c-></code> overload for transforming the value
channel.</p>
      <li data-md>
       <p>Defines another constrained overload of <code class="highlight"><c- n>tag_invoke</c-></code> that passes all other
customizations through unchanged.</p>
     </ul>
     <p>The <code class="highlight"><c- n>tag_invoke</c-></code> overloads are actually implemented by <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code>; they dispatch either to named members, as
shown above with <code class="highlight"><c- n>_then_receiver</c-><c- o>::</c-><c- n>set_value</c-></code>, or to the adapted receiver.</p>
    <li data-md>
     <p>Defines a sender that aggregates another sender and the invocable, which defines a <code class="highlight"><c- n>tag_invoke</c-></code> customization for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> that wraps the incoming receiver in the receiver from (1) and passes it and the incoming sender to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, returning the result. It also defines a <code class="highlight"><c- n>tag_invoke</c-></code> customization of <code class="highlight"><c- n>get_completion_signatures</c-></code> that declares the sender’s completion signatures when executed within a particular environment.</p>
   </ol>
   <h4 class="heading settled" data-level="1.5.2" id="example-retry"><span class="secno">1.5.2. </span><span class="content"><code class="highlight"><c- n>retry</c-></code></span><a class="self-link" href="#example-retry"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- p>;</c->
<c- n>namespace</c-> <c- n>exec</c-> <c- o>=</c-> <c- n>execution</c-><c- p>;</c->

<c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>From</c-><c- p>,</c-> <c- n>class</c-> <c- n>To</c-><c- o>></c->
<c- n>concept</c-> <c- n>_decays_to</c-> <c- o>=</c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>From</c-><c- o>></c-><c- p>,</c-> <c- n>To</c-><c- o>></c-><c- p>;</c->

<c- c1>// _conv needed so we can emplace construct non-movable types into</c->
<c- c1>// a std::optional.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>invocable</c-> <c- n>F</c-><c- o>></c->
  <c- n>requires</c-> <c- n>is_nothrow_move_constructible_v</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_conv</c-> <c- p>{</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->
  <c- n>explicit</c-> <c- nf>_conv</c-><c- p>(</c-><c- n>F</c-> <c- n>f</c-><c- p>)</c-> <c- nl>noexcept</c-> <c- p>:</c-> <c- n>f_</c-><c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f</c-><c- p>)</c-> <c- p>{}</c->
  <c- n>operator</c-> <c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f_</c-><c- p>)();</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_op</c-><c- p>;</c->

<c- c1>// pass through all customizations except set_error, which retries the operation.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_retry_receiver</c->
  <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>></c-> <c- p>{</c->
  <c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>*</c-> <c- n>o_</c-><c- p>;</c->

  <c- n>R</c-><c- o>&amp;&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- p>(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>o_</c-><c- o>-></c-><c- n>r_</c-><c- p>;</c-> <c- p>}</c->
  <c- k>const</c-> <c- n>R</c-><c- o>&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- k>const</c-> <c- o>&amp;</c-> <c- n>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>o_</c-><c- o>-></c-><c- n>r_</c-><c- p>;</c-> <c- p>}</c->

  <c- n>explicit</c-> <c- nf>_retry_receiver</c-><c- p>(</c-><c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>*</c-> <c- n>o</c-><c- p>)</c-> <c- o>:</c-> <c- n>o_</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-> <c- p>{}</c->

  <c- b>void</c-> <c- nf>set_error</c-><c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- n>o_</c-><c- o>-></c-><c- n>_retry</c-><c- p>();</c-> <c- c1>// This causes the op to be retried</c->
  <c- p>}</c->
<c- p>};</c->

<c- c1>// Hold the nested operation state in an optional so we can</c->
<c- c1>// re-construct and re-start it if the operation fails.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_op</c-> <c- p>{</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>R</c-> <c- n>r_</c-><c- p>;</c->
  <c- n>optional</c-><c- o>&lt;</c->
      <c- n>exec</c-><c- o>::</c-><c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>>></c-> <c- n>o_</c-><c- p>;</c->

  <c- n>_op</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c-><c- o>:</c-> <c- n>s_</c-><c- p>((</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-><c- n>s</c-><c- p>),</c-> <c- n>r_</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-><c- n>r</c-><c- p>),</c-> <c- n>o_</c-><c- p>{</c-><c- n>_connect</c-><c- p>()}</c-> <c- p>{}</c->
  <c- n>_op</c-><c- p>(</c-><c- n>_op</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- n>delete</c-><c- p>;</c->

  <c- k>auto</c-> <c- n>_connect</c-><c- p>()</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>_conv</c-><c- p>{[</c-><c- n>this</c-><c- p>]</c-> <c- p>{</c->
      <c- k>return</c-> <c- n>exec</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s_</c-><c- p>,</c-> <c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>{</c-><c- n>this</c-><c- p>});</c->
    <c- p>}};</c->
  <c- p>}</c->
  <c- b>void</c-> <c- n>_retry</c-><c- p>()</c-> <c- n>noexcept</c-> <c- n>try</c-> <c- p>{</c->
    <c- n>o_</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>_connect</c-><c- p>());</c-> <c- c1>// potentially throwing</c->
    <c- n>exec</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- o>*</c-><c- n>o_</c-><c- p>);</c->
  <c- p>}</c-> <c- n>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_error</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r_</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>current_exception</c-><c- p>());</c->
  <c- p>}</c->
  <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>start_t</c-><c- p>,</c-> <c- n>_op</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- o>*</c-><c- n>o</c-><c- p>.</c-><c- n>o_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_retry_sender</c-> <c- p>{</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>explicit</c-> <c- nf>_retry_sender</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- o>:</c-> <c- n>s_</c-><c- p>((</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>)</c-> <c- p>{}</c->

  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- n>using</c-> <c- n>_value_t</c-> <c- o>=</c->
      <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>Ts</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- o>></c->
    <c- n>using</c-> <c- n>_error_t</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>;</c->

  <c- c1>// Declare the signatures with which this sender can complete</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>Env</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_retry_sender</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>make_completion_signatures</c-><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c->
        <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>_value_t</c-><c- p>,</c-> <c- n>_error_t</c-><c- o>></c-><c- p>;</c->

  <c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>receiver</c-> <c- n>R</c-><c- o>></c->
  <c- n>friend</c-> <c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_retry_sender</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>,</c-> <c- p>(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r</c-><c- p>};</c->
  <c- p>}</c->

  <c- n>friend</c-> <c- n>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_attrs_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_retry_sender</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>get_attrs</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- o>></c->
<c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>retry</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>_retry_sender</c-><c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <p>The <code class="highlight"><c- n>retry</c-></code> algorithm takes a multi-shot sender and causes it to repeat on error, passing
through values and stopped signals. Each time the input sender is restarted, a new receiver
is connected and the resulting operation state is stored in an <code class="highlight"><c- n>optional</c-></code>, which allows us
to reinitialize it multiple times.</p>
   <p>This example does the following:</p>
   <ol>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_conv</c-></code> utility that takes advantage of C++17’s guaranteed copy elision to
emplace a non-movable type in a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code>.</p>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_retry_receiver</c-></code> that holds a pointer back to the operation state. It passes
all customizations through unmodified to the inner receiver owned by the operation state
except for <code class="highlight"><c- n>set_error</c-></code>, which causes a <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> function to be called instead.</p>
    <li data-md>
     <p>Defines an operation state that aggregates the input sender and receiver, and declares
storage for the nested operation state in an <code class="highlight"><c- n>optional</c-></code>. Constructing the operation
state constructs a <code class="highlight"><c- n>_retry_receiver</c-></code> with a pointer to the (under construction) operation
state and uses it to connect to the aggregated sender.</p>
    <li data-md>
     <p>Starting the operation state dispatches to <code class="highlight"><c- n>start</c-></code> on the inner operation state.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> function reinitializes the inner operation state by connecting the sender
to a new receiver, holding a pointer back to the outer operation state as before.</p>
    <li data-md>
     <p>After reinitializing the inner operation state, <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> calls <code class="highlight"><c- n>start</c-></code> on it, causing
the failed operation to be rescheduled.</p>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_retry_sender</c-></code> that implements the <code class="highlight"><c- n>connect</c-></code> customization point to return
an operation state constructed from the passed-in sender and receiver.</p>
    <li data-md>
     <p><code class="highlight"><c- n>_retry_sender</c-></code> also implements the <code class="highlight"><c- n>get_completion_signatures</c-></code> customization point to describe the ways this sender may complete when executed in a particular execution context.</p>
   </ol>
   <h3 class="heading settled" data-level="1.6" id="example-schedulers"><span class="secno">1.6. </span><span class="content">Examples: Schedulers</span><a class="self-link" href="#example-schedulers"></a></h3>
   <p>In this section we look at some schedulers of varying complexity.</p>
   <h4 class="heading settled" data-level="1.6.1" id="example-schedulers-inline"><span class="secno">1.6.1. </span><span class="content">Inline scheduler</span><a class="self-link" href="#example-schedulers-inline"></a></h4>
<pre class="language-c++ highlight"><c- n>class</c-> <c- n>inline_scheduler</c-> <c- p>{</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>_op</c-> <c- p>{</c->
      <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>R</c-> <c- n>rec_</c-><c- p>;</c->
      <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start_t</c-><c- p>,</c-> <c- n>_op</c-><c- o>&amp;</c-> <c- n>op</c-><c- p>)</c-> <c- n>noexcept</c-> <c- n>try</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>op</c-><c- p>.</c-><c- n>rec_</c-><c- p>);</c->
      <c- p>}</c-> <c- n>catch</c-><c- p>(...)</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>op</c-><c- p>.</c-><c- n>rec_</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>current_exception</c-><c- p>());</c->
      <c- p>}</c->
    <c- p>};</c->

  <c- k>struct</c-> <c- nc>_attrs</c-> <c- p>{</c->
    <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>Tag</c-><c- o>></c->
      <c- n>friend</c-> <c- n>inline_scheduler</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>,</c-> <c- n>_attrs</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- k>return</c-> <c- p>{};</c->
      <c- p>}</c->
  <c- p>};</c->

  <c- k>struct</c-> <c- nc>_sender</c-> <c- p>{</c->
    <c- n>using</c-> <c- n>completion_signatures</c-> <c- o>=</c->
      <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c->
        <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(),</c->
        <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>;</c->

    <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- o>></c->
      <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_sender</c-><c- p>,</c-> <c- n>R</c-><c- o>&amp;&amp;</c-> <c- n>rec</c-><c- p>)</c->
        <c- n>noexcept</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>)</c->
        <c- o>-></c-> <c- n>_op</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-> <c- p>{</c->
        <c- k>return</c-> <c- p>{(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>rec</c-><c- p>};</c->
      <c- p>}</c->

    <c- n>friend</c-> <c- n>_attrs</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_attrs_t</c-><c- p>,</c-> <c- n>_sender</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
      <c- k>return</c-> <c- p>{};</c->
    <c- p>}</c->
  <c- p>};</c->

  <c- n>friend</c-> <c- n>_sender</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>inline_scheduler</c-><c- o>&amp;</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{};</c->
  <c- p>}</c->

 <c- n>public</c-><c- o>:</c->
  <c- n>inline_scheduler</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- b>bool</c-> <c- n>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>inline_scheduler</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>const</c-> <c- n>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>The inline scheduler is a trivial scheduler that completes immediately and synchronously on
the thread that calls <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> on the operation state produced by its sender.
In other words, <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><i><c- kr>inline</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>),</c-> <c- n>receiver</c-><c- p>))</c-></code> is
just a fancy way of saying <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>receiver</c-><c- p>)</c-></code>, with the exception of the fact that <code class="highlight"><c- n>start</c-></code> wants to be passed an lvalue.</p>
   <p>Although not a particularly useful scheduler, it serves to illustrate the basics of
implementing one. The <code class="highlight"><c- n>inline_scheduler</c-></code>:</p>
   <ol>
    <li data-md>
     <p>Customizes <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> to return an instance of the sender type <code class="highlight"><c- n>_sender</c-></code>.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_sender</c-></code> type models the <code class="highlight"><c- n>sender</c-></code> concept and provides the metadata
needed to describe it as a sender of no values that can send an <code class="highlight"><c- n>exception_ptr</c-></code> as an error and that never calls <code class="highlight"><c- n>set_stopped</c-></code>. This
metadata is provided with the help of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> utility.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_sender</c-></code> type customizes <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> to accept a receiver of no
values. It returns an instance of type <code class="highlight"><c- n>_op</c-></code> that holds the receiver by
value.</p>
    <li data-md>
     <p>The operation state customizes <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> to call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> on the receiver, passing any exceptions to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> as an <code class="highlight"><c- n>exception_ptr</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="1.6.2" id="example-single-thread"><span class="secno">1.6.2. </span><span class="content">Single thread scheduler</span><a class="self-link" href="#example-single-thread"></a></h4>
   <p>This example shows how to create a scheduler for an execution context that consists of a single
thread. It is implemented in terms of a lower-level execution context called <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code>.</p>
<pre class="language-c++ highlight"><c- n>class</c-> <c- n>single_thread_context</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-> <c- n>loop_</c-><c- p>;</c->
  <c- n>std</c-><c- o>::</c-><c- kr>thread</c-> <c- n>thread_</c-><c- p>;</c->

<c- n>public</c-><c- o>:</c->
  <c- n>single_thread_context</c-><c- p>()</c->
    <c- o>:</c-> <c- n>loop_</c-><c- p>()</c->
    <c- p>,</c-> <c- n>thread_</c-><c- p>([</c-><c- n>this</c-><c- p>]</c-> <c- p>{</c-> <c- n>loop_</c-><c- p>.</c-><c- n>run</c-><c- p>();</c-> <c- p>})</c->
  <c- p>{}</c->

  <c- o>~</c-><c- n>single_thread_context</c-><c- p>()</c-> <c- p>{</c->
    <c- n>loop_</c-><c- p>.</c-><c- n>finish</c-><c- p>();</c->
    <c- n>thread_</c-><c- p>.</c-><c- n>join</c-><c- p>();</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>get_scheduler</c-><c- p>()</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>loop_</c-><c- p>.</c-><c- n>get_scheduler</c-><c- p>();</c->
  <c- p>}</c->

  <c- n>std</c-><c- o>::</c-><c- kr>thread</c-><c- o>::</c-><c- n>id</c-> <c- n>get_thread_id</c-><c- p>()</c-> <c- k>const</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>thread_</c-><c- p>.</c-><c- n>get_id</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
   <p>The <code class="highlight"><c- n>single_thread_context</c-></code> owns an event loop and a thread to drive it. In the destructor, it tells the event
loop to finish up what it’s doing and then joins the thread, blocking for the event loop to drain.</p>
   <p>The interesting bits are in the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code> context implementation. It
is slightly too long to include here, so we only provide <a href="https://github.com/NVIDIA/stdexec/blob/c2cdb2a2abe2b29a34cf277728319d6ca92ec0bb/include/stdexec/execution.hpp#L3916-L4101">a reference to
it</a>,
but there is one noteworthy detail about its implementation: It uses space in
its operation states to build an intrusive linked list of work items. In
structured concurrency patterns, the operation states of nested operations
compose statically, and in an algorithm like <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, the
composite operation state lives on the stack for the duration of the operation.
The end result is that work can be scheduled onto this thread with zero
allocations.</p>
   <h3 class="heading settled" data-level="1.7" id="example-server"><span class="secno">1.7. </span><span class="content">Examples: Server theme</span><a class="self-link" href="#example-server"></a></h3>
   <p>In this section we look at some examples of how one would use senders to implement an HTTP server. The examples ignore the low-level details of the HTTP server and looks at how senders can be combined to achieve the goals of the project.</p>
   <p>General application context:</p>
   <ul>
    <li data-md>
     <p>server application that processes images</p>
    <li data-md>
     <p>execution contexts:</p>
     <ul>
      <li data-md>
       <p>1 dedicated thread for network I/O</p>
      <li data-md>
       <p>N worker threads used for CPU-intensive work</p>
      <li data-md>
       <p>M threads for auxiliary I/O</p>
      <li data-md>
       <p>optional GPU context that may be used on some types of servers</p>
     </ul>
    <li data-md>
     <p>all parts of the applications can be asynchronous</p>
    <li data-md>
     <p>no locks shall be used in user code</p>
   </ul>
   <h4 class="heading settled" data-level="1.7.1" id="example-server-let"><span class="secno">1.7.1. </span><span class="content">Composability with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span><a class="self-link" href="#example-server-let"></a></h4>
   <p>Example context:</p>
   <ul>
    <li data-md>
     <p>we are looking at the flow of processing an HTTP request and sending back the response</p>
    <li data-md>
     <p>show how one can break the (slightly complex) flow into steps with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code> functions</p>
    <li data-md>
     <p>different phases of processing HTTP requests are broken down into separate concerns</p>
    <li data-md>
     <p>each part of the processing might use different execution contexts (details not shown in this example)</p>
    <li data-md>
     <p>error handling is generic, regardless which component fails; we always send the right response to the clients</p>
   </ul>
   <p>Goals:</p>
   <ul>
    <li data-md>
     <p>show how one can break more complex flows into steps with let_* functions</p>
    <li data-md>
     <p>exemplify the use of <code class="highlight"><c- n>let_value</c-></code>, <code class="highlight"><c- n>let_error</c-></code>, <code class="highlight"><c- n>let_stopped</c-></code>, and <code class="highlight"><c- n>just</c-></code> algorithms</p>
   </ul>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>ex</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- c1>// Returns a sender that yields an http_request object for an incoming request</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>schedule_request_start</c-><c- p>(</c-><c- n>read_requests_ctx</c-> <c- n>ctx</c-><c- p>)</c-> <c- p>{...}</c->
<c- c1>// Sends a response back to the client; yields a void signal on success</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>send_response</c-><c- p>(</c-><c- k>const</c-> <c- n>http_response</c-><c- o>&amp;</c-> <c- n>resp</c-><c- p>)</c-> <c- p>{...}</c->
<c- c1>// Validate that the HTTP request is well-formed; forwards the request on success</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>validate_request</c-><c- p>(</c-><c- k>const</c-> <c- n>http_request</c-><c- o>&amp;</c-> <c- n>req</c-><c- p>)</c-> <c- p>{...}</c->

<c- c1>// Handle the request; main application logic</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>handle_request</c-><c- p>(</c-><c- k>const</c-> <c- n>http_request</c-><c- o>&amp;</c-> <c- n>req</c-><c- p>)</c-> <c- p>{</c->
  <c- c1>//...</c->
  <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>200</c-><c- p>,</c-> <c- n>result_body</c-><c- p>});</c->
<c- p>}</c->

<c- c1>// Transforms server errors into responses to be sent to the client</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>error_to_response</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-> <c- n>err</c-><c- p>)</c-> <c- p>{</c->
  <c- n>try</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>rethrow_exception</c-><c- p>(</c-><c- n>err</c-><c- p>);</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(</c-><c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>invalid_argument</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>404</c-><c- p>,</c-> <c- n>e</c-><c- p>.</c-><c- n>what</c-><c- p>()});</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(</c-><c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>exception</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>500</c-><c- p>,</c-> <c- n>e</c-><c- p>.</c-><c- n>what</c-><c- p>()});</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>500</c-><c- p>,</c-> <c- s>"Unknown server error"</c-><c- p>});</c->
  <c- p>}</c->
<c- p>}</c->
<c- c1>// Transforms cancellation of the server into responses to be sent to the client</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_to_response</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>503</c-><c- p>,</c-> <c- s>"Service temporarily unavailable"</c-><c- p>});</c->
<c- p>}</c->
<c- c1>//...</c->
<c- c1>// The whole flow for transforming incoming requests into responses</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c->
    <c- c1>// get a sender when a new request comes</c->
    <c- n>schedule_request_start</c-><c- p>(</c-><c- n>the_read_requests_ctx</c-><c- p>)</c->
    <c- c1>// make sure the request is valid; throw if not</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>validate_request</c-><c- p>)</c->
    <c- c1>// process the request in a function that may be using a different execution context</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>handle_request</c-><c- p>)</c->
    <c- c1>// If there are errors transform them into proper responses</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_error</c-><c- p>(</c-><c- n>error_to_response</c-><c- p>)</c->
    <c- c1>// If the flow is cancelled, send back a proper response</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_stopped</c-><c- p>(</c-><c- n>stopped_to_response</c-><c- p>)</c->
    <c- c1>// write the result back to the client</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>send_response</c-><c- p>)</c->
    <c- c1>// done</c->
    <c- p>;</c->
<c- c1>// execute the whole flow asynchronously</c->
<c- n>ex</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>));</c->
</pre>
   The example shows how one can separate out the concerns for interpreting requests, validating requests, running the main logic for handling the request, generating error responses, handling cancellation and sending the response back to the client.
They are all different phases in the application, and can be joined together with the <code class="highlight"><c- n>let_</c-><c- o>*</c-></code> functions. 
   <p>All our functions return <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code> objects, so that they can all generate success, failure and cancellation paths.
For example, regardless where an error is generated (reading request, validating request or handling the response), we would have one common block to handle the error, and following error flows is easy.</p>
   <p>Also, because of using <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code> objects at any step, we might expect any of these steps to be completely asynchronous; the overall flow doesn’t care.
Regardless of the execution context in which the steps, or part of the steps are executed in, the flow is still the same.</p>
   <h4 class="heading settled" data-level="1.7.2" id="example-server-on"><span class="secno">1.7.2. </span><span class="content">Moving between execution contexts with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span><a class="self-link" href="#example-server-on"></a></h4>
   <p>Example context:</p>
   <ul>
    <li data-md>
     <p>reading data from the socket before processing the request</p>
    <li data-md>
     <p>reading of the data is done on the I/O context</p>
    <li data-md>
     <p>no processing of the data needs to be done on the I/O context</p>
   </ul>
   <p>Goals:</p>
   <ul>
    <li data-md>
     <p>show how one can change the execution context</p>
    <li data-md>
     <p>exemplify the use of <code class="highlight"><c- n>on</c-></code> and <code class="highlight"><c- n>transfer</c-></code> algorithms</p>
   </ul>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>ex</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- b>size_t</c-> <c- nf>legacy_read_from_socket</c-><c- p>(</c-><c- b>int</c-> <c- n>sock</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-> <c- n>buffer</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>buffer_len</c-><c- p>)</c-> <c- p>{}</c->
<c- b>void</c-> <c- nf>process_read_data</c-><c- p>(</c-><c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- n>read_data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>read_len</c-><c- p>)</c-> <c- p>{}</c->
<c- c1>//...</c->

<c- c1>// A sender that just calls the legacy read function</c->
<c- k>auto</c-> <c- n>snd_read</c-> <c- o>=</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>sock</c-><c- p>,</c-> <c- n>buf</c-><c- p>,</c-> <c- n>buf_len</c-><c- p>)</c-> <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>legacy_read_from_socket</c-><c- p>);</c->
<c- c1>// The entire flow</c->
<c- k>auto</c-> <c- n>snd</c-> <c- o>=</c->
    <c- c1>// start by reading data on the I/O thread</c->
    <c- n>ex</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>io_sched</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd_read</c-><c- p>))</c->
    <c- c1>// do the processing on the worker threads pool</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>work_sched</c-><c- p>)</c->
    <c- c1>// process the incoming data (on worker threads)</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>then</c-><c- p>([</c-><c- n>buf</c-><c- p>](</c-><c- b>int</c-> <c- n>read_len</c-><c- p>)</c-> <c- p>{</c-> <c- n>process_read_data</c-><c- p>(</c-><c- n>buf</c-><c- p>,</c-> <c- n>read_len</c-><c- p>);</c-> <c- p>})</c->
    <c- c1>// done</c->
    <c- p>;</c->
<c- c1>// execute the whole flow asynchronously</c->
<c- n>ex</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>));</c->
</pre>
   <p>The example assume that we need to wrap some legacy code of reading sockets, and handle execution context switching.
(This style of reading from socket may not be the most efficient one, but it’s working for our purposes.)
For performance reasons, the reading from the socket needs to be done on the I/O thread, and all the processing needs to happen on a work-specific execution context (i.e., thread pool).</p>
   <p>Calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> will ensure that the given sender will be started on the given scheduler.
In our example, <code class="highlight"><c- n>snd_read</c-></code> is going to be started on the I/O scheduler.
This sender will just call the legacy code.</p>
   <p>The completion signal will be issued in the I/O execution context, so we have to move it to the work thread pool.
This is achieved with the help of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> algorithm.
The rest of the processing (in our case, the last call to <code class="highlight"><c- n>then</c-></code>) will happen in the work thread pool.</p>
   <p>The reader should notice the difference between <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code>.
The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> algorithm will ensure that the given sender will start in the specified context, and doesn’t care where the completion signal for that sender is sent.
The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> algorithm will not care where the given sender is going to be started, but will ensure that the completion signal of will be transferred to the given context.</p>
   <h3 class="heading settled" data-level="1.8" id="intro-is-not"><span class="secno">1.8. </span><span class="content">What this proposal is <strong>not</strong></span><a class="self-link" href="#intro-is-not"></a></h3>
   <p>This paper is not a patch on top of <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; we are not asking to update the existing paper, we are asking to retire it in favor of this paper, which is already self-contained; any example code within this paper can be written in Standard C++, without the need
to standardize any further facilities.</p>
   <p>This paper is not an alternative design to <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; rather, we have taken the design in the current executors paper, and applied targeted fixes to allow it to fulfill the promises of the sender/receiver model, as well as provide all the facilities we consider
essential when writing user code using standard execution concepts; we have also applied the guidance of removing one-way executors from the paper entirely, and instead provided an algorithm based around senders that serves the same purpose.</p>
   <h3 class="heading settled" data-level="1.9" id="intro-compare"><span class="secno">1.9. </span><span class="content">Design changes from P0443</span><a class="self-link" href="#intro-compare"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>executor</c-></code> concept has been removed and all of its proposed functionality
is now based on schedulers and senders, as per SG1 direction.</p>
    <li data-md>
     <p>Properties are not included in this paper. We see them as a possible future
extension, if the committee gets more comfortable with them.</p>
    <li data-md>
     <p>Senders now advertise what scheduler, if any, their evaluation will complete
on.</p>
    <li data-md>
     <p>The places of execution of user code in P0443 weren’t precisely defined,
whereas they are in this paper. See <a href="#design-propagation">§ 4.5 Senders can propagate completion schedulers</a>.</p>
    <li data-md>
     <p>P0443 did not propose a suite of sender algorithms necessary for writing
sender code; this paper does. See <a href="#design-sender-factories">§ 4.20 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.21 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.22 User-facing sender consumers</a>.</p>
    <li data-md>
     <p>P0443 did not specify the semantics of variously qualified <code class="highlight"><c- n>connect</c-></code> overloads; this paper does. See <a href="#design-shot">§ 4.7 Senders can be either multi-shot or single-shot</a>.</p>
    <li data-md>
     <p>This paper extends the sender traits/typed sender design to support typed
senders whose value/error types depend on type information provided late via
the receiver.</p>
    <li data-md>
     <p>Support for untyped senders is dropped; the <code class="highlight"><c- n>typed_sender</c-></code> concept is renamed <code class="highlight"><c- n>sender</c-></code>; <code class="highlight"><c- n>sender_traits</c-></code> is replaced with <code class="highlight"><c- n>completion_signatures_of_t</c-></code>.</p>
    <li data-md>
     <p>Specific type erasure facilities are omitted, as per LEWG direction. Type
erasure facilities can be built on top of this proposal, as discussed in <a href="#design-dispatch">§ 5.9 Ranges-style CPOs vs tag_invoke</a>.</p>
    <li data-md>
     <p>A specific thread pool implementation is omitted, as per LEWG direction.</p>
    <li data-md>
     <p>Some additional utilities are added:</p>
     <ul>
      <li data-md>
       <p><b><code class="highlight"><c- n>run_loop</c-></code></b>: An execution context that provides a multi-producer,
single-consumer, first-in-first-out work queue.</p>
      <li data-md>
       <p><b><code class="highlight"><c- n>receiver_adaptor</c-></code></b>: A utility for algorithm authors for defining one
receiver type in terms of another.</p>
      <li data-md>
       <p><b><code class="highlight"><c- n>completion_signatures</c-></code></b> and <b><code class="highlight"><c- n>make_completion_signatures</c-></code></b>:
Utilities for describing the ways in which a sender can complete in a
declarative syntax.</p>
     </ul>
   </ol>
   <h3 class="heading settled" data-level="1.10" id="intro-prior-art"><span class="secno">1.10. </span><span class="content">Prior art</span><a class="self-link" href="#intro-prior-art"></a></h3>
   <p>This proposal builds upon and learns from years of prior art with asynchronous and parallel programming frameworks in C++. In this section, we discuss async abstractions that have previously been suggested as a possible basis for asynchronous algorithms and why they fall short.</p>
   <h4 class="heading settled" data-level="1.10.1" id="intro-prior-art-futures"><span class="secno">1.10.1. </span><span class="content">Futures</span><a class="self-link" href="#intro-prior-art-futures"></a></h4>
   <p>A future is a handle to work that has already been scheduled for execution. It is one end of a communication channel; the other end is a promise, used to receive the result from the concurrent operation and to communicate it to the future.</p>
   <p>Futures, as traditionally realized, require the dynamic allocation and management of a shared state, synchronization, and typically type-erasure of work and continuation. Many of these costs are inherent in the nature of "future" as a handle to work that is already scheduled for execution. These expenses rule out the future abstraction for many uses and makes it a poor choice for a basis of a generic mechanism.</p>
   <h4 class="heading settled" data-level="1.10.2" id="intro-prior-art-coroutines"><span class="secno">1.10.2. </span><span class="content">Coroutines</span><a class="self-link" href="#intro-prior-art-coroutines"></a></h4>
   <p>C++20 coroutines are frequently suggested as a basis for asynchronous algorithms. It’s fair to ask why, if we added coroutines to C++, are we suggesting the addition of a library-based abstraction for asynchrony. Certainly, coroutines come with huge syntactic and semantic advantages over the alternatives.</p>
   <p>Although coroutines are lighter weight than futures, coroutines suffer many of the same problems. Since they typically start suspended, they can avoid synchronizing the chaining of dependent work. However in many cases, coroutine frames require an unavoidable dynamic allocation and indirect function calls. This is done to hide the layout of the coroutine frame from the C++ type system, which in turn makes possible the separate compilation of coroutines and certain compiler optimizations, such as optimization of the coroutine frame size.</p>
   <p>Those advantages come at a cost, though. Because of the dynamic allocation of coroutine frames, coroutines in embedded or heterogeneous environments, which often lack support for dynamic allocation, require great attention to detail. And the allocations and indirections tend to complicate the job of the inliner, often resulting in sub-optimal codegen.</p>
   <p>The coroutine language feature mitigates these shortcomings somewhat with the HALO optimization <a data-link-type="biblio" href="https://wg21.link/p0981r0"><cite>Halo: coroutine Heap Allocation eLision Optimization: the joint response</cite></a>, which leverages existing compiler optimizations such as allocation elision and devirtualization to inline the coroutine, completely eliminating the runtime overhead. However, HALO requires a sophisiticated compiler, and a fair number of stars need to align for the optimization to kick in. In our experience, more often than not in real-world code today’s compilers are not able to inline the coroutine, resulting in allocations and indirections in the generated code.</p>
   <p>In a suite of generic async algorithms that are expected to be callable from hot code paths, the extra allocations and indirections are a deal-breaker. It is for these reasons that we consider coroutines a poor choise for a basis of all standard async.</p>
   <h4 class="heading settled" data-level="1.10.3" id="intro-prior-art-callbacks"><span class="secno">1.10.3. </span><span class="content">Callbacks</span><a class="self-link" href="#intro-prior-art-callbacks"></a></h4>
   <p>Callbacks are the oldest, simplest, most powerful, and most efficient mechanism for creating chains of work, but suffer problems of their own. Callbacks must propagate either errors or values. This simple requirement yields many different interface possibilities. The lack of a standard callback shape obstructs generic design.</p>
   <p>Additionally, few of these possibilities accommodate cancellation signals when the user requests upstream work to stop and clean up.</p>
   <h3 class="heading settled" data-level="1.11" id="intro-field-experience"><span class="secno">1.11. </span><span class="content">Field experience</span><a class="self-link" href="#intro-field-experience"></a></h3>
   <h4 class="heading settled" data-level="1.11.1" id="intro-field-experience-libunifex"><span class="secno">1.11.1. </span><span class="content">libunifex</span><a class="self-link" href="#intro-field-experience-libunifex"></a></h4>
   <p>This proposal draws heavily from our field experience with <a href="https://github.com/facebookexperimental/libunifex">libunifex</a>. Libunifex implements all of the concepts and customization points defined in this paper (with slight variations -- the design of P2300 has evolved due to LEWG feedback), many of this paper’s algorithms (some under different names), and much more besides.</p>
   <p>Libunifex has several concrete schedulers in addition to the <code class="highlight"><c- n>run_loop</c-></code> suggested here (where it is called <code class="highlight"><c- n>manual_event_loop</c-></code>). It has schedulers that dispatch efficiently to epoll and io_uring on Linux and the Windows Thread Pool on Windows.</p>
   <p>In addition to the proposed interfaces and the additional schedulers, it has several important extensions to the facilities described in this paper, which demonstrate directions in which these abstractions may be evolved over time, including:</p>
   <ul>
    <li data-md>
     <p>Timed schedulers, which permit scheduling work on an execution context at a particular time or after a particular duration has elapsed. In addition, it provides time-based algorithms.</p>
    <li data-md>
     <p>File I/O schedulers, which permit filesystem I/O to be scheduled.</p>
    <li data-md>
     <p>Two complementary abstractions for streams (asynchronous ranges), and a set of stream-based algorithms.</p>
   </ul>
   <p>Libunifex has seen heavy production use at Facebook. As of October 2021, it is currently used in production within the following applications and platforms:</p>
   <ul>
    <li data-md>
     <p>Facebook Messenger on iOS, Android, Windows, and macOS</p>
    <li data-md>
     <p>Instagram on iOS and Android</p>
    <li data-md>
     <p>Facebook on iOS and Android</p>
    <li data-md>
     <p>Portal</p>
    <li data-md>
     <p>An internal Facebook product that runs on Linux</p>
   </ul>
   <p>All of these applications are making direct use of the sender/receiver abstraction as presented in this paper. One product (Instagram on iOS) is making use of the sender/coroutine integration as presented. The monthly active users of these products number in the billions.</p>
   <h4 class="heading settled" data-level="1.11.2" id="intro-field-experience-other-implementations"><span class="secno">1.11.2. </span><span class="content">Other implementations</span><a class="self-link" href="#intro-field-experience-other-implementations"></a></h4>
   <p>The authors are aware of a number of other implementations of sender/receiver from this paper. These are presented here in perceived order of maturity and field experience.</p>
   <ul>
    <li data-md>
     <p><b><a data-link-type="biblio" href="https://doi.org/10.21105/joss.02352"><cite>HPX - The C++ Standard Library for Parallelism and Concurrency</cite></a></b></p>
     <p>HPX is a general purpose C++ runtime system for parallel and distributed applications that has been under active development since 2007. HPX exposes a uniform, standards-oriented API, and keeps abreast of the latest standards and proposals. It is used in a wide variety of high-performance applications.</p>
     <p>The sender/receiver implementation in HPX has been under active development since May 2020. It is used to erase the overhead of futures and to make it possible to write efficient generic asynchronous algorithms that are agnostic to their execution context. In HPX, algorithms can migrate execution between execution contexts, even to GPUs and back, using a uniform standard interface with sender/receiver.</p>
     <p>Far and away, the HPX team has the greatest usage experience outside Facebook. Mikael Simberg summarizes the experience as follows:</p>
     <blockquote>
      <p>Summarizing, for us the major benefits of sender/receiver compared to the old model are:</p>
      <ol>
       <li data-md>
        <p>Proper hooks for transitioning between execution contexts.</p>
       <li data-md>
        <p>The adaptors. Things like <code class="highlight"><c- n>let_value</c-></code> are really nice additions.</p>
       <li data-md>
        <p>Separation of the error channel from the value channel (also cancellation, but we don’t have much use for it at the moment). Even from a teaching perspective having to explain that the future <code class="highlight"><c- n>f2</c-></code> in the continuation will always be ready here <code class="highlight"><c- n>f1</c-><c- p>.</c-><c- n>then</c-><c- p>([](</c-><c- n>future</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>f2</c-><c- p>)</c-> <c- p>{...})</c-></code> is enough of a reason to separate the channels. All the other obvious reasons apply as well of course.</p>
       <li data-md>
        <p>For futures we have a thing called <code class="highlight"><c- n>hpx</c-><c- o>::</c-><c- n>dataflow</c-></code> which is an optimized version of <code class="highlight"><c- n>when_all</c-><c- p>(...).</c-><c- n>then</c-><c- p>(...)</c-></code> which avoids intermediate allocations. With the sender/receiver <code class="highlight"><c- n>when_all</c-><c- p>(...)</c-> <c- o>|</c-> <c- n>then</c-><c- p>(...)</c-></code> we get that "for free".</p>
      </ol>
     </blockquote>
    <li data-md>
     <p><b><a href="https://github.com/dietmarkuehl/kuhllib/">kuhllib</a> by Dietmar Kuehl</b></p>
     <p>This is a prototype Standard Template Library with an implementation of sender/receiver that has been under development since May, 2021. It is significant mostly for its support for sender/receiver-based networking interfaces.</p>
     <p>Here, Dietmar Kuehl speaks about the perceived complexity of sender/receiver:</p>
     <blockquote>
      <p>... and, also similar to STL: as I had tried to do things in that space before I recognize sender/receivers as being maybe complicated in one way but a huge simplification in another one: like with STL I think those who use it will benefit - if not from the algorithm from the clarity of abstraction: the separation of concerns of STL (the algorithm being detached from the details of the sequence representation) is a major leap. Here it is rather similar: the separation of the asynchronous algorithm from the details of execution. Sure, there is some glue to tie things back together but each of them is simpler than the combined result.</p>
     </blockquote>
     <p>Elsewhere, he said:</p>
     <blockquote>
      <p>... to me it feels like sender/receivers are like iterators when STL emerged: they are different from what everybody did in that space. However, everything people are already doing in that space isn’t right.</p>
     </blockquote>
     <p>Kuehl also has experience teaching sender/receiver at Bloomberg. About that experience he says:</p>
     <blockquote>
      <p>When I asked [my students] specifically about how complex they consider the sender/receiver stuff the feedback was quite unanimous that the sender/receiver parts aren’t trivial but not what contributes to the complexity.</p>
     </blockquote>
    <li data-md>
     <p><b><a href="https://github.com/NVIDIA/stdexec">The reference implementation</a></b></p>
     <p>This is a complete implementation written from the specification in this paper. Its primary purpose is to help find specification bugs and to harden the wording of the proposal. It is
fit for broad use and for contribution to libc++.</p>
     <p>It is current with R5 of this paper.</p>
    <li data-md>
     <p><b><a href="https://github.com/miscco/STL/tree/proposal/executors">Reference implementation for the Microsoft STL</a> by Michael Schellenberger Costa</b></p>
     <p>This is another reference implementation of this proposal, this time in a fork of the Mircosoft STL implementation. Michael Schellenberger Costa is not affiliated with Microsoft. He intends to contribute this implementation upstream when it is complete.</p>
   </ul>
   <h4 class="heading settled" data-level="1.11.3" id="intro-field-experience-inspirations"><span class="secno">1.11.3. </span><span class="content">Inspirations</span><a class="self-link" href="#intro-field-experience-inspirations"></a></h4>
   <p>This proposal also draws heavily from our experience with <a href="https://github.com/NVIDIA/thrust">Thrust</a> and <a href="https://github.com/agency-library/agency">Agency</a>. It is also inspired by the needs of countless other C++ frameworks for asynchrony, parallelism, and concurrency, including:</p>
   <ul>
    <li data-md>
     <p><a href="https://github.com/STEllAR-GROUP/hpx">HPX</a></p>
    <li data-md>
     <p><a href="https://github.com/facebook/folly/blob/master/folly/docs/Futures.md">Folly</a></p>
    <li data-md>
     <p><a href="https://stlab.cc/libraries/concurrency/">stlab</a></p>
   </ul>
   <h2 class="heading settled" data-level="2" id="revisions"><span class="secno">2. </span><span class="content">Revision history</span><a class="self-link" href="#revisions"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="r6"><span class="secno">2.1. </span><span class="content">R6</span><a class="self-link" href="#r6"></a></h3>
   <p>The changes since R5 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix typo in the specification of <code class="highlight"><c- n>in_place_stop_source</c-></code> about the relative
lifetimes of the tokens and the source that produced them.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_signatures</c-></code> tests for awaitability with a promise type
similar to the one used by <code class="highlight"><c- n>connect</c-></code> for the sake of consistency.</p>
    <li data-md>
     <p>A coroutine promise type is an environment provider (that is, it implements <code class="highlight"><c- n>get_env</c-><c- p>()</c-></code>) rather than being directly queryable. The previous draft was
inconsistent about that.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Sender queries are moved into a separate queryable "attributes" object
that is accessed by passing the sender to <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> (see below). The <code class="highlight"><c- n>sender</c-></code> concept is reexpressed to require <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> and separated
from a new <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Snd</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> concept for checking whether a type is
a sender within a particular execution environment.</p>
    <li data-md>
     <p>The placeholder types <code class="highlight"><c- n>no_env</c-></code> and <code class="highlight"><c- n>dependent_completion_signatures</c-><c- o>&lt;></c-></code> are no longer needed and are dropped.</p>
    <li data-md>
     <p><code class="highlight"><c- n>ensure_started</c-></code> and <code class="highlight"><c- n>split</c-></code> are changed to persist the result of
calling <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> on the input sender.</p>
    <li data-md>
     <p>Reorder constraints of the <code class="highlight"><c- n>scheduler</c-></code> and <code class="highlight"><c- n>receiver</c-></code> concepts to avoid constraint recursion
when used in tandem with poorly-constrained, implicitly convertible types.</p>
    <li data-md>
     <p>Re-express the <code class="highlight"><c- n>sender_of</c-></code> concept to be more ergonomic and general.</p>
    <li data-md>
     <p>Make the specification of the alias templates <code class="highlight"><c- n>value_types_of_t</c-></code> and <code class="highlight"><c- n>error_types_of_t</c-></code>, and the variable template <code class="highlight"><c- n>sends_done</c-></code> more concise by
expressing them in terms of a new exposition-only alias template <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i></code>.</p>
   </ul>
   <h4 class="heading settled" data-level="2.1.1" id="environments-and-attributes"><span class="secno">2.1.1. </span><span class="content">Environments and attributes</span><a class="self-link" href="#environments-and-attributes"></a></h4>
   <p>In earlier revisions, receivers, senders, and schedulers all were directly
queryable. In R4, receiver queries were moved into a separate "environment"
object, obtainable from a receiver with a <code class="highlight"><c- n>get_env</c-></code> accessor. In R6, the
sender queries are given similar treatment, relocating to a "attributes"
object obtainable from a sender with a <code class="highlight"><c- n>get_attrs</c-></code> accessor. This was done
to solve a number of design problems with the <code class="highlight"><c- n>split</c-></code> and <code class="highlight"><c- n>ensure_started</c-></code> algorithms; _e.g._, see <a href="https://github.com/NVIDIA/stdexec/issues/466">NVIDIA/stdexec#466</a>.</p>
   <p>Schedulers, however, remain directly queryable. As lightweight handles
that are required to be movable and copyable, there is little reason to
want to dispose of a scheduler and yet persist the scheduler’s queries.</p>
   <p>This revision also makes operation states directly queryable, even though
there isn’t yet a use for such. Some early prototypes of cooperative bulk
parallel sender algorithms done at NVIDIA suggest the utility of
forwardable operation state queries. The authors chose to make opstates
directly queryable since the opstate object is itself required to be kept
alive for the duration of asynchronous operation.</p>
   <h3 class="heading settled" data-level="2.2" id="r5"><span class="secno">2.2. </span><span class="content">R5</span><a class="self-link" href="#r5"></a></h3>
   <p>The changes since R4 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>start_detached</c-></code> requires its argument to be a <code class="highlight"><c- b>void</c-></code> sender (sends no values
to <code class="highlight"><c- n>set_value</c-></code>).</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Receiver concepts refactored to no longer require an error channel for <code class="highlight"><c- n>exception_ptr</c-></code> or a stopped channel.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sender_of</c-></code> concept and <code class="highlight"><c- n>connect</c-></code> customization point additionally require
that the receiver is capable of receiving all of the sender’s possible
completions.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_signatures</c-></code> is now required to return an instance of either <code class="highlight"><c- n>completion_signatures</c-></code> or <code class="highlight"><c- n>dependent_completion_signatures</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>make_completion_signatures</c-></code> made more general.</p>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-></code> handles <code class="highlight"><c- n>get_env</c-></code> as it does the <code class="highlight"><c- n>set_</c-><c- o>*</c-></code> members; that is, <code class="highlight"><c- n>receiver_adaptor</c-></code> will look for a member named <code class="highlight"><c- n>get_env</c-><c- p>()</c-></code> in the derived
class, and if found dispatch the <code class="highlight"><c- n>get_env_t</c-></code> tag invoke customization to it.</p>
    <li data-md>
     <p><code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, <code class="highlight"><c- n>just_stopped</c-></code>, and <code class="highlight"><c- n>into_variant</c-></code> have been respecified
as customization point objects instead of functions, following LEWG guidance.</p>
   </ul>
   <h3 class="heading settled" data-level="2.3" id="r4"><span class="secno">2.3. </span><span class="content">R4</span><a class="self-link" href="#r4"></a></h3>
   <p>The changes since R3 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix specification of <code class="highlight"><c- n>get_completion_scheduler</c-></code> on the <code class="highlight"><c- n>transfer</c-></code>, <code class="highlight"><c- n>schedule_from</c-></code> and <code class="highlight"><c- n>transfer_when_all</c-></code> algorithms; the completion scheduler cannot be guaranteed
for <code class="highlight"><c- n>set_error</c-></code>.</p>
    <li data-md>
     <p>The value of <code class="highlight"><c- n>sends_stopped</c-></code> for the default sender traits of types that are
generally awaitable was changed from <code class="highlight">false</code> to <code class="highlight">true</code> to acknowledge the
fact that some coroutine types are generally awaitable and may implement the <code class="highlight"><c- n>unhandled_stopped</c-><c- p>()</c-></code> protocol in their promise types.</p>
    <li data-md>
     <p>Fix the incorrect use of inline namespaces in the <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> header.</p>
    <li data-md>
     <p>Shorten the stable names for the sections.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sync_wait</c-></code> now handles <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>error_code</c-></code> specially by throwing a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>system_error</c-></code> on failure.</p>
    <li data-md>
     <p>Fix how ADL isolation from class template arguments is specified so it
doesn’t constrain implmentations.</p>
    <li data-md>
     <p>Properly expose the tag types in the header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Support for "dependently-typed" senders, where the completion signatures -- and
thus the sender metadata -- depend on the type of the receiver connected
to it. See the section <a href="#dependently-typed-senders">dependently-typed
senders</a> below for more information.</p>
    <li data-md>
     <p>Add a <code class="highlight"><c- n>read</c-><c- p>(</c-><i><c- n>query</c-></i><c- p>)</c-></code> sender factory for issuing a query
against a receiver and sending the result through the value channel. (This is
a useful instance of a dependently-typed sender.)</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>completion_signatures</c-></code> utility for declaratively defining a typed
sender’s metadata and a <code class="highlight"><c- n>make_completion_signatures</c-></code> utility for adapting
another sender’s completions in helpful ways.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>make_completion_signatures</c-></code> utility for specifying a sender’s completion
signatures by adapting those of another sender.</p>
    <li data-md>
     <p>Drop support for untyped senders and rename <code class="highlight"><c- n>typed_sender</c-></code> to <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_done</c-></code> is renamed to <code class="highlight"><c- n>set_stopped</c-></code>. All occurances of "<code class="highlight"><c- n>done</c-></code>" in
indentifiers replaced with "<code class="highlight"><c- n>stopped</c-></code>"</p>
    <li data-md>
     <p>Add customization points for controlling the forwarding of scheduler,
sender, receiver, and environment queries through layers of adaptors;
specify the behavior of the standard adaptors in terms of the new
customization points.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>get_delegatee_scheduler</c-></code> query to forward a scheduler that can be used
by algorithms or by the scheduler to delegate work and forward progress.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>schedule_result_t</c-></code> alias template.</p>
    <li data-md>
     <p>More precisely specify the sender algorithms, including precisely what their
completion signatures are.</p>
    <li data-md>
     <p><code class="highlight"><c- n>stopped_as_error</c-></code> respecified as a customization point object.</p>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-></code> respecified to improve diagnostics.</p>
   </ul>
   <h4 class="heading settled" data-level="2.3.1" id="dependently-typed-senders"><span class="secno">2.3.1. </span><span class="content">Dependently-typed senders</span><a class="self-link" href="#dependently-typed-senders"></a></h4>
   <p><strong>Background:</strong></p>
   <p>In the sender/receiver model, as with coroutines, contextual information about
the current execution is most naturally propagated from the consumer to the
producer. In coroutines, that means information like stop tokens, allocators and
schedulers are propagated from the calling coroutine to the callee. In
sender/receiver, that means that that contextual information is associated with
the receiver and is queried by the sender and/or operation state after the
sender and the receiver are <code class="highlight"><c- n>connect</c-></code>-ed.</p>
   <p><strong>Problem:</strong></p>
   <p>The implication of the above is that the sender alone does not have all the
information about the async computation it will ultimately initiate; some of
that information is provided late via the receiver. However, the <code class="highlight"><c- n>sender_traits</c-></code> mechanism, by which an algorithm can introspect the value and error types the
sender will propagate, <em>only</em> accepts a sender parameter. It does not take into
consideration the type information that will come in late via the receiver. The
effect of this is that some senders cannot be typed senders when they
otherwise could be.</p>
   <p><strong>Example:</strong></p>
   <p>To get concrete, consider the case of the "<code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code>" sender: when <code class="highlight"><c- n>connect</c-></code>-ed and <code class="highlight"><c- n>start</c-></code>-ed, it queries the receiver for its associated
scheduler and passes it back to the receiver through the value channel. That
sender’s "value type" is the type of the <em>receiver’s</em> scheduler. What then
should <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;</c-><c- n>get_scheduler_sender</c-><c- o>>::</c-><c- n>value_types</c-></code> report for the <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code>'s value type? It can’t answer because it doesn’t know.</p>
   <p>This causes knock-on problems since some important algorithms require a typed
sender, such as <code class="highlight"><c- n>sync_wait</c-></code>. To illustrate the problem, consider the following
code:</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>ex</c-> <c- o>=</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-><c- p>;</c->

<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>task</c-> <c- o>=</c->
  <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c->
    <c- n>ex</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>(),</c-> <c- c1>// Fetches scheduler from receiver.</c->
    <c- p>[](</c-><c- k>auto</c-> <c- n>current_sched</c-><c- p>)</c-> <c- p>{</c->
      <c- c1>// Lauch some nested work on the current scheduler:</c->
      <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>current_sched</c-><c- p>,</c-> <i><c- n>nested</c-> <c- n>work</c-><c- p>...</c-></i><c- p>);</c->
    <c- p>});</c->

<c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>));</c->
</pre>
   <p>The code above is attempting to schedule some work onto the <code class="highlight"><c- n>sync_wait</c-></code>'s <code class="highlight"><c- n>run_loop</c-></code> execution context. But <code class="highlight"><c- n>let_value</c-></code> only returns a typed sender when
the input sender is typed. As we explained above, <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> is not
typed, so <code class="highlight"><c- n>task</c-></code> is likewise not typed. Since <code class="highlight"><c- n>task</c-></code> isn’t typed, it cannot be
passed to <code class="highlight"><c- n>sync_wait</c-></code> which is expecting a typed sender. The above code would
fail to compile.</p>
   <p><strong>Solution:</strong></p>
   <p>The solution is conceptually quite simple: extend the <code class="highlight"><c- n>sender_traits</c-></code> mechanism
to optionally accept a receiver in addition to the sender. The algorithms can
use <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;</c-><i><c- n>Sender</c-></i><c- p>,</c-> <i><c- n>Receiver</c-></i><c- o>></c-></code> to inspect the
async operation’s completion signals. The <code class="highlight"><c- n>typed_sender</c-></code> concept would also need
to take an optional receiver parameter. This is the simplest change, and it
would solve the immediate problem.</p>
   <p><strong>Design:</strong></p>
   <p>Using the receiver type to compute the sender traits turns out to have pitfalls
in practice. Many receivers make use of that type information in their
implementation. It is very easy to create cycles in the type system, leading to
inscrutible errors. The design pursued in R4 is to give receivers an associated <em>environment</em> object -- a bag of key/value pairs -- and to move the contextual
information (schedulers, etc) out of the receiver and into the environment. The <code class="highlight"><c- n>sender_traits</c-></code> template and the <code class="highlight"><c- n>typed_sender</c-></code> concept, rather than taking a
receiver, take an environment. This is a much more robust design.</p>
   <p>A further refinement of this design would be to separate the receiver and the
environment entirely, passing then as separate arguments along with the sender to <code class="highlight"><c- n>connect</c-></code>. This paper does not propose that change.</p>
   <p><strong>Impact:</strong></p>
   <p>This change, apart from increasing the expressive power of the sender/receiver abstraction, has the following impact:</p>
   <ul>
    <li data-md>
     <p>Typed senders become moderately more challenging to write. (The new <code class="highlight"><c- n>completion_signatures</c-></code> and <code class="highlight"><c- n>make_completion_signatures</c-></code> utilities are added
to ease this extra burden.)</p>
    <li data-md>
     <p>Sender adaptor algorithms that previously constrained their sender arguments
to satisfy the <code class="highlight"><c- n>typed_sender</c-></code> concept can no longer do so as the receiver is
not available yet. This can result in type-checking that is done later, when <code class="highlight"><c- n>connect</c-></code> is ultimately called on the resulting sender adaptor.</p>
    <li data-md>
     <p>Operation states that own receivers that add to or change the environment
are typically larger by one pointer. It comes with the benefit of far fewer
indirections to evaluate queries.</p>
   </ul>
   <p><strong>"Has it been implemented?"</strong></p>
   <p>Yes, the reference implementation, which can be found at
https://github.com/NVIDIA/stdexec, has implemented this
design as well as some dependently-typed senders to confirm that it works.</p>
   <p><strong>Implementation experience</strong></p>
   <p>Although this change has not yet been made in libunifex, the most widely adopted sender/receiver implementation, a similar design can be found in Folly’s coroutine support library. In Folly.Coro, it is possible to await a special awaitable to obtain the current coroutine’s associated scheduler (called an executor in Folly).</p>
   <p>For instance, the following Folly code grabs the current executor, schedules a task for execution on that executor, and starts the resulting (scheduled) task by enqueueing it for execution.</p>
<pre class="language-c++ highlight"><c- c1>// From Facebook’s Folly open source library:</c->
<c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
<c- n>folly</c-><c- o>::</c-><c- n>coro</c-><c- o>::</c-><c- n>Task</c-><c- o>&lt;</c-><c- b>void</c-><c- o>></c-> <c- n>CancellableAsyncScope</c-><c- o>::</c-><c- n>co_schedule</c-><c- p>(</c-><c- n>folly</c-><c- o>::</c-><c- n>coro</c-><c- o>::</c-><c- n>Task</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>&amp;&amp;</c-> <c- n>task</c-><c- p>)</c-> <c- p>{</c->
  <c- n>this</c-><c- o>-></c-><c- n>add</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>).</c-><c- n>scheduleOn</c-><c- p>(</c-><c- n>co_await</c-> <c- n>co_current_executor</c-><c- p>));</c->
  <c- n>co_return</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Facebook relies heavily on this pattern in its coroutine code. But as described
above, this pattern doesn’t work with R3 of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code> because of the lack
of dependently-typed schedulers. The change to <code class="highlight"><c- n>sender_traits</c-></code> in R4 rectifies that.</p>
   <p><strong>Why now?</strong></p>
   <p>The authors are loathe to make any changes to the design, however small, at this
stage of the C++23 release cycle. But we feel that, for a relatively minor
design change -- adding an extra template parameter to <code class="highlight"><c- n>sender_traits</c-></code> and <code class="highlight"><c- n>typed_sender</c-></code> -- the returns are large enough to justify the change. And there
is no better time to make this change than as early as possible.</p>
   <p>One might wonder why this missing feature not been added to sender/receiver
before now. The designers of sender/receiver have long been aware of the need.
What was missing was a clean, robust, and simple design for the change, which we
now have.</p>
   <p><strong>Drive-by:</strong></p>
   <p>We took the opportunity to make an additional drive-by change: Rather than
providing the sender traits via a class template for users to specialize, we
changed it into a sender <em>query</em>: <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><i><c- n>sender</c-></i><c- p>,</c-> <i><c- n>env</c-></i><c- p>)</c-></code>. That function’s return type is used as the sender’s traits.
The authors feel this leads to a more uniform design and gives sender authors a
straightforward way to make the value/error types dependent on the cv- and
ref-qualification of the sender if need be.</p>
   <p><strong>Details:</strong></p>
   <p>Below are the salient parts of the new support for dependently-typed senders in
R4:</p>
   <ul>
    <li data-md>
     <p>Receiver queries have been moved from the receiver into a separate environment
object.</p>
    <li data-md>
     <p>Receivers have an associated environment. The new <code class="highlight"><c- n>get_env</c-></code> CPO retrieves a
receiver’s environment. If a receiver doesn’t implement <code class="highlight"><c- n>get_env</c-></code>, it returns
an unspecified "empty" environment -- an empty struct.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sender_traits</c-></code> now takes an optional <code class="highlight"><c- n>Env</c-></code> parameter that is used to
determine the error/value types.</p>
    <li data-md>
     <p>The primary <code class="highlight"><c- n>sender_traits</c-></code> template is replaced with a <code class="highlight"><c- n>completion_signatures_of_t</c-></code> alias implemented in terms of a new <code class="highlight"><c- n>get_completion_signatures</c-></code> CPO that dispatches
with <code class="highlight"><c- n>tag_invoke</c-></code>. <code class="highlight"><c- n>get_completion_signatures</c-></code> takes a sender and an optional
environment. A sender can customize this to specify its value/error types.</p>
    <li data-md>
     <p>Support for untyped senders is dropped. The <code class="highlight"><c- n>typed_sender</c-></code> concept has been
renamed to <code class="highlight"><c- n>sender</c-></code> and now takes an optional environment.</p>
    <li data-md>
     <p>The environment argument to the <code class="highlight"><c- n>sender</c-></code> concept and the <code class="highlight"><c- n>get_completion_signatures</c-></code> CPO defaults to <code class="highlight"><c- n>no_env</c-></code>. All environment queries fail (are ill-formed) when
passed an instance of <code class="highlight"><c- n>no_env</c-></code>.</p>
    <li data-md>
     <p>A type <code class="highlight"><c- n>S</c-></code> is required to satisfy <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- o>></c-></code> to be
considered a sender. If it doesn’t know what types it will complete with
independent of an environment, it returns an instance of the placeholder
traits <code class="highlight"><c- n>dependent_completion_signatures</c-></code>.</p>
    <li data-md>
     <p>If a sender satisfies both <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- o>></c-></code> and <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- p>,</c-> <i><c- n>Env</c-></i><c- o>></c-></code>, then the completion signatures
for the two cannot be different in any way. It is possible for an
implementation to enforce this statically, but not required.</p>
    <li data-md>
     <p>All of the algorithms and examples have been updated to work with
dependently-typed senders.</p>
   </ul>
   <h3 class="heading settled" data-level="2.4" id="r3"><span class="secno">2.4. </span><span class="content">R3</span><a class="self-link" href="#r3"></a></h3>
   <p>The changes since R2 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix specification of the <code class="highlight"><c- n>on</c-></code> algorithm to clarify lifetimes of
intermediate operation states and properly scope the <code class="highlight"><c- n>get_scheduler</c-></code> query.</p>
    <li data-md>
     <p>Fix a memory safety bug in the implementation of <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code>.</p>
    <li data-md>
     <p>Fix recursive definition of the <code class="highlight"><c- n>scheduler</c-></code> concept.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Add <code class="highlight"><c- n>run_loop</c-></code> execution context.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>receiver_adaptor</c-></code> utility to simplify writing receivers.</p>
    <li data-md>
     <p>Require a scheduler’s sender to model <code class="highlight"><c- n>sender_of</c-></code> and provide a completion scheduler.</p>
    <li data-md>
     <p>Specify the cancellation scope of the <code class="highlight"><c- n>when_all</c-></code> algorithm.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>as_awaitable</c-></code> a customization point.</p>
    <li data-md>
     <p>Change <code class="highlight"><c- n>connect</c-></code>'s handling of awaitables to consider those types that are awaitable owing to customization of <code class="highlight"><c- n>as_awaitable</c-></code>.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>value_types_of_t</c-></code> and <code class="highlight"><c- n>error_types_of_t</c-></code> alias templates; rename <code class="highlight"><c- n>stop_token_type_t</c-></code> to <code class="highlight"><c- n>stop_token_of_t</c-></code>.</p>
    <li data-md>
     <p>Add a design rationale for the removal of the possibly eager algorithms.</p>
    <li data-md>
     <p>Expand the section on field experience.</p>
   </ul>
   <h3 class="heading settled" data-level="2.5" id="r2"><span class="secno">2.5. </span><span class="content">R2</span><a class="self-link" href="#r2"></a></h3>
   <p>The changes since R1 are as follows:</p>
   <ul>
    <li data-md>
     <p>Remove the eagerly executing sender algorithms.</p>
    <li data-md>
     <p>Extend the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> customization point and the <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;></c-></code> template to recognize awaitables as <code class="highlight"><c- n>typed_sender</c-></code>s.</p>
    <li data-md>
     <p>Add utilities <code class="highlight"><c- n>as_awaitable</c-><c- p>()</c-></code> and <code class="highlight"><c- n>with_awaitable_senders</c-><c- o>&lt;></c-></code> so a coroutine type can trivially make senders awaitable with a coroutine.</p>
    <li data-md>
     <p>Add a section describing the design of the sender/awaitable interactions.</p>
    <li data-md>
     <p>Add a section describing the design of the cancellation support in sender/receiver.</p>
    <li data-md>
     <p>Add a section showing examples of simple sender adaptor algorithms.</p>
    <li data-md>
     <p>Add a section showing examples of simple schedulers.</p>
    <li data-md>
     <p>Add a few more examples: a sudoku solver, a parallel recursive file copy, and an echo server.</p>
    <li data-md>
     <p>Refined the forward progress guarantees on the <code class="highlight"><c- n>bulk</c-></code> algorithm.</p>
    <li data-md>
     <p>Add a section describing how to use a range of senders to represent async sequences.</p>
    <li data-md>
     <p>Add a section showing how to use senders to represent partial success.</p>
    <li data-md>
     <p>Add sender factories <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code>.</p>
    <li data-md>
     <p>Add sender adaptors <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code>.</p>
    <li data-md>
     <p>Document more production uses of sender/receiver at scale.</p>
    <li data-md>
     <p>Various fixes of typos and bugs.</p>
   </ul>
   <h3 class="heading settled" data-level="2.6" id="r1"><span class="secno">2.6. </span><span class="content">R1</span><a class="self-link" href="#r1"></a></h3>
   <p>The changes since R0 are as follows:</p>
   <ul>
    <li data-md>
     <p>Added a new concept, <code class="highlight"><c- n>sender_of</c-></code>.</p>
    <li data-md>
     <p>Added a new scheduler query, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code>.</p>
    <li data-md>
     <p>Added a new scheduler query, <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>.</p>
    <li data-md>
     <p>Removed the <code class="highlight"><c- n>unschedule</c-></code> adaptor.</p>
    <li data-md>
     <p>Various fixes of typos and bugs.</p>
   </ul>
   <h3 class="heading settled" data-level="2.7" id="r0"><span class="secno">2.7. </span><span class="content">R0</span><a class="self-link" href="#r0"></a></h3>
   <p>Initial revision.</p>
   <h2 class="heading settled" data-level="3" id="design-intro"><span class="secno">3. </span><span class="content">Design - introduction</span><a class="self-link" href="#design-intro"></a></h2>
   <p>The following three sections describe the entirety of the proposed design.</p>
   <ul>
    <li data-md>
     <p><a href="#design-intro">§ 3 Design - introduction</a> describes the conventions used through the rest of the design sections, as well as an example illustrating how we envision code will be written using this proposal.</p>
    <li data-md>
     <p><a href="#design-user">§ 4 Design - user side</a> describes all the functionality from the perspective we intend for users: it describes the various concepts they will interact with, and what their programming model is.</p>
    <li data-md>
     <p><a href="#design-implementer">§ 5 Design - implementer side</a> describes the machinery that allows for that programming model to function, and the information contained there is necessary for people implementing senders and sender algorithms (including the standard library ones) - but is not necessary to use senders productively.</p>
   </ul>
   <h3 class="heading settled" data-level="3.1" id="design-conventions"><span class="secno">3.1. </span><span class="content">Conventions</span><a class="self-link" href="#design-conventions"></a></h3>
   <p>The following conventions are used throughout the design section:</p>
   <ol>
    <li data-md>
     <p>The namespace proposed in this paper is the same as in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>: <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code>; however, for brevity, the <code class="highlight"><c- n>std</c-><c- o>::</c-></code> part of this name is omitted. When you see <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>foo</c-></code>, treat that as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>foo</c-></code>.</p>
    <li data-md>
     <p>Universal references and explicit calls to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-></code> are omitted in code samples and signatures for simplicity; assume universal references and perfect forwarding unless stated otherwise.</p>
    <li data-md>
     <p>None of the names proposed here are names that we are particularly attached to; consider the names to be reasonable placeholders that can freely be changed, should the committee want to do so.</p>
   </ol>
   <h3 class="heading settled" data-level="3.2" id="design-queries-and-algorithms"><span class="secno">3.2. </span><span class="content">Queries and algorithms</span><a class="self-link" href="#design-queries-and-algorithms"></a></h3>
   <p>A <dfn data-dfn-type="dfn" data-export id="query">query<a class="self-link" href="#query"></a></dfn> is a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that takes some set of objects (usually one) as parameters and returns facts about those objects without modifying them. Queries are usually customization point objects, but in some cases may be functions.</p>
   <p>An <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="algorithm">algorithm</dfn> is a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that takes some set of objects as parameters and causes those objects to do something. Algorithms are usually customization point objects, but in some cases may be functions.</p>
   <h2 class="heading settled" data-level="4" id="design-user"><span class="secno">4. </span><span class="content">Design - user side</span><a class="self-link" href="#design-user"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="design-contexts"><span class="secno">4.1. </span><span class="content">Execution contexts describe the place of execution</span><a class="self-link" href="#design-contexts"></a></h3>
   <p>An <dfn data-dfn-type="dfn" data-export id="execution-context">execution context<a class="self-link" href="#execution-context"></a></dfn> is a resource that represents the <em>place</em> where execution will happen. This could be a concrete resource - like a specific thread pool object, or a GPU - or a more abstract one, like the current thread of execution. Execution contexts
don’t need to have a representation in code; they are simply a term describing certain properties of execution of a function.</p>
   <h3 class="heading settled" data-level="4.2" id="design-schedulers"><span class="secno">4.2. </span><span class="content">Schedulers represent execution contexts</span><a class="self-link" href="#design-schedulers"></a></h3>
   <p>A <dfn data-dfn-type="dfn" data-export id="scheduler">scheduler<a class="self-link" href="#scheduler"></a></dfn> is a lightweight handle that represents a strategy for scheduling work onto an <em>execution context</em>. Since execution contexts don’t necessarily manifest in C++ code, it’s not possible to program
directly against their API. A scheduler is a solution to that problem: the scheduler concept is defined by a single sender algorithm, <code class="highlight"><c- n>schedule</c-></code>, which returns a sender that will complete on an execution context determined
by the scheduler. Logic that you want to run on that context can be placed in the receiver’s completion-signalling method.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->
<c- c1>// snd is a sender (see below) describing the creation of a new execution resource</c->
<c- c1>// on the execution context associated with sch</c->
</pre>
   <p>Note that a particular scheduler type may provide other kinds of scheduling operations
which are supported by its associated execution context. It is not limited to scheduling
purely using the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> API.</p>
   <p>Future papers will propose additional scheduler concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to add other capabilities. For example:</p>
   <ul>
    <li data-md>
     <p>A <code class="highlight"><c- n>time_scheduler</c-></code> concept that extends <code class="highlight"><c- n>scheduler</c-></code> to support time-based scheduling.
Such a concept might provide access to <code class="highlight"><c- n>schedule_after</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>duration</c-><c- p>)</c-></code>, <code class="highlight"><c- n>schedule_at</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>time_point</c-><c- p>)</c-></code> and <code class="highlight"><c- n>now</c-><c- p>(</c-><c- n>sched</c-><c- p>)</c-></code> APIs.</p>
    <li data-md>
     <p>Concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to support opening, reading and writing files asynchronously.</p>
    <li data-md>
     <p>Concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to support connecting, sending data and receiving data over the network asynchronously.</p>
   </ul>
   <h3 class="heading settled" data-level="4.3" id="design-senders"><span class="secno">4.3. </span><span class="content">Senders describe work</span><a class="self-link" href="#design-senders"></a></h3>
   <p>A <dfn data-dfn-type="dfn" data-export id="sender">sender<a class="self-link" href="#sender"></a></dfn> is an object that describes work. Senders are similar to futures in existing asynchrony designs, but unlike futures, the work that is being done to arrive at the values they will <em>send</em> is also directly described by the sender object itself. A
sender is said to <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="send">send</dfn> some values if a receiver connected (see <a href="#design-connect">§ 5.3 execution::connect</a>) to that sender will eventually <em>receive</em> said values.</p>
   <p>The primary defining sender algorithm is <a href="#design-connect">§ 5.3 execution::connect</a>; this function, however, is not a user-facing API; it is used to facilitate communication between senders and various sender algorithms, but end user code is not expected to invoke
it directly.</p>
   <p>The way user code is expected to interact with senders is by using <a data-link-type="dfn" href="#sender-algorithms" id="ref-for-sender-algorithms">sender algorithms</a>.
This paper proposes an initial set of such sender algorithms, which are described in <a href="#design-composable">§ 4.4 Senders are composable through sender algorithms</a>, <a href="#design-sender-factories">§ 4.20 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.21 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.22 User-facing sender consumers</a>.
For example, here is how a user can create a new sender on a scheduler, attach a continuation to it, and then wait for execution of the continuation to complete:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>cont</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>fstream</c-> <c- n>file</c-><c- p>{</c-> <c- s>"result.txt"</c-> <c- p>};</c->
    <c- n>file</c-> <c- o>&lt;&lt;</c-> <c- n>compute_result</c-><c- p>;</c->
<c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>cont</c-><c- p>);</c->
<c- c1>// at this point, cont has completed execution</c->
</pre>
   <h3 class="heading settled" data-level="4.4" id="design-composable"><span class="secno">4.4. </span><span class="content">Senders are composable through sender algorithms</span><a class="self-link" href="#design-composable"></a></h3>
   <p>Asynchronous programming often departs from traditional code structure and control flow that we are familiar with.
A successful asynchronous framework must provide an intuitive story for composition of asynchronous work: expressing dependencies, passing objects, managing object lifetimes, etc.</p>
   <p>The true power and utility of senders is in their composability.
With senders, users can describe generic execution pipelines and graphs, and then run them on and across a variety of different schedulers.
Senders are composed using <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-algorithms">sender algorithms</dfn>:</p>
   <ul>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-factory" id="ref-for-sender-factory">sender factories</a>, algorithms that take no senders and return a sender.</p>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-adaptor" id="ref-for-sender-adaptor">sender adaptors</a>, algorithms that take (and potentially <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>) senders and return a sender.</p>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-consumer" id="ref-for-sender-consumer">sender consumers</a>, algorithms that take (and potentially <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>) senders and do not return a sender.</p>
   </ul>
   <h3 class="heading settled" data-level="4.5" id="design-propagation"><span class="secno">4.5. </span><span class="content">Senders can propagate completion schedulers</span><a class="self-link" href="#design-propagation"></a></h3>
   <p>One of the goals of executors is to support a diverse set of execution contexts, including traditional thread pools, task and fiber frameworks (like <a href="https://github.com/STEllAR-GROUP/hpx">HPX</a> and <a href="https://github.com/StanfordLegion/legion">Legion</a>), and GPUs and other accelerators (managed by runtimes such as CUDA or SYCL).
On many of these systems, not all execution agents are created equal and not all functions can be run on all execution agents.
Having precise control over the execution context used for any given function call being submitted is important on such systems, and the users of standard execution facilities will expect to be able to express such requirements.</p>
   <p><a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> was not always clear about the <i>place of execution</i> of any given piece of code.
Precise control was present in the two-way execution API present in earlier executor designs, but it has so far been missing from the senders design. There has been a proposal (<a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>) to provide a number of sender algorithms that would enforce certain rules on the places of execution
of the work described by a sender, but we have found those sender algorithms to be insufficient for achieving the best performance on all platforms that are of interest to us. The implementation strategies that we are aware of result in one of the following situations:</p>
   <ol>
    <li data-md>
     <p>trying to submit work to one execution context (such as a CPU thread pool) from another execution context (such as a GPU or a task framework), which assumes that all execution agents are as capable as a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> (which they aren’t).</p>
    <li data-md>
     <p>forcibly interleaving two adjacent execution graph nodes that are both executing on one execution context (such as a GPU) with glue code that runs on another execution context (such as a CPU), which is prohibitively expensive for some execution contexts (such as CUDA or SYCL).</p>
    <li data-md>
     <p>having to customise most or all sender algorithms to support an execution context, so that you can avoid problems described in 1. and 2, which we believe is impractical and brittle based on months of field experience attempting this in <a href="https://github.com/agency-library/agency">Agency</a>.</p>
   </ol>
   <p>None of these implementation strategies are acceptable for many classes of parallel runtimes, such as task frameworks (like <a href="https://github.com/STEllAR-GROUP/hpx">HPX</a>) or accelerator runtimes (like CUDA or SYCL).</p>
   <p>Therefore, in addition to the <code class="highlight"><c- n>on</c-></code> sender algorithm from <a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>, we are proposing a way for senders to advertise what scheduler (and by extension what execution context) they will complete on.
Any given sender <b>may</b> have <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="completion-schedulers">completion schedulers</dfn> for some or all of the signals (value, error, or stopped) it completes with (for more detail on the completion signals, see <a href="#design-receivers">§ 5.1 Receivers serve as glue between senders</a>).
When further work is attached to that sender by invoking sender algorithms, that work will also complete on an appropriate completion scheduler.</p>
   <h4 class="heading settled" data-level="4.5.1" id="design-sender-query-get_completion_scheduler"><span class="secno">4.5.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code></span><a class="self-link" href="#design-sender-query-get_completion_scheduler"></a></h4>
   <p><code class="highlight"><c- n>get_completion_scheduler</c-></code> is a query that retrieves the <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers">completion scheduler</a> for a specific completion signal from a sender’s attributes.
For a sender that lacks a completion scheduler attribute for a given signal, calling <code class="highlight"><c- n>get_completion_scheduler</c-></code> is ill-formed.
If a sender advertises a completion scheduler for a signal in this way, that sender <b>must</b> ensure that it <a data-link-type="dfn" href="#send" id="ref-for-send">sends</a> that signal on an execution agent belonging to an execution context represented by a scheduler returned from this function.
See <a href="#design-propagation">§ 4.5 Senders can propagate completion schedulers</a> for more details.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cpu_sched</c-> <c- o>=</c-> <c- n>new_thread_scheduler</c-><c- p>{};</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>gpu_sched</c-> <c- o>=</c-> <c- n>cuda</c-><c- o>::</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd0</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cpu_sched</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch0</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>snd0</c-><c- p>));</c->
<c- c1>// completion_sch0 is equivalent to cpu_sched</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd0</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on cpu_sched!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch1</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>snd1</c-><c- p>));</c->
<c- c1>// completion_sch1 is equivalent to cpu_sched</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- n>gpu_sched</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on gpu_sched!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch3</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>snd3</c-><c- p>));</c->
<c- c1>// completion_sch3 is equivalent to gpu_sched</c->
</pre>
   <h3 class="heading settled" data-level="4.6" id="design-transitions"><span class="secno">4.6. </span><span class="content">Execution context transitions are explicit</span><a class="self-link" href="#design-transitions"></a></h3>
   <p><a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> does not contain any mechanisms for performing an execution context transition. The only sender algorithm that can create a sender that will move execution to a <em>specific</em> execution context is <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code>, which does not take an input sender.
That means that there’s no way to construct sender chains that traverse different execution contexts. This is necessary to fulfill the promise of senders being able to replace two-way executors, which had this capability.</p>
   <p>We propose that, for senders advertising their <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers①">completion scheduler</a>, all execution context transitions <b>must</b> be explicit; running user code anywhere but where they defined it to run <b>must</b> be considered a bug.</p>
   <p>The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> sender adaptor performs a transition from one execution context to another:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch2</c-> <c- o>=</c-> <c- p>...;</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch1</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on sch1!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>then1</c-><c- p>,</c-> <c- n>sch2</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on sch2!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>then2</c-><c- p>);</c->
</pre>
   <h3 class="heading settled" data-level="4.7" id="design-shot"><span class="secno">4.7. </span><span class="content">Senders can be either multi-shot or single-shot</span><a class="self-link" href="#design-shot"></a></h3>
   <p>Some senders may only support launching their operation a single time, while others may be repeatable
and support being launched multiple times. Executing the operation may consume resources owned by the
sender.</p>
   <p>For example, a sender may contain a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-></code> that it will be transferring ownership of to the
operation-state returned by a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> so that the operation has access to
this resource. In such a sender, calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> consumes the sender such that after
the call the input sender is no longer valid. Such a sender will also typically be move-only so that
it can maintain unique ownership of that resource.</p>
   <p>A <dfn data-dfn-type="dfn" data-export id="single-shot-sender">single-shot sender<a class="self-link" href="#single-shot-sender"></a></dfn> can only be connected to a receiver at most once. Its implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> only has overloads for an rvalue-qualified sender. Callers must pass the sender
as an rvalue to the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, indicating that the call consumes the sender.</p>
   <p>A <dfn data-dfn-type="dfn" data-export id="multi-shot-sender">multi-shot sender<a class="self-link" href="#multi-shot-sender"></a></dfn> can be connected to multiple receivers and can be launched multiple
times. Multi-shot senders customise <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> to accept an lvalue reference to the
sender. Callers can indicate that they want the sender to remain valid after the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> by passing an lvalue reference to the sender to call these overloads. Multi-shot senders should also define
overloads of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> that accept rvalue-qualified senders to allow the sender to be also used in places
where only a single-shot sender is required.</p>
   <p>If the user of a sender does not require the sender to remain valid after connecting it to a
receiver then it can pass an rvalue-reference to the sender to the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>.
Such usages should be able to accept either single-shot or multi-shot senders.</p>
   <p>If the caller does wish for the sender to remain valid after the call then it can pass an lvalue-qualified sender
to the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>. Such usages will only accept multi-shot senders.</p>
   <p>Algorithms that accept senders will typically either decay-copy an input sender and store it somewhere
for later usage (for example as a data-member of the returned sender) or will immediately call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on the input sender, such as in <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code>.</p>
   <p>Some multi-use sender algorithms may require that an input sender be copy-constructible but will only call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on an rvalue of each copy, which still results in effectively executing the operation multiple times.
Other multi-use sender algorithms may require that the sender is move-constructible but will invoke <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on an lvalue reference to the sender.</p>
   <p>For a sender to be usable in both multi-use scenarios, it will generally be required to be both copy-constructible and lvalue-connectable.</p>
   <h3 class="heading settled" data-level="4.8" id="design-forkable"><span class="secno">4.8. </span><span class="content">Senders are forkable</span><a class="self-link" href="#design-forkable"></a></h3>
   <p>Any non-trivial program will eventually want to fork a chain of senders into independent streams of work, regardless of whether they are single-shot or multi-shot.
For instance, an incoming event to a middleware system may be required to trigger events on more than one downstream system.
This requires that we provide well defined mechanisms for making sure that connecting a sender multiple times is possible and correct.</p>
   <p>The <code class="highlight"><c- n>split</c-></code> sender adaptor facilitates connecting to a sender multiple times, regardless of whether it is single-shot or multi-shot:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>some_algorithm</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>input</c-><c- p>)</c-> <c- p>{</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>multi_shot</c-> <c- o>=</c-> <c- n>split</c-><c- p>(</c-><c- n>input</c-><c- p>);</c->
    <c- c1>// "multi_shot" is guaranteed to be multi-shot,</c->
    <c- c1>// regardless of whether "input" was multi-shot or not</c->

    <c- k>return</c-> <c- n>when_all</c-><c- p>(</c->
      <c- n>then</c-><c- p>(</c-><c- n>multi_shot</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"First continuation</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c-> <c- p>}),</c->
      <c- n>then</c-><c- p>(</c-><c- n>multi_shot</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Second continuation</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c-> <c- p>})</c->
    <c- p>);</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="4.9" id="design-join"><span class="secno">4.9. </span><span class="content">Senders are joinable</span><a class="self-link" href="#design-join"></a></h3>
   <p>Similarly to how it’s hard to write a complex program that will eventually want to fork sender chains into independent streams, it’s also hard to write a program that does not want to eventually create join nodes, where multiple independent streams of execution are
merged into a single one in an asynchronous fashion.</p>
   <p><code class="highlight"><c- n>when_all</c-></code> is a sender adaptor that returns a sender that completes when the last of the input senders completes. It <a data-link-type="dfn" href="#send" id="ref-for-send①">sends</a> a pack of values, where the elements of said pack are the values sent by the input senders, in order. <code class="highlight"><c- n>when_all</c-></code> returns a sender that also does not have an associated scheduler.</p>
   <p><code class="highlight"><c- n>transfer_when_all</c-></code> accepts an additional scheduler argument. It returns a sender whose value <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers②">completion scheduler</a> is the scheduler provided as an argument, but otherwise behaves the same as <code class="highlight"><c- n>when_all</c-></code>. You can think of it as a composition of <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>when_all</c-><c- p>(</c-><c- n>inputs</c-><c- p>...),</c-> <c- n>scheduler</c-><c- p>)</c-></code>, but one that allows for better efficiency through customization.</p>
   <h3 class="heading settled" data-level="4.10" id="design-cancellation"><span class="secno">4.10. </span><span class="content">Senders support cancellation</span><a class="self-link" href="#design-cancellation"></a></h3>
   <p>Senders are often used in scenarios where the application may be concurrently executing
multiple strategies for achieving some program goal. When one of these strategies succeeds
(or fails) it may not make sense to continue pursuing the other strategies as their results
are no longer useful.</p>
   <p>For example, we may want to try to simultaneously connect to multiple network servers and use
whichever server responds first. Once the first server responds we no longer need to continue
trying to connect to the other servers.</p>
   <p>Ideally, in these scenarios, we would somehow be able to request that those other strategies
stop executing promptly so that their resources (e.g. cpu, memory, I/O bandwidth) can be
released and used for other work.</p>
   <p>While the design of senders has support for cancelling an operation before it starts
by simply destroying the sender or the operation-state returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> before calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code>, there also needs to be a standard, generic mechanism
to ask for an already-started operation to complete early.</p>
   <p>The ability to be able to cancel in-flight operations is fundamental to supporting some kinds
of generic concurrency algorithms.</p>
   <p>For example:</p>
   <ul>
    <li data-md>
     <p>a <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>ops</c-><c- p>...)</c-></code> algorithm should cancel other operations as soon as one operation fails</p>
    <li data-md>
     <p>a <code class="highlight"><c- n>first_successful</c-><c- p>(</c-><c- n>ops</c-><c- p>...)</c-></code> algorithm should cancel the other operations as soon as one operation completes successfuly</p>
    <li data-md>
     <p>a generic <code class="highlight"><c- n>timeout</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- n>duration</c-><c- p>)</c-></code> algorithm needs to be able to cancel the <code class="highlight"><c- n>src</c-></code> operation after the timeout duration has elapsed.</p>
    <li data-md>
     <p>a <code class="highlight"><c- n>stop_when</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- n>trigger</c-><c- p>)</c-></code> algorithm should cancel <code class="highlight"><c- n>src</c-></code> if <code class="highlight"><c- n>trigger</c-></code> completes first and cancel <code class="highlight"><c- n>trigger</c-></code> if <code class="highlight"><c- n>src</c-></code> completes first</p>
   </ul>
   <p>The mechanism used for communcating cancellation-requests, or stop-requests, needs to have a uniform interface
so that generic algorithms that compose sender-based operations, such as the ones listed above, are able to
communicate these cancellation requests to senders that they don’t know anything about.</p>
   <p>The design is intended to be composable so that cancellation of higher-level operations can propagate
those cancellation requests through intermediate layers to lower-level operations that need to actually
respond to the cancellation requests.</p>
   <p>For example, we can compose the algorithms mentioned above so that child operations
are cancelled when any one of the multiple cancellation conditions occurs:</p>
<pre class="highlight"><c- n>sender</c-> <c- k>auto</c-> <c- n>composed_cancellation_example</c-><c- p>(</c-><c- k>auto</c-> <c- n>query</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>stop_when</c-><c- p>(</c->
    <c- n>timeout</c-><c- p>(</c->
      <c- n>when_all</c-><c- p>(</c->
        <c- n>first_successful</c-><c- p>(</c->
          <c- n>query_server_a</c-><c- p>(</c-><c- n>query</c-><c- p>),</c->
          <c- n>query_server_b</c-><c- p>(</c-><c- n>query</c-><c- p>)),</c->
        <c- n>load_file</c-><c- p>(</c-><c- s>"some_file.jpg"</c-><c- p>)),</c->
      <c- mi>5</c-><c- n>s</c-><c- p>),</c->
    <c- n>cancelButton</c-><c- p>.</c-><c- n>on_click</c-><c- p>());</c->
<c- p>}</c->
</pre>
   <p>In this example, if we take the operation returned by <code class="highlight"><c- n>query_server_b</c-><c- p>(</c-><c- n>query</c-><c- p>)</c-></code>, this operation will
receive a stop-request when any of the following happens:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>first_successful</c-></code> algorithm will send a stop-request if <code class="highlight"><c- n>query_server_a</c-><c- p>(</c-><c- n>query</c-><c- p>)</c-></code> completes successfully</p>
    <li data-md>
     <p><code class="highlight"><c- n>when_all</c-></code> algorithm will send a stop-request if the <code class="highlight"><c- n>load_file</c-><c- p>(</c-><c- s>"some_file.jpg"</c-><c- p>)</c-></code> operation completes with an error or stopped result.</p>
    <li data-md>
     <p><code class="highlight"><c- n>timeout</c-></code> algorithm will send a stop-request if the operation does not complete within 5 seconds.</p>
    <li data-md>
     <p><code class="highlight"><c- n>stop_when</c-></code> algorithm will send a stop-request if the user clicks on the "Cancel" button in the user-interface.</p>
    <li data-md>
     <p>The parent operation consuming the <code class="highlight"><c- n>composed_cancellation_example</c-><c- p>()</c-></code> sends a stop-request</p>
   </ul>
   <p>Note that within this code there is no explicit mention of cancellation, stop-tokens, callbacks, etc.
yet the example fully supports and responds to the various cancellation sources.</p>
   <p>The intent of the design is that the common usage of cancellation in sender/receiver-based code is
primarily through use of concurrency algorithms that manage the detailed plumbing of cancellation
for you. Much like algorithms that compose senders relieve the user from having to write their own
receiver types, algorithms that introduce concurrency and provide higher-level cancellation semantics
relieve the user from having to deal with low-level details of cancellation.</p>
   <h4 class="heading settled" data-level="4.10.1" id="design-cancellation-summary"><span class="secno">4.10.1. </span><span class="content">Cancellation design summary</span><a class="self-link" href="#design-cancellation-summary"></a></h4>
   <p>The design of cancellation described in this paper is built on top of and extends the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_token</c-></code>-based
cancellation facilities added in C++20, first proposed in <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>.</p>
   <p>At a high-level, the facilities proposed by this paper for supporting cancellation include:</p>
   <ul>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token_for</c-></code> concepts that generalise the interface of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_token</c-></code> type to allow other types with different implementation strategies.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unstoppable_token</c-></code> concept for detecting whether a <code class="highlight"><c- n>stoppable_token</c-></code> can never receive a stop-request.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_token</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_source</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> types that provide a more efficient implementation of a stop-token for use in structured concurrency situations.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>never_stop_token</c-></code> for use in places where you never want to issue a stop-request</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO for querying the stop-token to use for an operation from its receiver’s execution environment.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> for querying the type of a stop-token returned from <code class="highlight"><c- n>get_stop_token</c-><c- p>()</c-></code></p>
   </ul>
   <p>In addition, there are requirements added to some of the algorithms to specify what their cancellation
behaviour is and what the requirements of customisations of those algorithms are with respect to
cancellation.</p>
   <p>The key component that enables generic cancellation within sender-based operations is the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO.
This CPO takes a single parameter, which is the execution environment of the receiver passed to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, and returns a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token</c-></code> that the operation can use to check for stop-requests for that operation.</p>
   <p>As the caller of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> typically has control over the receiver
type it passes, it is able to customise the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>()</c-></code> CPO for that
receiver to return an execution environment that hooks the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO to return a stop-token that the receiver has
control over and that it can use to communicate a stop-request to the operation
once it has started.</p>
   <h4 class="heading settled" data-level="4.10.2" id="design-cancellation-optional"><span class="secno">4.10.2. </span><span class="content">Support for cancellation is optional</span><a class="self-link" href="#design-cancellation-optional"></a></h4>
   <p>Support for cancellation is optional, both on part of the author of the receiver and on part of the author of the sender.</p>
   <p>If the receiver’s execution environment does not customise the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO then invoking the CPO on that receiver’s
environment will invoke the default implementation which returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>never_stop_token</c-></code>. This is a special <code class="highlight"><c- n>stoppable_token</c-></code> type that is
statically known to always return <code class="highlight">false</code> from the <code class="highlight"><c- n>stop_possible</c-><c- p>()</c-></code> method.</p>
   <p>Sender code that tries to use this stop-token will in general result in code that handles stop-requests being
compiled out and having little to no run-time overhead.</p>
   <p>If the sender doesn’t call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code>, for example because the operation does not support
cancellation, then it will simply not respond to stop-requests from the caller.</p>
   <p>Note that stop-requests are generally racy in nature as there is often a race betwen an operation completing
naturally and the stop-request being made. If the operation has already completed or past the point at which
it can be cancelled when the stop-request is sent then the stop-request may just be ignored. An application
will typically need to be able to cope with senders that might ignore a stop-request anyway.</p>
   <h4 class="heading settled" data-level="4.10.3" id="design-cancellation-racy"><span class="secno">4.10.3. </span><span class="content">Cancellation is inherently racy</span><a class="self-link" href="#design-cancellation-racy"></a></h4>
   <p>Usually, an operation will attach a stop-callback at some point inside the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> so that
a subsequent stop-request will interrupt the logic.</p>
   <p>A stop-request can be issued concurrently from another thread. This means the implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> needs to be careful to ensure that, once a stop-callback has been registered, that there are no data-races between
a potentially concurrently-executing stop-callback and the rest of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> implementation.</p>
   <p>An implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> that supports cancellation will generally need to perform (at least)
two separate steps: launch the operation, subscribe a stop-callback to the receiver’s stop-token. Care needs
to be taken depending on the order in which these two steps are performed.</p>
   <p>If the stop-callback is subscribed first and then the operation is launched, care needs to be taken to ensure
that a stop-request that invokes the stop-callback on another thread after the stop-callback is registered
but before the operation finishes launching does not either result in a missed cancellation request or a
data-race. e.g. by performing an atomic write after the launch has finished executing</p>
   <p>If the operation is launched first and then the stop-callback is subscribed, care needs to be taken to ensure
that if the launched operation completes concurrently on another thread that it does not destroy the operation-state
until after the stop-callback has been registered. e.g. by having the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> implementation write to
an atomic variable once it has finished registering the stop-callback and having the concurrent completion handler
check that variable and either call the completion-signalling operation or store the result and defer calling the
receiver’s completion-signalling operation to the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> call (which is still executing).</p>
   <p>For an example of an implementation strategy for solving these data-races see <a href="#example-async-windows-socket-recv">§ 1.4 Asynchronous Windows socket recv</a>.</p>
   <h4 class="heading settled" data-level="4.10.4" id="design-cancellation-status"><span class="secno">4.10.4. </span><span class="content">Cancellation design status</span><a class="self-link" href="#design-cancellation-status"></a></h4>
   <p>This paper currently includes the design for cancellation as proposed in <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a> - "Composable cancellation for sender-based async operations".
P2175R0 contains more details on the background motivation and prior-art and design rationale of this design.</p>
   <p>It is important to note, however, that initial review of this design in the SG1 concurrency subgroup raised some concerns
related to runtime overhead of the design in single-threaded scenarios and these concerns are still being investigated.</p>
   <p>The design of P2175R0 has been included in this paper for now, despite its potential to change, as we believe that
support for cancellation is a fundamental requirement for an async model and is required in some form to be able to
talk about the semantics of some of the algorithms proposed in this paper.</p>
   <p>This paper will be updated in the future with any changes that arise from the investigations into P2175R0.</p>
   <h3 class="heading settled" data-level="4.11" id="design-lazy-algorithms"><span class="secno">4.11. </span><span class="content">Sender factories and adaptors are lazy</span><a class="self-link" href="#design-lazy-algorithms"></a></h3>
   <p>In an earlier revision of this paper, some of the proposed algorithms supported
executing their logic eagerly; <i>i.e.</i>, before the returned sender has been
connected to a receiver and started. These algorithms were removed because eager
execution has a number of negative semantic and performance implications.</p>
   <p>We have originally included this functionality in the paper because of a long-standing
belief that eager execution is a mandatory feature to be included in the standard Executors
facility for that facility to be acceptable for accelerator vendors. A particular concern
was that we must be able to write generic algorithms that can run either eagerly or lazily,
depending on the kind of an input sender or scheduler that have been passed into them as
arguments. We considered this a requirement, because the _latency_ of launching work on an
accelerator can sometimes be considerable.</p>
   <p>However, in the process of working on this paper and implementations of the features
proposed within, our set of requirements has shifted, as we understood the different
implementation strategies that are available for the feature set of this paper better,
and, after weighting the earlier concerns against the points presented below, we
have arrived at the conclusion that a purely lazy model is enough for most algorithms,
and users who intend to launch work earlier may use an algorithm such as <code class="highlight"><c- n>ensure_started</c-></code> to achieve that goal. We have also come to deeply appreciate the fact that a purely
lazy model allows both the implementation and the compiler to have a much better
understanding of what the complete graph of tasks looks like, allowing them to better
optimize the code - also when targetting accelerators.</p>
   <h4 class="heading settled" data-level="4.11.1" id="design-lazy-algorithms-detached"><span class="secno">4.11.1. </span><span class="content">Eager execution leads to detached work or worse</span><a class="self-link" href="#design-lazy-algorithms-detached"></a></h4>
   <p>One of the questions that arises with APIs that can potentially return
eagerly-executing senders is "What happens when those senders are destructed
without a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>?" or similarly, "What happens if a call
to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> is made, but the returned operation state is destroyed
before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on that operation state"?</p>
   <p>In these cases, the operation represented by the sender is potentially executing
concurrently in another thread at the time that the destructor of the sender
and/or operation-state is running. In the case that the operation has not
completed executing by the time that the destructor is run we need to decide
what the semantics of the destructor is.</p>
   <p>There are three main strategies that can be adopted here, none of which is
particularly satisfactory:</p>
   <ol>
    <li data-md>
     <p>Make this undefined-behaviour - the caller must ensure that any
eagerly-executing sender is always joined by connecting and starting that
sender. This approach is generally pretty hostile to programmers,
particularly in the presence of exceptions, since it complicates the ability
to compose these operations.</p>
     <p>Eager operations typically need to acquire resources when they are first
called in order to start the operation early. This makes eager algorithms
prone to failure. Consider, then, what might happen in an expression such as <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>eager_op_1</c-><c- p>(),</c-> <c- n>eager_op_2</c-><c- p>())</c-></code>. Imagine <code class="highlight"><c- n>eager_op_1</c-><c- p>()</c-></code> starts an
asynchronous operation successfully, but then <code class="highlight"><c- n>eager_op_2</c-><c- p>()</c-></code> throws. For
lazy senders, that failure happens in the context of the <code class="highlight"><c- n>when_all</c-></code> algorithm, which handles the failure and ensures that async work joins on
all code paths. In this case though -- the eager case -- the child operation
has failed even before <code class="highlight"><c- n>when_all</c-></code> has been called.</p>
     <p>It then becomes the responsibility, not of the algorithm, but of the end
user to handle the exception and ensure that <code class="highlight"><c- n>eager_op_1</c-><c- p>()</c-></code> is joined before
allowing the exception to propagate. If they fail to do that, they incur
undefined behavior.</p>
    <li data-md>
     <p>Detach from the computation - let the operation continue in the background -
like an implicit call to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-><c- o>::</c-><c- n>detach</c-><c- p>()</c-></code>. While this approach can
work in some circumstances for some kinds of applications, in general it is
also pretty user-hostile; it makes it difficult to reason about the safe
destruction of resources used by these eager operations. In general,
detached work necessitates some kind of garbage collection; <i>e.g.</i>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code>, to ensure resources are kept alive until the operations
complete, and can make clean shutdown nigh impossible.</p>
    <li data-md>
     <p>Block in the destructor until the operation completes. This approach is
probably the safest to use as it preserves the structured nature of the
concurrent operations, but also introduces the potential for deadlocking the
application if the completion of the operation depends on the current thread
making forward progress.</p>
     <p>The risk of deadlock might occur, for example, if a thread-pool with a
small number of threads is executing code that creates a sender representing
an eagerly-executing operation and then calls the destructor of that sender
without joining it (e.g. because an exception was thrown). If the current
thread blocks waiting for that eager operation to complete and that eager
operation cannot complete until some entry enqueued to the thread-pool’s
queue of work is run then the thread may wait for an indefinite amount of
time. If all thread of the thread-pool are simultaneously performing such
blocking operations then deadlock can result.</p>
   </ol>
   <p>There are also minor variations on each of these choices. For example:</p>
   <ol start="4">
    <li data-md>
     <p>A variation of (1): Call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> if an eager sender is destructed
without joining it. This is the approach that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> destructor
takes.</p>
    <li data-md>
     <p>A variation of (2): Request cancellation of the operation before detaching.
This reduces the chances of operations continuing to run indefinitely in the
background once they have been detached but does not solve the
lifetime- or shutdown-related challenges.</p>
    <li data-md>
     <p>A variation of (3): Request cancellation of the operation before blocking on
its completion. This is the strategy that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>jthread</c-></code> uses for its
destructor. It reduces the risk of deadlock but does not eliminate it.</p>
   </ol>
   <h4 class="heading settled" data-level="4.11.2" id="design-lazy-algorithms-complexity"><span class="secno">4.11.2. </span><span class="content">Eager senders complicate algorithm implementations</span><a class="self-link" href="#design-lazy-algorithms-complexity"></a></h4>
   <p>Algorithms that can assume they are operating on senders with strictly lazy
semantics are able to make certain optimizations that are not available if
senders can be potentially eager. With lazy senders, an algorithm can safely
assume that a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> on an operation state strictly happens
before the execution of that async operation. This frees the algorithm from
needing to resolve potential race conditions. For example, consider an algorithm <code class="highlight"><c- n>sequence</c-></code> that puts async operations in sequence by starting an operation only
after the preceding one has completed. In an expression like <code class="highlight"><c- n>sequence</c-><c- p>(</c-><c- n>a</c-><c- p>(),</c-> <c- n>then</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>b</c-><c- p>();</c-> <c- p>}),</c-> <c- n>c</c-><c- p>())</c-></code>, one my reasonably assume that <code class="highlight"><c- n>a</c-><c- p>()</c-></code>, <code class="highlight"><c- n>b</c-><c- p>()</c-></code> and <code class="highlight"><c- n>c</c-><c- p>()</c-></code> are sequenced and therefore do not need synchronisation. Eager algorithms
break that assumption.</p>
   <p>When an algorithm needs to deal with potentially eager senders, the potential
race conditions can be resolved one of two ways, neither of which is desirable:</p>
   <ol>
    <li data-md>
     <p>Assume the worst and implement the algorithm defensively, assuming all
senders are eager. This obviously has overheads both at runtime and in
algorithm complexity. Resolving race conditions is hard.</p>
    <li data-md>
     <p>Require senders to declare whether they are eager or not with a query.
Algorithms can then implement two different implementation strategies, one
for strictly lazy senders and one for potentially eager senders. This
addresses the performance problem of (1) while compounding the complexity
problem.</p>
   </ol>
   <h4 class="heading settled" data-level="4.11.3" id="design-lazy-algorithms-runtime"><span class="secno">4.11.3. </span><span class="content">Eager senders incur cancellation-related overhead</span><a class="self-link" href="#design-lazy-algorithms-runtime"></a></h4>
   <p>Another implication of the use of eager operations is with regards to
cancellation. The eagerly executing operation will not have access to the
caller’s stop token until the sender is connected to a receiver. If we still
want to be able to cancel the eager operation then it will need to create a new
stop source and pass its associated stop token down to child operations. Then
when the returned sender is eventually connected it will register a stop
callback with the receiver’s stop token that will request stop on the eager
sender’s stop source.</p>
   <p>As the eager operation does not know at the time that it is launched what the
type of the receiver is going to be, and thus whether or not the stop token
returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-></code> is an <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unstoppable_token</c-></code> or not,
the eager operation is going to need to assume it might be later connected to a
receiver with a stop token that might actually issue a stop request. Thus it
needs to declare space in the operation state for a type-erased stop callback
and incur the runtime overhead of supporting cancellation, even if cancellation
will never be requested by the caller.</p>
   <p>The eager operation will also need to do this to support sending a stop request
to the eager operation in the case that the sender representing the eager work
is destroyed before it has been joined (assuming strategy (5) or (6) listed
above is chosen).</p>
   <h4 class="heading settled" data-level="4.11.4" id="design-lazy-algorithms-context"><span class="secno">4.11.4. </span><span class="content">Eager senders cannot access execution context from the receiver</span><a class="self-link" href="#design-lazy-algorithms-context"></a></h4>
   <p>In sender/receiver, contextual information is passed from parent operations to
their children by way of receivers. Information like stop tokens, allocators,
current scheduler, priority, and deadline are propagated to child operations
with custom receivers at the time the operation is connected. That way, each
operation has the contextual information it needs before it is started.</p>
   <p>But if the operation is started before it is connected to a receiver, then there
isn’t a way for a parent operation to communicate contextual information to its
child operations, which may complete before a receiver is ever attached.</p>
   <h3 class="heading settled" data-level="4.12" id="design-fpg"><span class="secno">4.12. </span><span class="content">Schedulers advertise their forward progress guarantees</span><a class="self-link" href="#design-fpg"></a></h3>
   <p>To decide whether a scheduler (and its associated execution context) is sufficient for a specific task, it may be necessary to know what kind of forward progress guarantees it provides for the execution agents it creates. The C++ Standard defines the following
forward progress guarantees:</p>
   <ul>
    <li data-md>
     <p><i>concurrent</i>, which requires that a thread makes progress <i>eventually</i>;</p>
    <li data-md>
     <p><i>parallel</i>, which requires that a thread makes progress once it executes a step; and</p>
    <li data-md>
     <p><i>weakly parallel</i>, which does not require that the thread makes progress.</p>
   </ul>
   <p>This paper introduces a scheduler query function, <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>, which returns one of the enumerators of a new <code class="highlight"><c- k>enum</c-></code> type, <code class="highlight"><c- n>forward_progress_guarantee</c-></code>. Each enumerator of <code class="highlight"><c- n>forward_progress_guarantee</c-></code> corresponds to one of the aforementioned
guarantees.</p>
   <h3 class="heading settled" data-level="4.13" id="design-pipeable"><span class="secno">4.13. </span><span class="content">Most sender adaptors are pipeable</span><a class="self-link" href="#design-pipeable"></a></h3>
   <p>To facilitate an intuitive syntax for composition, most sender adaptors are <dfn data-dfn-type="dfn" data-export id="pipeable">pipeable<a class="self-link" href="#pipeable"></a></dfn>; they can be composed (<dfn data-dfn-type="dfn" data-export id="piped">piped<a class="self-link" href="#piped"></a></dfn>) together with <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>.
This mechanism is similar to the <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> composition that C++ range adaptors support and draws inspiration from piping in *nix shells.
Pipeable sender adaptors take a sender as their first parameter and have no other sender parameters.</p>
   <p><code class="highlight"><c- n>a</c-> <c- o>|</c-> <c- n>b</c-></code> will pass the sender <code class="highlight"><c- n>a</c-></code> as the first argument to the pipeable sender adaptor <code class="highlight"><c- n>b</c-></code>. Pipeable sender adaptors support partial application of the parameters after the first. For example, all of the following are equivalent:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{});</c->
<c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{})(</c-><c- n>snd</c-><c- p>);</c->
<c- n>snd</c-> <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{});</c->
</pre>
   <p>Piping enables you to compose together senders with a linear syntax.
Without it, you’d have to use either nested function call syntax, which would cause a syntactic inversion of the direction of control flow, or you’d have to introduce a temporary variable for each stage of the pipeline.
Consider the following example where we want to execute first on a CPU thread pool, then on a CUDA GPU, then back on the CPU thread pool:</p>
   <table>
    <tbody>
     <tr>
      <th>Syntax Style 
      <th>Example 
     <tr>
      <th>Function call <br> (nested) 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
             <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c->
               <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
                 <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c->
                   <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
                     <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
                     <c- p>[]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>}),</c->
                   <c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>()),</c->
                 <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>}),</c->
               <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>()),</c->
             <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// result == 610</c->
</pre>
     <tr>
      <th>Function call <br> (named temporaries) 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd0</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>());</c->
<c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd0</c-><c- p>,</c-> <c- p>[]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>());</c->
<c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>})</c->
<c- k>auto</c-> <c- n>snd4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd3</c-><c- p>,</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
<c- k>auto</c-> <c- n>snd5</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd4</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- o>*</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd4</c-><c- p>);</c->
<c- c1>// result == 610</c->
</pre>
     <tr>
      <th>Pipe 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>})</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>})</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// result == 610</c->
</pre>
   </table>
   <p>Certain sender adaptors are not pipeable, because using the pipeline syntax can result in confusion of the semantics of the adaptors involved. Specifically, the following sender adaptors are not pipeable.</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-></code>: Since this sender adaptor takes a variadic pack of senders, a partially applied form would be ambiguous with a non partially applied form with an arity of one less.</p>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code>: This sender adaptor changes how the sender passed to it is executed, not what happens to its result, but allowing it in a pipeline makes it read as if it performed a function more similar to <code class="highlight"><c- n>transfer</c-></code>.</p>
   </ul>
   <p>Sender consumers could be made pipeable, but we have chosen to not do so.
However, since these are terminal nodes in a pipeline and nothing can be piped after them, we believe a pipe syntax may be confusing as well as unnecessary, as consumers cannot be chained.
We believe sender consumers read better with function call syntax.</p>
   <h3 class="heading settled" data-level="4.14" id="design-range-of-senders"><span class="secno">4.14. </span><span class="content">A range of senders represents an async sequence of data</span><a class="self-link" href="#design-range-of-senders"></a></h3>
   <p>Senders represent a single unit of asynchronous work. In many cases though, what is being modelled is a sequence of data arriving asynchronously, and you want computation to happen on demand, when each element arrives. This requires nothing more than what is in this paper and the range support in C++20. A range of senders would allow you to model such input as keystrikes, mouse movements, sensor readings, or network requests.</p>
   <p>Given some expression <code class="highlight"><i><c- n>R</c-></i></code> that is a range of senders, consider the following in a coroutine that returns an async generator type:</p>
<pre class="highlight"><c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- n>snd</c-> <c- o>:</c-> <i><c- n>R</c-></i><c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c-><c- k>auto</c-> <c- n>opt</c-> <c- o>=</c-> <c- k>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>)))</c->
    <c- k>co_yield</c-> <c- n>fn</c-><c- p>(</c-><c- o>*</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>opt</c-><c- p>));</c->
  <c- k>else</c->
    <c- k>break</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>This transforms each element of the asynchronous sequence <code class="highlight"><i><c- n>R</c-></i></code> with the function <code class="highlight"><c- n>fn</c-></code> on demand, as the data arrives. The result is a new asynchronous sequence of the transformed values.</p>
   <p>Now imagine that <code class="highlight"><i><c- n>R</c-></i></code> is the simple expression <code class="highlight"><c- n>views</c-><c- o>::</c-><c- n>iota</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-> <c- o>|</c-> <c- n>views</c-><c- o>::</c-><c- n>transform</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>)</c-></code>. This creates a lazy range of senders, each of which completes immediately with monotonically increasing integers. The above code churns through the range, generating a new infine asynchronous range of values [<code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-></code>, <code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code>, <code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>2</c-><c- p>)</c-></code>, ...].</p>
   <p>Far more interesting would be if <code class="highlight"><i><c- n>R</c-></i></code> were a range of senders representing, say, user actions in a UI. The above code gives a simple way to respond to user actions on demand.</p>
   <h3 class="heading settled" data-level="4.15" id="design-partial-success"><span class="secno">4.15. </span><span class="content">Senders can represent partial success</span><a class="self-link" href="#design-partial-success"></a></h3>
   <p>Receivers have three ways they can complete: with success, failure, or cancellation. This begs the question of how they can be used to represent async operations that <em>partially</em> succeed. For example, consider an API that reads from a socket. The connection could drop after the API has filled in some of the buffer. In cases like that, it makes sense to want to report both that the connection dropped and that some data has been successfully read.</p>
   <p>Often in the case of partial success, the error condition is not fatal nor does it mean the API has failed to satisfy its post-conditions. It is merely an extra piece of information about the nature of the completion. In those cases, "partial success" is another way of saying "success". As a result, it is sensible to pass both the error code and the result (if any) through the value channel, as shown below:</p>
<pre class="highlight"><c- c1>// Capture a buffer for read_socket_async to fill in</c->
<c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>></c-><c- p>{})</c->
  <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([</c-><c- n>socket</c-><c- p>](</c-><c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>>&amp;</c-> <c- n>buff</c-><c- p>)</c-> <c- p>{</c->
      <c- c1>// read_socket_async completes with two values: an error_code and</c->
      <c- c1>// a count of bytes:</c->
      <c- k>return</c-> <c- n>read_socket_async</c-><c- p>(</c-><c- n>socket</c-><c- p>,</c-> <c- n>span</c-><c- p>{</c-><c- n>buff</c-><c- p>})</c->
          <c- c1>// For success (partial and full), specify the next action:</c->
        <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([](</c-><c- n>error_code</c-> <c- n>err</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->
            <c- k>if</c-> <c- p>(</c-><c- n>err</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
              <c- c1>// OK, partial success. Decide how to deal with the partial results</c->
            <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
              <c- c1>// OK, full success here.</c->
            <c- p>}</c->
          <c- p>});</c->
    <c- p>})</c->
</pre>
   <p>In other cases, the partial success is more of a partial <em>failure</em>. That happens when the error condition indicates that in some way the function failed to satisfy its post-conditions. In those cases, sending the error through the value channel loses valuable contextual information. It’s possible that bundling the error and the incomplete results into an object and passing it through the error channel makes more sense. In that way, generic algorithms will not miss the fact that a post-condition has not been met and react inappropriately.</p>
   <p>Another possibility is for an async API to return a <em>range</em> of senders: if the API completes with full success, full error, or cancellation, the returned range contains just one sender with the result. Otherwise, if the API partially fails (doesn’t satisfy its post-conditions, but some incomplete result is available), the returned range would have <em>two</em> senders: the first containing the partial result, and the second containing the error. Such an API might be used in a coroutine as follows:</p>
<pre class="highlight"><c- c1>// Declare a buffer for read_socket_async to fill in</c->
<c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>></c-> <c- n>buff</c-><c- p>;</c->

<c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- n>snd</c-> <c- o>:</c-> <c- n>read_socket_async</c-><c- p>(</c-><c- n>socket</c-><c- p>,</c-> <c- n>span</c-><c- p>{</c-><c- n>buff</c-><c- p>}))</c-> <c- p>{</c->
  <c- k>try</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>size_t</c-><c- o>></c-> <c- n>bytes_read</c-> <c- o>=</c->
          <c- k>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>)))</c->
      <c- c1>// OK, we read some bytes into buff. Process them here....</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- c1>// The socket read was cancelled and returned no data. React</c->
      <c- c1>// appropriately.</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
    <c- c1>// read_socket_async failed to meet its post-conditions.</c->
    <c- c1>// Do some cleanup and propagate the error...</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
   <p>Finally, it’s possible to combine these two approaches when the API can both partially succeed (meeting its post-conditions) and partially fail (not meeting its post-conditions).</p>
   <h3 class="heading settled" data-level="4.16" id="design-awaitables-are-senders"><span class="secno">4.16. </span><span class="content">All awaitables are senders</span><a class="self-link" href="#design-awaitables-are-senders"></a></h3>
   <p>Since C++20 added coroutines to the standard, we expect that coroutines and awaitables will be how a great many will choose to express their asynchronous code. However, in this paper, we are proposing to add a suite of asynchronous algorithms that accept senders, not awaitables. One might wonder whether and how these algorithms will be accessible to those who choose coroutines instead of senders.</p>
   <p>In truth there will be no problem because all generally awaitable types
automatically model the <code class="highlight"><c- n>sender</c-></code> concept. The adaptation is transparent and
happens in the sender customization points, which are aware of awaitables. (By
"generally awaitable" we mean types that don’t require custom <code class="highlight"><c- n>await_transform</c-></code> trickery from a promise type to make them awaitable.)</p>
   <p>For an example, imagine a coroutine type called <code class="highlight"><c- n>task</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> that knows nothing
about senders. It doesn’t implement any of the sender customization points.
Despite that fact, and despite the fact that the <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> algorithm is constrained with the <code class="highlight"><c- n>sender</c-></code> concept, the following would compile
and do what the user wants:</p>
<pre class="language-c++ highlight"><c- n>task</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>doSomeAsyncWork</c-><c- p>();</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
  <c- c1>// OK, awaitable types satisfy the requirements for senders:</c->
  <c- k>auto</c-> <c- n>o</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>doSomeAsyncWork</c-><c- p>());</c->
<c- p>}</c->
</pre>
   <p>Since awaitables are senders, writing a sender-based asynchronous algorithm is trivial if you have a coroutine task type: implement the algorithm as a coroutine. If you are not bothered by the possibility of allocations and indirections as a result of using coroutines, then there is no need to ever write a sender, a receiver, or an operation state.</p>
   <h3 class="heading settled" data-level="4.17" id="design-senders-are-awaitable"><span class="secno">4.17. </span><span class="content">Many senders can be trivially made awaitable</span><a class="self-link" href="#design-senders-are-awaitable"></a></h3>
   <p>If you choose to implement your sender-based algorithms as coroutines, you’ll run into the issue of how to retrieve results from a passed-in sender. This is not a problem. If the coroutine type opts in to sender support -- trivial with the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> utility -- then a large class of senders are transparently awaitable from within the coroutine.</p>
   <p>For example, consider the following trivial implementation of the sender-based <code class="highlight"><c- n>retry</c-></code> algorithm:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
  <c- k>requires</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;></c-> <c- c1>// See </c-><a href="#spec-execution.coro_utils.as_awaitable"><c- c1>[exec.as_awaitable]</c-></a>
<c- n>task</c-><c- o>&lt;</c-><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-> <c- n>retry</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(;;)</c-> <c- p>{</c->
    <c- k>try</c-> <c- p>{</c->
      <c- k>co_return</c-> <c- k>co_await</c-> <c- n>s</c-><c- p>;</c->
    <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- p>}</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
   <p>Only <em>some</em> senders can be made awaitable directly because of the fact that callbacks are more expressive than coroutines. An awaitable expression has a single type: the result value of the async operation. In contrast, a callback can accept multiple arguments as the result of an operation. What’s more, the callback can have overloaded function call signatures that take different sets of arguments. There is no way to automatically map such senders into awaitables. The <code class="highlight"><c- n>with_awaitable_senders</c-></code> utility recognizes as awaitables those senders that send a single value of a single type. To await another kind of sender, a user would have to first map its value channel into a single value of a single type -- say, with the <code class="highlight"><c- n>into_variant</c-></code> sender algorithm -- before <code class="highlight"><c- k>co_await</c-></code>-ing that sender.</p>
   <h3 class="heading settled" data-level="4.18" id="design-native-coro-unwind"><span class="secno">4.18. </span><span class="content">Cancellation of a sender can unwind a stack of coroutines</span><a class="self-link" href="#design-native-coro-unwind"></a></h3>
   <p>When looking at the sender-based <code class="highlight"><c- n>retry</c-></code> algorithm in the previous section, we can see that the value and error cases are correctly handled. But what about cancellation? What happens to a coroutine that is suspended awaiting a sender that completes by calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>?</p>
   <p>When your task type’s promise inherits from <code class="highlight"><c- n>with_awaitable_senders</c-></code>, what happens is this: the coroutine behaves as if an <em>uncatchable exception</em> had been thrown from the <code class="highlight"><c- k>co_await</c-></code> expression. (It is not really an exception, but it’s helpful to think of it that way.) Provided that the promise types of the calling coroutines also inherit from <code class="highlight"><c- n>with_awaitable_senders</c-></code>, or more generally implement a member function called <code class="highlight"><c- n>unhandled_stopped</c-></code>, the exception unwinds the chain of coroutines as if an exception were thrown except that it bypasses <code class="highlight"><c- k>catch</c-><c- p>(...)</c-></code> clauses.</p>
   <p>In order to "catch" this uncatchable stopped exception, one of the calling coroutines in the stack would have to await a sender that maps the stopped channel into either a value or an error. That is achievable with the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code>, or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> sender adaptors. For instance, we can use <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> to "catch" the stopped signal and map it into an empty optional as shown below:</p>
<pre class="language-c++ highlight"><c- k>if</c-> <c- p>(</c-><c- k>auto</c-> <c- n>opt</c-> <c- o>=</c-> <c- n>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>some_sender</c-><c- p>))</c-> <c- p>{</c->
  <c- c1>// OK, some_sender completed successfully, and opt contains the result.</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- c1>// some_sender completed with a cancellation signal.</c->
<c- p>}</c->
</pre>
   <p>As described in the section <a href="#design-awaitables-are-senders">"All awaitables are senders"</a>, the sender customization points recognize awaitables and adapt them transparently to model the sender concept. When <code class="highlight"><c- n>connect</c-></code>-ing an awaitable and a receiver, the adaptation layer awaits the awaitable within a coroutine that implements <code class="highlight"><c- n>unhandled_stopped</c-></code> in its promise type. The effect of this is that an "uncatchable" stopped exception propagates seamlessly out of awaitables, causing <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> to be called on the receiver.</p>
   <p>Obviously, <code class="highlight"><c- n>unhandled_stopped</c-></code> is a library extension of the coroutine promise interface. Many promise types will not implement <code class="highlight"><c- n>unhandled_stopped</c-></code>. When an uncatchable stopped exception tries to propagate through such a coroutine, it is treated as an unhandled exception and <code class="highlight"><c- n>terminate</c-></code> is called. The solution, as described above, is to use a sender adaptor to handle the stopped exception before awaiting it. It goes without saying that any future Standard Library coroutine types ought to implement <code class="highlight"><c- n>unhandled_stopped</c-></code>. The author of <a data-link-type="biblio" href="https://wg21.link/p1056r1"><cite>Add lazy coroutine (coroutine task) type</cite></a>, which proposes a standard coroutine task type, is in agreement.</p>
   <h3 class="heading settled" data-level="4.19" id="design-parallel-algorithms"><span class="secno">4.19. </span><span class="content">Composition with parallel algorithms</span><a class="self-link" href="#design-parallel-algorithms"></a></h3>
   <p>The C++ Standard Library provides a large number of algorithms that offer the potential for non-sequential execution via the use of execution policies. The set of algorithms with execution policy overloads are often referred to as "parallel algorithms", although
additional policies are available.</p>
   <p>Existing policies, such as <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>par</c-></code>, give the implementation permission to execute the algorithm in parallel. However, the choice of execution resources used to perform the work is left to the implementation.</p>
   <p>We will propose a customization point for combining schedulers with policies in order to provide control over where work will execute.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>ExecutionPolicy</c-><c- o>></c->
<i><c- n>implementation</c-><c- o>-</c-><c- n>defined</c-></i> <c- n>executing_on</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c-><c- p>,</c->
    <c- n>ExecutionPolicy</c-> <c- o>&amp;&amp;</c-> <c- n>policy</c->
<c- p>);</c->
</pre>
   <p>This function would return an object of an implementation-defined type which can be used in place of an execution policy as the first argument to one of the parallel algorithms. The overload selected by that object should execute its computation as requested by <code class="highlight"><c- n>policy</c-></code> while using <code class="highlight"><c- n>scheduler</c-></code> to create any work to be run. The expression may be ill-formed if <code class="highlight"><c- n>scheduler</c-></code> is not able to support the given policy.</p>
   <p>The existing parallel algorithms are synchronous; all of the effects performed by the computation are complete before the algorithm returns to its caller. This remains unchanged with the <code class="highlight"><c- n>executing_on</c-></code> customization point.</p>
   <p>In the future, we expect additional papers will propose asynchronous forms of the parallel algorithms which (1) return senders rather than values or <code class="highlight"><c- b>void</c-></code> and (2) where a customization point pairing a sender with an execution policy would similarly be used to
obtain an object of implementation-defined type to be provided as the first argument to the algorithm.</p>
   <h3 class="heading settled" data-level="4.20" id="design-sender-factories"><span class="secno">4.20. </span><span class="content">User-facing sender factories</span><a class="self-link" href="#design-sender-factories"></a></h3>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-factory">sender factory</dfn> is an <a data-link-type="dfn" href="#algorithm" id="ref-for-algorithm">algorithm</a> that takes no senders as parameters and returns a sender.</p>
   <h4 class="heading settled" data-level="4.20.1" id="design-sender-factory-schedule"><span class="secno">4.20.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code></span><a class="self-link" href="#design-sender-factory-schedule"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>schedule</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the start of a task graph on the provided scheduler. See <a href="#design-schedulers">§ 4.2 Schedulers represent execution contexts</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch1</c-> <c- o>=</c-> <c- n>get_system_thread_pool</c-><c- p>().</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch1</c-><c- p>);</c->
<c- c1>// snd1 describes the creation of a new task on the system thread pool</c->
</pre>
   <h4 class="heading settled" data-level="4.20.2" id="design-sender-factory-just"><span class="secno">4.20.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code></span><a class="self-link" href="#design-sender-factory-just"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just</c-><c- p>(</c->
    <c- k>auto</c-> <c- p>...</c-><c- o>&amp;&amp;</c-> <c- n>values</c->
<c- p>);</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers③">completion schedulers</a>, which <a data-link-type="dfn" href="#send" id="ref-for-send②">sends</a> the provided values. The input values are decay-copied into the returned sender. When the returned sender is connected to a receiver, the values are moved into the operation state if the sender is an rvalue; otherwise, they are copied. Then xvalues referencing the values in the operation state are passed to the receiver’s <code class="highlight"><c- n>set_value</c-></code>.</p>
<pre class="language-c++ highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- mf>3.14</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- b>double</c-> <c- n>d</c-><c- p>)</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>d</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- mf>3.14</c-><c- p>,</c-> <c- mi>42</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- b>double</c-> <c- n>d</c-><c- p>,</c-> <c- b>int</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>d</c-> <c- o>&lt;&lt;</c-> <c- s>", "</c-> <c- o>&lt;&lt;</c-> <c- n>i</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>std</c-><c- o>::</c-><c- n>vector</c-> <c- n>v3</c-><c- p>{</c-><c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>5</c-><c- p>};</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>v3</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd3</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>&amp;&amp;</c-> <c- n>v3copy</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>e</c-> <c- o>:</c-> <c- n>v3copy</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>*=</c-> <c- mi>2</c-><c- p>;</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>v3copy</c-><c- p>);</c->
<c- p>}</c->
<c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>v3copy</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>then3</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// v3 contains {1, 2, 3, 4, 5}; v3copy will contain {2, 4, 6, 8, 10}.</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- p>{</c-><c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>5</c-><c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd4</c-><c- p>),</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>&amp;&amp;</c-> <c- n>v4</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>e</c-> <c- o>:</c-> <c- n>v4</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>*=</c-> <c- mi>2</c-><c- p>;</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>v4</c-><c- p>);</c->
<c- p>});</c->
<c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>v4</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>then4</c-><c- p>)).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// v4 contains {2, 4, 6, 8, 10}. No vectors were copied in this example.</c->
</pre>
   <h4 class="heading settled" data-level="4.20.3" id="design-sender-factory-transfer_just"><span class="secno">4.20.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code></span><a class="self-link" href="#design-sender-factory-transfer_just"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>transfer_just</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c-><c- p>,</c->
    <c- k>auto</c-> <c- p>...</c-><c- o>&amp;&amp;</c-> <c- n>values</c->
<c- p>);</c->
</pre>
   <p>Returns a sender whose value <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers④">completion scheduler</a> is the provided scheduler, which <a data-link-type="dfn" href="#send" id="ref-for-send③">sends</a> the provided values in the same manner as <code class="highlight"><c- n>just</c-></code>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>vals</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-><c- p>(</c->
    <c- n>get_system_thread_pool</c-><c- p>().</c-><c- n>scheduler</c-><c- p>(),</c->
    <c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- mi>3</c->
<c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>vals</c-><c- p>,</c-> <c- p>[](</c-><c- k>auto</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>print</c-><c- p>(</c-><c- n>args</c-><c- p>...);</c->
<c- p>});</c->
<c- c1>// when snd is executed, it will print "123"</c->
</pre>
   <p>This adaptor is included as it greatly simplifies lifting values into senders.</p>
   <h4 class="heading settled" data-level="4.20.4" id="design-sender-factory-just_error"><span class="secno">4.20.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code></span><a class="self-link" href="#design-sender-factory-just_error"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just_error</c-><c- p>(</c->
    <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>error</c->
<c- p>);</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers⑤">completion schedulers</a>, which completes with the specified error. If the provided error is an lvalue reference, a copy is made inside the returned sender and a non-const lvalue reference to the copy is sent to the receiver’s <code class="highlight"><c- n>set_error</c-></code>. If the provided value is an rvalue reference, it is moved into the returned sender and an rvalue reference to it is sent to the receiver’s <code class="highlight"><c- n>set_error</c-></code>.</p>
   <h4 class="heading settled" data-level="4.20.5" id="design-sender-factory-just_stopped"><span class="secno">4.20.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code></span><a class="self-link" href="#design-sender-factory-just_stopped"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just_stopped</c-><c- p>();</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers⑥">completion schedulers</a>, which completes immediately by calling the receiver’s <code class="highlight"><c- n>set_stopped</c-></code>.</p>
   <h4 class="heading settled" data-level="4.20.6" id="design-sender-factory-read"><span class="secno">4.20.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code></span><a class="self-link" href="#design-sender-factory-read"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>read</c-><c- p>(</c-><c- k>auto</c-> <c- n>tag</c-><c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_scheduler</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_delegatee_scheduler</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_allocator</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_stop_token</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>Returns a sender that reaches into a receiver’s environment and pulls out the current value associated with the customization point denoted by <code class="highlight"><c- n>Tag</c-></code>. It then sends the value read back to the receiver through the value channel. For instance, <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> (with no arguments) is a sender that asks the receiver for the currently suggested <code class="highlight"><c- n>scheduler</c-></code> and passes it to the receiver’s <code class="highlight"><c- n>set_value</c-></code> completion-signal.</p>
   <p>This can be useful when scheduling nested dependent work. The following sender pulls the current schduler into the value channel and then schedules more work onto it.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>task</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>()</c->
    <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([](</c-><c- k>auto</c-> <c- n>sched</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <i><c- n>some</c-> <c- n>nested</c-> <c- n>work</c-> <c- n>here</c-></i><c- p>);</c->
    <c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>)</c-> <c- p>);</c-> <c- c1>// wait for it to finish</c->
</pre>
   <p>This code uses the fact that <code class="highlight"><c- n>sync_wait</c-></code> associates a scheduler with the receiver that it connects with <code class="highlight"><c- n>task</c-></code>. <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> reads that scheduler out of the receiver, and passes it to <code class="highlight"><c- n>let_value</c-></code>'s receiver’s <code class="highlight"><c- n>set_value</c-></code> function, which in turn passes it to the lambda. That lambda returns a new sender that uses the scheduler to schedule some nested work onto <code class="highlight"><c- n>sync_wait</c-></code>'s scheduler.</p>
   <h3 class="heading settled" data-level="4.21" id="design-sender-adaptors"><span class="secno">4.21. </span><span class="content">User-facing sender adaptors</span><a class="self-link" href="#design-sender-adaptors"></a></h3>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-adaptor">sender adaptor</dfn> is an <a data-link-type="dfn" href="#algorithm" id="ref-for-algorithm①">algorithm</a> that takes one or more senders, which it may <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, as parameters, and returns a sender, whose completion is related to the sender arguments it has received.</p>
   <p>Sender adaptors are <i>lazy</i>, that is, they are never allowed to submit any work for execution prior to the returned sender being <dfn data-dfn-type="dfn" data-export data-lt="start" id="start">started<a class="self-link" href="#start"></a></dfn> later on, and are also guaranteed to not start any input senders passed into them. Sender consumers
such as <a href="#design-sender-consumer-start_detached">§ 4.22.1 execution::start_detached</a> and <a href="#design-sender-consumer-sync_wait">§ 4.22.2 this_thread::sync_wait</a> start senders.</p>
   <p>For more implementer-centric description of starting senders, see <a href="#design-laziness">§ 5.5 Sender adaptors are lazy</a>.</p>
   <h4 class="heading settled" data-level="4.21.1" id="design-sender-adaptor-transfer"><span class="secno">4.21.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span><a class="self-link" href="#design-sender-adaptor-transfer"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>transfer</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the transition from the execution agent of the input sender to the execution agent of the target scheduler. See <a href="#design-transitions">§ 4.6 Execution context transitions are explicit</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cpu_sched</c-> <c- o>=</c-> <c- n>get_system_thread_pool</c-><c- p>().</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>gpu_sched</c-> <c- o>=</c-> <c- n>cuda</c-><c- o>::</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>cpu_task</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cpu_sched</c-><c- p>);</c->
<c- c1>// cpu_task describes the creation of a new task on the system thread pool</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>gpu_task</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>cpu_task</c-><c- p>,</c-> <c- n>gpu_sched</c-><c- p>);</c->
<c- c1>// gpu_task describes the transition of the task graph described by cpu_task to the gpu</c->
</pre>
   <h4 class="heading settled" data-level="4.21.2" id="design-sender-adaptor-then"><span class="secno">4.21.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code></span><a class="self-link" href="#design-sender-adaptor-then"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>then</c-></code> returns a sender describing the task graph described by the input sender, with an added node of invoking the provided function with the values <a data-link-type="dfn" href="#send" id="ref-for-send④">sent</a> by the input sender as arguments.</p>
   <p><code class="highlight"><c- n>then</c-></code> is <strong>guaranteed</strong> to not begin executing <code class="highlight"><c- n>function</c-></code> until the returned sender is started.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-> <c- o>=</c-> <c- n>get_input</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>input</c-><c- p>,</c-> <c- p>[](</c-><c- k>auto</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>print</c-><c- p>(</c-><c- n>args</c-><c- p>...);</c->
<c- p>});</c->
<c- c1>// snd describes the work described by pred</c->
<c- c1>// followed by printing all of the values sent by pred</c->
</pre>
   <p>This adaptor is included as it is necessary for writing any sender code that actually performs a useful function.</p>
   <h4 class="heading settled" data-level="4.21.3" id="design-sender-adaptor-upon"><span class="secno">4.21.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_</c-><c- o>*</c-></code></span><a class="self-link" href="#design-sender-adaptor-upon"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>upon_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>errors</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>upon_stopped</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-> <c- k>auto</c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>upon_error</c-></code> and <code class="highlight"><c- n>upon_stopped</c-></code> are similar to <code class="highlight"><c- n>then</c-></code>, but where <code class="highlight"><c- n>then</c-></code> works with values sent by the input sender, <code class="highlight"><c- n>upon_error</c-></code> works with errors, and <code class="highlight"><c- n>upon_stopped</c-></code> is invoked when the "stopped" signal is sent.</p>
   <h4 class="heading settled" data-level="4.21.4" id="design-sender-adaptor-let"><span class="secno">4.21.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span><a class="self-link" href="#design-sender-adaptor-let"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_value</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>errors</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_stopped</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-> <c- k>auto</c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>let_value</c-></code> is very similar to <code class="highlight"><c- n>then</c-></code>: when it is started, it invokes the provided function with the values <a data-link-type="dfn" href="#send" id="ref-for-send⑤">sent</a> by the input sender as arguments. However, where the sender returned from <code class="highlight"><c- n>then</c-></code> sends exactly what that function ends up returning - <code class="highlight"><c- n>let_value</c-></code> requires that the function return a sender, and the sender returned by <code class="highlight"><c- n>let_value</c-></code> sends the values sent by the sender returned from the callback. This is similar to the notion of "future unwrapping" in future/promise-based frameworks.</p>
   <p><code class="highlight"><c- n>let_value</c-></code> is <strong>guaranteed</strong> to not begin executing <code class="highlight"><c- n>function</c-></code> until the returned sender is started.</p>
   <p><code class="highlight"><c- n>let_error</c-></code> and <code class="highlight"><c- n>let_stopped</c-></code> are similar to <code class="highlight"><c- n>let_value</c-></code>, but where <code class="highlight"><c- n>let_value</c-></code> works with values sent by the input sender, <code class="highlight"><c- n>let_error</c-></code> works with errors, and <code class="highlight"><c- n>let_stopped</c-></code> is invoked when the "stopped" signal is sent.</p>
   <h4 class="heading settled" data-level="4.21.5" id="design-sender-adaptor-on"><span class="secno">4.21.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code></span><a class="self-link" href="#design-sender-adaptor-on"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>on</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender which, when started, will start the provided sender on an execution agent belonging to the execution context associated with the provided scheduler. This returned sender has no <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers⑦">completion schedulers</a>.</p>
   <h4 class="heading settled" data-level="4.21.6" id="design-sender-adaptor-into_variant"><span class="secno">4.21.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code></span><a class="self-link" href="#design-sender-adaptor-into_variant"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>into_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender which sends a variant of tuples of all the possible sets of types sent by the input sender. Senders can send multiple sets of values depending on runtime conditions; this is a helper function that turns them into a single variant value.</p>
   <h4 class="heading settled" data-level="4.21.7" id="design-sender-adaptor-stopped_as_optional"><span class="secno">4.21.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code></span><a class="self-link" href="#design-sender-adaptor-stopped_as_optional"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_as_optional</c-><c- p>(</c->
    <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender that maps the value channel from a <code class="highlight"><c- n>T</c-></code> to an <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, and maps the stopped channel to a value of an empty <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>.</p>
   <h4 class="heading settled" data-level="4.21.8" id="design-sender-adaptor-stopped_as_error"><span class="secno">4.21.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code></span><a class="self-link" href="#design-sender-adaptor-stopped_as_error"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>move_constructible</c-> <c- n>Error</c-><c- o>></c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_as_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-><c- p>,</c->
    <c- n>Error</c-> <c- n>err</c->
<c- p>);</c->
</pre>
   <p>Returns a sender that maps the stopped channel to an error of <code class="highlight"><c- n>err</c-></code>.</p>
   <h4 class="heading settled" data-level="4.21.9" id="design-sender-adaptor-bulk"><span class="secno">4.21.9. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code></span><a class="self-link" href="#design-sender-adaptor-bulk"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>integral</c-> <c- k>auto</c-> <c- n>shape</c-><c- p>,</c->
    <c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>size</c-><c- p>),</c-> <i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the task of invoking the provided function with every index in the provided shape along with the values sent by the input sender. The returned sender completes once all invocations have completed, or an error has occurred. If it completes
by sending values, they are equivalent to those sent by the input sender.</p>
   <p>No instance of <code class="highlight"><c- n>function</c-></code> will begin executing until the returned sender is started. Each invocation of <code class="highlight"><c- n>function</c-></code> runs in an execution agent whose forward progress guarantees are determined by the scheduler on which they are run. All agents created by a single use
of <code class="highlight"><c- n>bulk</c-></code> execute with the same guarantee. The number of execution agents used by <code class="highlight"><c- n>bulk</c-></code> is not specified. This allows a scheduler to execute some invocations of the <code class="highlight"><c- n>function</c-></code> in parallel.</p>
   <p>In this proposal, only integral types are used to specify the shape of the bulk section. We expect that future papers may wish to explore extensions of the interface to explore additional kinds of shapes, such as multi-dimensional grids, that are commonly used for
parallel computing tasks.</p>
   <h4 class="heading settled" data-level="4.21.10" id="design-sender-adaptor-split"><span class="secno">4.21.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code></span><a class="self-link" href="#design-sender-adaptor-split"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>split</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c-><c- p>);</c->
</pre>
   <p>If the provided sender is a multi-shot sender, returns that sender. Otherwise, returns a multi-shot sender which sends values equivalent to the values sent by the provided sender. See <a href="#design-shot">§ 4.7 Senders can be either multi-shot or single-shot</a>.</p>
   <h4 class="heading settled" data-level="4.21.11" id="design-sender-adaptor-when_all"><span class="secno">4.21.11. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code></span><a class="self-link" href="#design-sender-adaptor-when_all"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>when_all</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>when_all_with_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>when_all</c-></code> returns a sender that completes once all of the input senders have completed. It is constrained to only accept senders that can complete with a single set of values (_i.e._, it only calls one overload of <code class="highlight"><c- n>set_value</c-></code> on its receiver). The values sent by this sender are the values sent by each of the input senders, in order of the arguments passed to <code class="highlight"><c- n>when_all</c-></code>. It completes inline on the execution context on which the last input sender completes, unless stop is requested before <code class="highlight"><c- n>when_all</c-></code> is started, in which case it completes inline within the call to <code class="highlight"><c- n>start</c-></code>.</p>
   <p><code class="highlight"><c- n>when_all_with_variant</c-></code> does the same, but it adapts all the input senders using <code class="highlight"><c- n>into_variant</c-></code>, and so it does not constrain the input arguments as <code class="highlight"><c- n>when_all</c-></code> does.</p>
   <p>The returned sender has no <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers⑧">completion schedulers</a>.</p>
   <p>See <a href="#design-join">§ 4.9 Senders are joinable</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_abc</c-> <c- o>=</c-> <c- p>...;</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>both</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c->
    <c- n>sends_1</c-><c- p>,</c->
    <c- n>sends_abc</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- k>final</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>both</c-><c- p>,</c-> <c- p>[](</c-><c- k>auto</c-><c- p>...</c-> <c- n>args</c-><c- p>){</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>format</c-><c- p>(</c-><c- s>"the two args: {}, {}"</c-><c- p>,</c-> <c- n>args</c-><c- p>...);</c->
<c- p>});</c->
<c- c1>// when final executes, it will print "the two args: 1, abc"</c->
</pre>
   <h4 class="heading settled" data-level="4.21.12" id="design-sender-adaptor-transfer_when_all"><span class="secno">4.21.12. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code></span><a class="self-link" href="#design-sender-adaptor-transfer_when_all"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>transfer_when_all</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>transfer_when_all_with_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->
</pre>
   <p>Similar to <a href="#design-sender-adaptor-when_all">§ 4.21.11 execution::when_all</a>, but returns a sender whose value <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers⑨">completion scheduler</a> is the provided scheduler.</p>
   <p>See <a href="#design-join">§ 4.9 Senders are joinable</a>.</p>
   <h4 class="heading settled" data-level="4.21.13" id="design-sender-adaptor-ensure_started"><span class="secno">4.21.13. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code></span><a class="self-link" href="#design-sender-adaptor-ensure_started"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>ensure_started</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>);</c->
</pre>
   <p>Once <code class="highlight"><c- n>ensure_started</c-></code> returns, it is known that the provided sender has been <a data-link-type="dfn" href="#connect" id="ref-for-connect">connected</a> and <code class="highlight"><c- n>start</c-></code> has been called on the resulting operation state (see <a href="#design-states">§ 5.2 Operation states represent work</a>); in other words, the work described by the provided sender has been submitted
for execution on the appropriate execution contexts. Returns a sender which completes when the provided sender completes and sends values equivalent to those of the provided sender.</p>
   <p>If the returned sender is destroyed before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> is called, or if <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> is called but the
returned operation-state is destroyed before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> is called, then a stop-request is sent to the eagerly launched
operation and the operation is detached and will run to completion in the background. Its result will be discarded when it
eventually completes.</p>
   <p>Note that the application will need to make sure that resources are kept alive in the case that the operation detaches.
e.g. by holding a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code> to those resources or otherwise having some out-of-band way to signal completion of
the operation so that resource release can be sequenced after the completion.</p>
   <h3 class="heading settled" data-level="4.22" id="design-sender-consumers"><span class="secno">4.22. </span><span class="content">User-facing sender consumers</span><a class="self-link" href="#design-sender-consumers"></a></h3>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-consumer">sender consumer</dfn> is an <a data-link-type="dfn" href="#algorithm" id="ref-for-algorithm②">algorithm</a> that takes one or more senders, which it may <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, as parameters, and does not return a sender.</p>
   <h4 class="heading settled" data-level="4.22.1" id="design-sender-consumer-start_detached"><span class="secno">4.22.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code></span><a class="self-link" href="#design-sender-consumer-start_detached"></a></h4>
<pre class="highlight"><c- b>void</c-> <c- nf>start_detached</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>);</c->
</pre>
   <p>Like <code class="highlight"><c- n>ensure_started</c-></code>, but does not return a value; if the provided sender sends an error instead of a value, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> is called.</p>
   <h4 class="heading settled" data-level="4.22.2" id="design-sender-consumer-sync_wait"><span class="secno">4.22.2. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code></span><a class="self-link" href="#design-sender-consumer-sync_wait"></a></h4>
<pre class="highlight"><c- k>auto</c-> <c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- k>requires</c-> <c- p>(</c-><i><c- n>always</c-><c- o>-</c-><c- n>sends</c-><c- o>-</c-><c- n>same</c-><c- o>-</c-><c- n>values</c-></i><c- p>(</c-><c- n>sender</c-><c- p>))</c->
    <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>>></c-><c- p>;</c->
</pre>
   <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> is a sender consumer that submits the work described by the provided sender for execution, similarly to <code class="highlight"><c- n>ensure_started</c-></code>, except that it blocks <b>the current <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> or thread of <code class="highlight"><c- n>main</c-></code></b> until the work is completed, and returns
an optional tuple of values that were sent by the provided sender on its completion of work. Where <a href="#design-sender-factory-schedule">§ 4.20.1 execution::schedule</a> and <a href="#design-sender-factory-transfer_just">§ 4.20.3 execution::transfer_just</a> are meant to <i>enter</i> the domain of senders, <code class="highlight"><c- n>sync_wait</c-></code> is meant to <i>exit</i> the domain of
senders, retrieving the result of the task graph.</p>
   <p>If the provided sender sends an error instead of values, <code class="highlight"><c- n>sync_wait</c-></code> throws that error as an exception, or rethrows the original exception if the error is of type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-></code>.</p>
   <p>If the provided sender sends the "stopped" signal instead of values, <code class="highlight"><c- n>sync_wait</c-></code> returns an empty optional.</p>
   <p>For an explanation of the <code class="highlight"><c- k>requires</c-></code> clause, see <a href="#design-typed">§ 5.8 All senders are typed</a>. That clause also explains another sender consumer, built on top of <code class="highlight"><c- n>sync_wait</c-></code>: <code class="highlight"><c- n>sync_wait_with_variant</c-></code>.</p>
   <p class="note" role="note"><span>Note:</span> This function is specified inside <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-></code>, and not inside <code class="highlight"><c- n>execution</c-></code>. This is because <code class="highlight"><c- n>sync_wait</c-></code> has to block the <i>current</i> execution agent, but determining what the current execution agent is is not reliable. Since the standard
does not specify any functions on the current execution agent other than those in <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-></code>, this is the flavor of this function that is being proposed. If C++ ever obtains fibers, for instance, we expect that a variant of this function called <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_fiber</c-><c- o>::</c-><c- n>sync_wait</c-></code> would be provided. We also expect that runtimes with execution agents that use different synchronization mechanisms than <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code>'s will provide their own flavors of <code class="highlight"><c- n>sync_wait</c-></code> as well (assuming their execution agents have the means
to block in a non-deadlock manner).</p>
   <h3 class="heading settled" data-level="4.23" id="design-execute"><span class="secno">4.23. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code></span><a class="self-link" href="#design-execute"></a></h3>
   <p>In addition to the three categories of functions presented above, we also propose to include a convenience function for fire-and-forget eager one-way submission of an invocable to a scheduler, to fulfil the role of one-way executors from P0443.</p>
<pre class="highlight"><c- b>void</c-> <c- nf>execution::execute</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><void> <c- k>auto</c-> <c- n>fn</c->
<c- p>);</c->
</void></pre>
   <p>Submits the provided function for execution on the provided scheduler, as-if by:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sched</c-><c- p>);</c->
<c- k>auto</c-> <c- n>work</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>fn</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>work</c-><c- p>);</c->
</pre>
   <h2 class="heading settled" data-level="5" id="design-implementer"><span class="secno">5. </span><span class="content">Design - implementer side</span><a class="self-link" href="#design-implementer"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="design-receivers"><span class="secno">5.1. </span><span class="content">Receivers serve as glue between senders</span><a class="self-link" href="#design-receivers"></a></h3>
   <p>A <dfn data-dfn-type="dfn" data-export id="receiver">receiver<a class="self-link" href="#receiver"></a></dfn> is a callback that supports more than one channel. In fact, it supports three of them:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>set_value</c-></code>, which is the moral equivalent of an <code class="highlight"><c- k>operator</c-><c- p>()</c-></code> or a function call, which signals successful completion of the operation its execution depends on;</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_error</c-></code>, which signals that an error has happened during scheduling of the current work, executing the current work, or at some earlier point in the sender chain; and</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_stopped</c-></code>, which signals that the operation completed without succeeding (<code class="highlight"><c- n>set_value</c-></code>) and without failing (<code class="highlight"><c- n>set_error</c-></code>). This result is often used to indicate that the operation stopped early, typically because it was asked to do so because the result is no
longer needed.</p>
   </ul>
   <p>Exactly one of these channels must be successfully (i.e. without an exception being thrown) invoked on a receiver before it is destroyed; if a call to <code class="highlight"><c- n>set_value</c-></code> failed with an exception, either <code class="highlight"><c- n>set_error</c-></code> or <code class="highlight"><c- n>set_stopped</c-></code> must be invoked on the same receiver. These
requirements are know as the <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="receiver-contract">receiver contract</dfn>.</p>
   <p>While the receiver interface may look novel, it is in fact very similar to the interface of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>promise</c-></code>, which provides the first two signals as <code class="highlight"><c- n>set_value</c-></code> and <code class="highlight"><c- n>set_error</c-></code>, and it’s possible to emulate the third channel with lifetime management of the promise.</p>
   <p>Receivers are not a part of the end-user-facing API of this proposal; they are necessary to allow unrelated senders communicate with each other, but the only users who will interact with receivers directly are authors of senders.</p>
   <p>Receivers are what is passed as the second argument to <a href="#design-connect">§ 5.3 execution::connect</a>.</p>
   <h3 class="heading settled" data-level="5.2" id="design-states"><span class="secno">5.2. </span><span class="content">Operation states represent work</span><a class="self-link" href="#design-states"></a></h3>
   <p>An <dfn data-dfn-type="dfn" data-export id="operation-state">operation state<a class="self-link" href="#operation-state"></a></dfn> is an object that represents work. Unlike senders, it is not a chaining mechanism; instead, it is a concrete object that packages the work described by a full sender chain, ready to be executed. An operation state is neither movable nor
copyable, and its interface consists of a single algorithm: <code class="highlight"><c- n>start</c-></code>, which serves as the submission point of the work represented by a given operation state.</p>
   <p>Operation states are not a part of the user-facing API of this proposal; they are necessary for implementing sender consumers like <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, and the knowledge of them is necessary to implement senders, so the only users who will
interact with operation states directly are authors of senders and authors of sender algorithms.</p>
   <p>The return value of <a href="#design-connect">§ 5.3 execution::connect</a> must satisfy the operation state concept.</p>
   <h3 class="heading settled" data-level="5.3" id="design-connect"><span class="secno">5.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code></span><a class="self-link" href="#design-connect"></a></h3>
   <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> is a customization point which <dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="connect" data-noexport id="connect">connects</dfn> senders with receivers, resulting in an operation state that will ensure that the <a data-link-type="dfn" href="#receiver-contract" id="ref-for-receiver-contract">receiver contract</a> of the receiver passed to <code class="highlight"><c- n>connect</c-></code> will be fulfilled.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <i><c- n>some</c-> <c- n>input</c-> <c- n>sender</c-></i><c- p>;</c->
<c- n>execution</c-><c- o>::</c-><c- n>receiver</c-> <c- k>auto</c-> <c- n>rcv</c-> <c- o>=</c-> <i><c- n>some</c-> <c- n>receiver</c-></i><c- p>;</c->
<c- n>execution</c-><c- o>::</c-><c- n>operation_state</c-> <c- k>auto</c-> <c- n>state</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>rcv</c-><c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>state</c-><c- p>);</c->
<c- c1>// at this point, it is guaranteed that the work represented by state has been submitted</c->
<c- c1>// to an execution context, and that execution context will eventually fulfill the</c->
<c- c1>// receiver contract of rcv</c->

<c- c1>// operation states are not movable, and therefore this operation state object must be</c->
<c- c1>// kept alive until the operation finishes</c->
</pre>
   <h3 class="heading settled" data-level="5.4" id="design-customization"><span class="secno">5.4. </span><span class="content">Sender algorithms are customizable</span><a class="self-link" href="#design-customization"></a></h3>
   <p>Senders being able to advertise what their <a data-link-type="dfn" href="#completion-schedulers" id="ref-for-completion-schedulers①⓪">completion schedulers</a> are fulfills one of the promises of senders: that of being able to customize an implementation of a sender algorithm based on what scheduler any work it depends on will complete on.</p>
   <p>The simple way to provide customizations for functions like <code class="highlight"><c- n>then</c-></code>, that is for <a data-link-type="dfn" href="#sender-adaptor" id="ref-for-sender-adaptor①">sender adaptors</a> and <a data-link-type="dfn" href="#sender-consumer" id="ref-for-sender-consumer①">sender consumers</a>, is to follow the customization scheme that has been adopted for C++20 ranges library; to do that, we would define
the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>invocable</c-><c- p>)</c-></code> to be equivalent to:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>sender</c-><c- p>.</c-><c- n>then</c-><c- p>(</c-><c- n>invocable</c-><c- p>)</c-></code>, if that expression is well formed; otherwise</p>
    <li data-md>
     <p><code class="highlight"><c- n>then</c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>invocable</c-><c- p>)</c-></code>, performed in a context where this call always performs ADL, if that expression is well formed; otherwise</p>
    <li data-md>
     <p>a default implementation of <code class="highlight"><c- n>then</c-></code>, which returns a sender adaptor, and then define the exact semantics of said adaptor.</p>
   </ol>
   <p>However, this definition is problematic. Imagine another sender adaptor, <code class="highlight"><c- n>bulk</c-></code>, which is a structured abstraction for a loop over an index space. Its default implementation is just a for loop. However, for accelerator runtimes like CUDA, we would like sender algorithms
like <code class="highlight"><c- n>bulk</c-></code> to have specialized behavior, which invokes a kernel of more than one thread (with its size defined by the call to <code class="highlight"><c- n>bulk</c-></code>); therefore, we would like to customize <code class="highlight"><c- n>bulk</c-></code> for CUDA senders to achieve this. However, there’s no reason for CUDA kernels to
necessarily customize the <code class="highlight"><c- n>then</c-></code> sender adaptor, as the generic implementation is perfectly sufficient. This creates a problem, though; consider the following snippet:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cuda_sch</c-> <c- o>=</c-> <c- n>cuda_scheduler</c-><c- p>{};</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>initial</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cuda_sch</c-><c- p>);</c->
<c- c1>// the type of initial is a type defined by the cuda_scheduler</c->
<c- c1>// let’s call it cuda::schedule_sender&lt;></c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>next</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>cuda_sch</c-><c- p>,</c-> <c- p>[]{</c-> <c- k>return</c-> <c- mi>1</c-><c- p>;</c-> <c- p>});</c->
<c- c1>// the type of next is a standard-library implementation-defined sender adaptor</c->
<c- c1>// that wraps the cuda sender</c->
<c- c1>// let’s call it execution::then_sender_adaptor&lt;cuda::schedule_sender&lt;>></c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>kernel_sender</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>next</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- p>...</c-> <c- p>});</c->
</pre>
   <p>How can we specialize the <code class="highlight"><c- n>bulk</c-></code> sender adaptor for our wrapped <code class="highlight"><c- n>schedule_sender</c-></code>? Well, here’s one possible approach, taking advantage of ADL (and the fact that the definition of "associated namespace" also recursively enumerates the associated namespaces of all template
parameters of a type):</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>cuda</c-><c- o>::</c-><c- nn>for_adl_purposes</c-> <c- p>{</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>SentValues</c-><c- o>></c->
<c- k>class</c-> <c- nc>schedule_sender</c-> <c- p>{</c->
    <c- n>execution</c-><c- o>::</c-><c- n>operation_state</c-> <c- k>auto</c-> <c- n>connect</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>receiver</c-> <c- k>auto</c-> <c- n>rcv</c-><c- p>);</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>get_completion_scheduler</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
<c- p>};</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>input</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>shape</c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>shape</c-><c- p>,</c->
    <c- n>invocable</c-><c- o>&lt;</c-><i><c- n>sender</c-><c- o>-</c-><c- n>values</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- o>></c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>)</c->
<c- p>{</c->
    <c- c1>// return a cuda sender representing a bulk kernel launch</c->
<c- p>}</c->
<c- p>}</c-> <c- c1>// namespace cuda::for_adl_purposes</c->
</pre>
   <p>However, if the input sender is not just a <code class="highlight"><c- n>then_sender_adaptor</c-></code> like in the example above, but another sender that overrides <code class="highlight"><c- n>bulk</c-></code> by itself, as a member function, because its author believes they know an optimization for bulk - the specialization above will no
longer be selected, because a member function of the first argument is a better match than the ADL-found overload.</p>
   <p>This means that well-meant specialization of sender algorithms that are entirely scheduler-agnostic can have negative consequences.
The scheduler-specific specialization - which is essential for good performance on platforms providing specialized ways to launch certain sender algorithms - would not be selected in such cases.
But it’s really the scheduler that should control the behavior of sender algorithms when a non-default implementation exists, not the sender. Senders merely describe work; schedulers, however, are the handle to the
runtime that will eventually execute said work, and should thus have the final say in <em>how</em> the work is going to be executed.</p>
   <p>Therefore, we are proposing the following customization scheme (also modified to take <a href="#design-dispatch">§ 5.9 Ranges-style CPOs vs tag_invoke</a> into account): the expression <code class="highlight"><c- n>execution</c-><c- o>::&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, for any given sender algorithm that accepts a sender as its first argument, should be
equivalent to:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- o>&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><i><c- n>Signal</c-></i><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>sender</c-><c- p>)),</c-> <c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- o>&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>,</c-> <c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p>a default implementation, if there exists a default implementation of the given sender algorithm.</p>
   </ol>
   <p>where <code class="highlight"><i><c- n>Signal</c-></i></code> is one of <code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, or <code class="highlight"><c- n>set_stopped</c-></code>. For most sender algorithms, the completion scheduler for <code class="highlight"><c- n>set_value</c-></code> would be used, but for some (like <code class="highlight"><c- n>upon_error</c-></code> or <code class="highlight"><c- n>let_stopped</c-></code>), one of the others would be used.</p>
   <p>For sender algorithms which accept concepts other than <code class="highlight"><c- n>sender</c-></code> as their first argument, we propose that the customization scheme remains as it has been in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> so far, except it should also use <code class="highlight"><c- n>tag_invoke</c-></code>.</p>
   <h3 class="heading settled" data-level="5.5" id="design-laziness"><span class="secno">5.5. </span><span class="content">Sender adaptors are lazy</span><a class="self-link" href="#design-laziness"></a></h3>
   <p>Contrary to early revisions of this paper, we propose to make all sender adaptors perform strictly lazy submission, unless specified otherwise (the one notable exception in this paper is <a href="#design-sender-adaptor-ensure_started">§ 4.21.13 execution::ensure_started</a>, whose sole purpose is to start an
input sender).</p>
   <p><dfn data-dfn-type="dfn" data-export id="strictly-lazy-submission">Strictly lazy submission<a class="self-link" href="#strictly-lazy-submission"></a></dfn> means that there is a guarantee that no work is submitted to an execution context before a receiver is connected to a sender, and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on the resulting operation state.</p>
   <h3 class="heading settled" data-level="5.6" id="design-fusion"><span class="secno">5.6. </span><span class="content">Lazy senders provide optimization opportunities</span><a class="self-link" href="#design-fusion"></a></h3>
   <p>Because lazy senders fundamentally <em>describe</em> work, instead of describing or representing the submission of said work to an execution context, and thanks to the flexibility of the customization of most sender algorithms, they provide an opportunity for fusing
multiple algorithms in a sender chain together, into a single function that can later be submitted for execution by an execution context. There are two ways this can happen.</p>
   <p>The first (and most common) way for such optimizations to happen is thanks to the structure of the implementation: because all the work is done within callbacks invoked on the completion of an earlier sender, recursively up to the original source of computation,
the compiler is able to see a chain of work described using senders as a tree of tail calls, allowing for inlining and removal of most of the sender machinery. In fact, when work is not submitted to execution contexts outside of the current thread of execution,
compilers are capable of removing the senders abstraction entirely, while still allowing for composition of functions across different parts of a program.</p>
   <p>The second way for this to occur is when a sender algorithm is specialized for a specific set of arguments. For instance, we expect that, for senders which are known to have been started already, <a href="#design-sender-adaptor-ensure_started">§ 4.21.13 execution::ensure_started</a> will be an identity transformation,
because the sender algorithm will be specialized for such senders. Similarly, an implementation could recognize two subsequent <a href="#design-sender-adaptor-bulk">§ 4.21.9 execution::bulk</a>s of compatible shapes, and merge them together into a single submission of a GPU kernel.</p>
   <h3 class="heading settled" data-level="5.7" id="design-transition-details"><span class="secno">5.7. </span><span class="content">Execution context transitions are two-step</span><a class="self-link" href="#design-transition-details"></a></h3>
   <p>Because <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> takes a sender as its first argument, it is not actually directly customizable by the target scheduler. This is by design: the target scheduler may not know how to transition <i>from</i> a scheduler such as a CUDA scheduler;
transitioning away from a GPU in an efficient manner requires making runtime calls that are specific to the GPU in question, and the same is usually true for other kinds of accelerators too (or for scheduler running on remote systems). To avoid this problem,
specialized schedulers like the ones mentioned here can still hook into the transition mechanism, and inject a sender which will perform a transition to the regular CPU execution context, so that any sender can be attached to it.</p>
   <p>This, however, is a problem: because customization of sender algorithms must be controlled by the scheduler they will run on (see <a href="#design-customization">§ 5.4 Sender algorithms are customizable</a>), the type of the sender returned from <code class="highlight"><c- n>transfer</c-></code> must be controllable by the target scheduler. Besides, the target
scheduler may itself represent a specialized execution context, which requires additional work to be performed to transition <i>to</i> it. GPUs and remote node schedulers are once again good examples of such schedulers: executing code on their execution contexts
requires making runtime API calls for work submission, and quite possibly for the data movement of the values being sent by the input sender passed into <code class="highlight"><c- n>transfer</c-></code>.</p>
   <p>To allow for such customization from both ends, we propose the inclusion of a secondary transitioning sender adaptor, called <code class="highlight"><c- n>schedule_from</c-></code>. This adaptor is a form of <code class="highlight"><c- n>schedule</c-></code>, but takes an additional, second argument: the input sender. This adaptor is not
meant to be invoked manually by the end users; they are always supposed to invoke <code class="highlight"><c- n>transfer</c-></code>, to ensure that both schedulers have a say in how the transitions are made. Any scheduler that specializes <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> shall ensure that the
return value of their customization is equivalent to <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>snd2</c-><c- p>)</c-></code>, where <code class="highlight"><c- n>snd2</c-></code> is a successor of <code class="highlight"><c- n>snd</c-></code> that sends values equivalent to those sent by <code class="highlight"><c- n>snd</c-></code>.</p>
   <p>The default implementation of <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>sched</c-><c- p>)</c-></code> is <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>snd</c-><c- p>)</c-></code>.</p>
   <h3 class="heading settled" data-level="5.8" id="design-typed"><span class="secno">5.8. </span><span class="content">All senders are typed</span><a class="self-link" href="#design-typed"></a></h3>
   <p>All senders must advertise the types they will <a data-link-type="dfn" href="#send" id="ref-for-send⑥">send</a> when they complete.
This is necessary for a number of features, and writing code in a way that’s
agnostic of whether an input sender is typed or not in common sender adaptors
such as <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> is hard.</p>
   <p>The mechanism for this advertisement is similar to the one in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; the
way to query the types is through <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- p>[</c-><c- n>Env</c-><c- p>]</c-><c- o>>::</c-><c- n>value_types</c-><c- o>&lt;</c-><c- n>tuple_like</c-><c- p>,</c-> <c- n>variant_like</c-><c- o>></c-></code>.</p>
   <p><code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>::</c-><c- n>value_types</c-></code> is a template that takes two
arguments: one is a tuple-like template, the other is a variant-like template.
The tuple-like argument is required to represent senders sending more than one
value (such as <code class="highlight"><c- n>when_all</c-></code>). The variant-like argument is required to represent
senders that choose which specific values to send at runtime.</p>
   <p>There’s a choice made in the specification of <a href="#design-sender-consumer-sync_wait">§ 4.22.2 this_thread::sync_wait</a>: it returns a tuple of values sent by the
sender passed to it, wrapped in <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> to handle the <code class="highlight"><c- n>set_stopped</c-></code> signal. However, this assumes that those values can be represented as a tuple,
like here:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_2</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_3</c-> <c- o>=</c-> <c- p>...;</c->

<c- k>auto</c-> <c- p>[</c-><c- n>a</c-><c- p>,</c-> <c- n>b</c-><c- p>,</c-> <c- n>c</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>(</c->
        <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>sends_1</c-><c- p>)),</c->
        <c- n>sends_1</c-><c- p>,</c->
        <c- n>sends_2</c-><c- p>,</c->
        <c- n>sends_3</c->
    <c- p>)).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// a == 1</c->
<c- c1>// b == 2</c->
<c- c1>// c == 3</c->
</pre>
   <p>This works well for senders that always send the same set of arguments. If we ignore the possibility of having a sender that sends different sets of arguments into a receiver, we can specify the "canonical" (i.e. required to be followed by all senders) form of <code class="highlight"><c- n>value_types</c-></code> of a sender which sends <code class="highlight"><c- n>Types</c-><c- p>...</c-></code> to be as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>TupleLike</c-><c- o>></c->
<c- k>using</c-> <c- n>value_types</c-> <c- o>=</c-> <c- n>TupleLike</c-><types...><c- p>;</c->
</types...></pre>
   <p>If senders could only ever send one specific set of values, this would probably need to be the required form of <code class="highlight"><c- n>value_types</c-></code> for all senders; defining it otherwise would cause very weird results and should be considered a bug.</p>
   <p>This matter is somewhat complicated by the fact that (1) <code class="highlight"><c- n>set_value</c-></code> for receivers can be overloaded and accept different sets of arguments, and (2) senders are allowed to send multiple different sets of values, depending on runtime conditions, the data they
consumed, and so on. To accomodate this, <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> also includes a second template parameter to <code class="highlight"><c- n>value_types</c-></code>, one that represents a variant-like type. If we permit such senders, we would almost certainly need to require that the canonical form of <code class="highlight"><c- n>value_types</c-></code> for <em>all</em> senders (to ensure consistency in how they are handled, and to avoid accidentally interpreting a user-provided variant as a sender-provided one) sending the different sets of arguments <code class="highlight"><c- n>Types1</c-><c- p>...</c-></code>, <code class="highlight"><c- n>Types2</c-><c- p>...</c-></code>, ..., <code class="highlight"><c- n>TypesN</c-><c- p>...</c-></code> to be as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>TupleLike</c-><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>VariantLike</c->
<c- o>></c->
<c- k>using</c-> <c- n>value_types</c-> <c- o>=</c-> <c- n>VariantLike</c-><c- o>&lt;</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types1</c-><c- p>...</c-><c- o>></c-><c- p>,</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types2</c-><c- p>...</c-><c- o>></c-><c- p>,</c->
    <c- p>...,</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types3</c-><c- p>...</c-><c- o>></c->
<c- o>></c-><c- p>;</c->
</pre>
   <p>This, however, introduces a couple of complications:</p>
   <ol>
    <li data-md>
     <p>A <code class="highlight"><c- n>just</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code> sender would also need to follow this structure, so the correct type for storing the value sent by it would be <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-></code> or some such. This introduces a lot of compile time overhead for the simplest senders, and this overhead
effectively exists in all places in the code where <code class="highlight"><c- n>value_types</c-></code> is queried, regardless of the tuple-like and variant-like templates passed to it. Such overhead does exist if only the tuple-like parameter exists, but is made much worse by adding this second
wrapping layer.</p>
    <li data-md>
     <p>As a consequence of (1): because <code class="highlight"><c- n>sync_wait</c-></code> needs to store the above type, it can no longer return just a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> for <code class="highlight"><c- n>just</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code>; it has to return <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-></code>. C++ currently does not have an easy way to destructure this; it may get
less awkward with pattern matching, but even then it seems extremely heavyweight to involve variants in this API, and for the purpose of generic code, the kind of the return type of <code class="highlight"><c- n>sync_wait</c-></code> must be the same across all sender types.</p>
   </ol>
   <p>One possible solution to (2) above is to place a requirement on <code class="highlight"><c- n>sync_wait</c-></code> that it can only accept senders which send only a single set of values, therefore removing the need for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-></code> to appear in its API; because of this, we propose to expose both <code class="highlight"><c- n>sync_wait</c-></code>, which is a simple, user-friendly version of the sender consumer, but requires that <code class="highlight"><c- n>value_types</c-></code> have only one possible variant, and <code class="highlight"><c- n>sync_wait_with_variant</c-></code>, which accepts any sender, but returns an optional whose value type is the variant of all the
possible tuples sent by the input sender:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>sync_wait_with_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>0</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>1</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- p>...,</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>n</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c->
    <c- o>>></c-><c- p>;</c->

<c- k>auto</c-> <c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- k>requires</c-> <c- p>(</c-><i><c- n>always</c-><c- o>-</c-><c- n>sends</c-><c- o>-</c-><c- n>same</c-><c- o>-</c-><c- n>values</c-></i><c- p>(</c-><c- n>sender</c-><c- p>))</c->
    <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>>></c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="5.9" id="design-dispatch"><span class="secno">5.9. </span><span class="content">Ranges-style CPOs vs <code class="highlight"><c- n>tag_invoke</c-></code></span><a class="self-link" href="#design-dispatch"></a></h3>
   <p>The contemporary technique for customization in the Standard Library is customization point objects. A customization point object, will it look for member functions and then for nonmember functions with the same name as the customization point, and calls those if
they match. This is the technique used by the C++20 ranges library, and previous executors proposals (<a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> and <a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>) intended to use it as well. However, it has several unfortunate consequences:</p>
   <ol>
    <li data-md>
     <p>It does not allow for easy propagation of customization points unknown to the adaptor to a wrapped object, which makes writing universal adapter types much harder - and this proposal uses quite a lot of those.</p>
    <li data-md>
     <p>It effectively reserves names globally. Because neither member names nor ADL-found functions can be qualified with a namespace, every customization point object that uses the ranges scheme reserves the name for all types in all namespaces. This is unfortunate
due to the sheer number of customization points already in the paper, but also ones that we are envisioning in the future. It’s also a big problem for one of the operations being proposed already: <code class="highlight"><c- n>sync_wait</c-></code>. We imagine that if, in the future, C++ was to
gain fibers support, we would want to also have <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_fiber</c-><c- o>::</c-><c- n>sync_wait</c-></code>, in addition to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>. However, because we would want the names to be the same in both cases, we would need to make the names of the customizations not match the
names of the customization points. This is undesirable.</p>
   </ol>
   <p>This paper proposes to instead use the mechanism described in <a data-link-type="biblio" href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>: <code class="highlight"><c- n>tag_invoke</c-></code>; the wording for <code class="highlight"><c- n>tag_invoke</c-></code> has been incorporated into the proposed specification in this paper.</p>
   <p>In short, instead of using globally reserved names, <code class="highlight"><c- n>tag_invoke</c-></code> uses the <i>type</i> of the customization point object itself as the mechanism to find customizations. It globally reserves only a single name - <code class="highlight"><c- n>tag_invoke</c-></code> - which itself is used the same way that
ranges-style customization points are used. All other customization points are defined in terms of <code class="highlight"><c- n>tag_invoke</c-></code>. For example, the customization for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> will call <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, instead of attempting
to invoke <code class="highlight"><c- n>s</c-><c- p>.</c-><c- n>sync_wait</c-><c- p>()</c-></code>, and then <code class="highlight"><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> if the member call is not valid.</p>
   <p>Using <code class="highlight"><c- n>tag_invoke</c-></code> has the following benefits:</p>
   <ol>
    <li data-md>
     <p>It reserves only a single global name, instead of reserving a global name for every customization point object we define.</p>
    <li data-md>
     <p>It is possible to propagate customizations to a subobject, because the information of which customization point is being resolved is in the type of an argument, and not in the name of the function:</p>
<pre class="highlight"><c- c1>// forward most customizations to a subobject</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>typename</c-> <c- p>...</c-><c- n>Args</c-><c- o>></c->
<c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-> <c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>wrapper</c-> <c- o>&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Args</c-> <c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>)(</c-><c- n>self</c-><c- p>.</c-><c- n>subobject</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
<c- p>}</c->

<c- c1>// but override one of them with a specific value</c->
<c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>specific_customization_point_t</c-><c- p>,</c-> <c- n>wrapper</c-> <c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>self</c-><c- p>.</c-><c- n>some_value</c-><c- p>;</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>It is possible to pass those as template arguments to types, because the information of which customization point is being resolved is in the type. Similarly to how <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> defines a polymorphic executor wrapper which accepts a list of properties it
supports, we can imagine scheduler and sender wrappers that accept a list of queries and operations they support. That list can contain the types of the customization point objects, and the polymorphic wrappers can then specialize those customization points on
themselves using <code class="highlight"><c- n>tag_invoke</c-></code>, dispatching to manually constructed vtables containing pointers to specialized implementations for the wrapped objects. For an example of such a polymorphic wrapper, see <code class="highlight"><a href="https://github.com/facebookexperimental/libunifex/blob/1a6fbfc9cc3829356ccbdcf9e8d1f3cc33a6d9e0/include/unifex/any_unique.hpp"><c- n>unifex</c-><c- o>::</c-><c- n>any_unique</c-></a></code> (<a href="https://github.com/facebookexperimental/libunifex/blob/1a6fbfc9cc3829356ccbdcf9e8d1f3cc33a6d9e0/examples/any_unique.cpp">example</a>).</p>
   </ol>
   <h2 class="heading settled" data-level="6" id="spec"><span class="secno">6. </span><span class="content">Specification</span><a class="self-link" href="#spec"></a></h2>
   <p>Much of this wording follows the wording of <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>.</p>
   <p><a href="#spec-library">§ 8 Library introduction [library]</a> is meant to be a diff relative to the wording of the <b>[library]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>.</p>
   <p><a href="#spec-utilities">§ 9 General utilities library [utilities]</a> is meant to be a diff relative to the wording of the <b>[utilities]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. This diff applies changes from <a data-link-type="biblio" href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>.</p>
   <p><a href="#spec-thread">§ 10 Thread support library [thread]</a> is meant to be a diff relative to the wording of the <b>[thread]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. This diff applies changes from <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>.</p>
   <p><a href="#spec-execution">§ 11 Execution control library [exec]</a> is meant to be added as a new library clause to the working draft of C++.</p>
   <h2 class="heading settled" data-level="7" id="spec-except"><span class="secno">7. </span><span class="content">Exception handling [except]</span><a class="self-link" href="#spec-except"></a></h2>
   <h3 class="heading settled" data-level="7.1" id="spec-except.special"><span class="secno">7.1. </span><span class="content">Special functions [except.special]</span><a class="self-link" href="#spec-except.special"></a></h3>
   <h4 class="heading settled" data-level="7.1.1" id="spec-except.special.general"><span class="secno">7.1.1. </span><span class="content">General [except.special.general]</span><a class="self-link" href="#spec-except.special.general"></a></h4>
   <h5 class="heading settled" data-level="7.1.1.1" id="spec-except.terminate"><span class="secno">7.1.1.1. </span><span class="content">The <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> function [except.terminate]</span><a class="self-link" href="#spec-except.terminate"></a></h5>
   <div class="ed-note">At the end of the bulleted list in the Note in paragraph 1, add a new bullet as follows:</div>
   <ins>
    <blockquote>
     <ul>
      <li data-md>
       <p>when a callback invocation exits via an exception when requesting stop on a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_source</c-></code> or a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_source</c-></code> ([stopsource.mem], [stopsource.inplace.mem]), or in
the constructor of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_callback</c-></code> or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_callback</c-></code> ([stopcallback.cons], [stopcallback.inplace.cons]) when a callback invocation exits
via an exception.</p>
     </ul>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="8" id="spec-library"><span class="secno">8. </span><span class="content">Library introduction <b>[library]</b></span><a class="self-link" href="#spec-library"></a></h2>
   <div class="ed-note">
    Add the header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> to Table 23: C++ library headers [tab:headers.cpp] 
    <p>In subclause [conforming], after [lib.types.movedfrom], add the following new subclause with suggested stable name [lib.tmpl-heads].</p>
   </div>
   <p></p>
   <ins>
    <blockquote>
      <strong>16.4.6.17  Class template-heads</strong> 
     <ol>
      <li data-md>
       <p>If a class template’s template-head is marked with "<em>arguments are not
associated entities</em>"", any template arguments do not contribute to the
associated entities ([basic.lookup.argdep]) of a function call where a
specialization of the class template is an associated entity. In such a case,
the class template may be implemented as an alias template referring to a
templated class, or as a class template where the template arguments
themselves are templated classes.</p>
      <li data-md>
       <p>[<em>Example:</em></p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- c1>// arguments are not associated entities</c->
<c- k>struct</c-> <c- nc>S</c-> <c- p>{};</c->

<c- k>namespace</c-> <c- nn>N</c-> <c- p>{</c->
  <c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- k>auto</c-><c- p>);</c->
  <c- k>struct</c-> <c- nc>A</c-> <c- p>{};</c->
<c- p>}</c->

<c- b>int</c-> <c- n>x</c-> <c- o>=</c-> <c- n>f</c-><c- p>(</c-><c- n>S</c-><c- o>&lt;</c-><c- n>N</c-><c- o>::</c-><c- n>A</c-><c- o>></c-><c- p>{});</c->  <c- c1>// error: N::f not a candidate</c->
</pre>
       <p>The template <code class="highlight"><c- n>S</c-></code> specified above may be implemented as</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>s</c-><c- o>-</c-><c- n>impl</c-></i> <c- p>{</c->
  <c- k>struct</c-> <c- nc>type</c-> <c- p>{</c-> <c- p>};</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>using</c-> <c- n>S</c-> <c- o>=</c-> <c- k>typename</c-> <i><c- nc>s</c-><c- o>-</c-><c- n>impl</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- p>;</c->
</pre>
       <p>or as</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>hidden</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- k>struct</c-> <c- nc>_</c-> <c- p>{</c->
    <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- n>T</c-><c- p>;</c->
  <c- p>};</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>HiddenT</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>s</c-><c- o>-</c-><c- n>impl</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>T</c-> <c- o>=</c-> <c- k>typename</c-> <c- nc>HiddenT</c-><c- o>::</c-><c- n>type</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>using</c-> <c- n>S</c-> <c- o>=</c-> <i><c- n>s</c-><c- o>-</c-><c- n>impl</c-></i><c- o>&lt;</c-><c- k>typename</c-> <i><c- nc>hidden</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- o>></c-><c- p>;</c->
</pre>
       <p>-- <i>end example</i>]</p>
     </ol>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="9" id="spec-utilities"><span class="secno">9. </span><span class="content">General utilities library <b>[utilities]</b></span><a class="self-link" href="#spec-utilities"></a></h2>
   <h3 class="heading settled" data-level="9.1" id="spec-function.objects"><span class="secno">9.1. </span><span class="content">Function objects <b>[function.objects]</b></span><a class="self-link" href="#spec-function.objects"></a></h3>
   <h4 class="heading settled" data-level="9.1.1" id="spec-functional.syn"><span class="secno">9.1.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>functional</c-><c- o>></c-></code> synopsis <b>[functional.syn]</b></span><a class="self-link" href="#spec-functional.syn"></a></h4>
   <p>At the end of this subclause, insert the following declarations into the synopsis within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><c- c1>// Expositon-only:</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>callable</c-></i> <c- o>=</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Fn</c-><c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
      <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>(</c-><c- n>fn</c-><c- p>)(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>};</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>nothrow</c-><c- o>-</c-><c- n>callable</c-></i> <c- o>=</c->
    <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Fn</c-><c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>(</c-><c- n>fn</c-><c- p>)(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>};</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>()(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>()...));</c->

<c- c1>// [func.tag_invoke], tag_invoke</c->
<c- k>namespace</c-> <i><c- nn>tag</c-><c- o>-</c-><c- nn>invoke</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
  <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>();</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>tag_invocable</c-> <c- o>=</c->
      <c- k>requires</c-> <c- p>(</c-><c- n>Tag</c-><c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
        <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
      <c- p>};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>nothrow_tag_invocable</c-> <c- o>=</c->
      <c- n>tag_invocable</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- o>&amp;&amp;</c->
      <c- k>requires</c-> <c- p>(</c-><c- n>Tag</c-><c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
        <c- p>{</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
      <c- p>};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>using</c-> <c- n>tag_invoke_result_t</c-> <c- o>=</c->
      <c- k>decltype</c-><c- p>(</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(),</c-> <c- n>declval</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>()...));</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>tag_invoke_result</c-> <c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
      <c- k>requires</c-> <c- n>tag_invocable</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>tag_invoke_result</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- p>{</c->
      <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->

  <c- k>struct</c-> <i><c- nc>tag</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
<c- p>}</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><i><c- n>tag</c-></i> <c- n>tag_invoke</c-> <c- p>{};</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invocable</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>nothrow_tag_invocable</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invoke_result_t</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invoke_result</c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>auto</c-><c- o>&amp;</c-> <c- n>Tag</c-><c- o>></c->
  <c- k>using</c-> <c- n>tag_t</c-> <c- o>=</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>Tag</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
</pre>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="9.1.2" id="spec-func.tag_invoke"><span class="secno">9.1.2. </span><span class="content"><code class="highlight"><c- n>tag_invoke</c-></code> <b>[func.tag_invoke]</b></span><a class="self-link" href="#spec-func.tag_invoke"></a></h4>
   <p>Insert this section as a new subclause, between Searchers <b>[func.search]</b> and Class template <code class="highlight"><c- n>hash</c-></code> <b>[unord.hash]</b>.</p>
   <ins>
    <blockquote>
     <ol>
      <li data-md>
       <p>The name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-></code> denotes a customization point object [customization.point.object]. Given subexpressions <code class="highlight"><c- n>T</c-></code> and <code class="highlight"><c- n>A</c-><c- p>...</c-></code>, the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> is expression-equivalent [defns.expression-equivalent] to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> if it is a well-formed expression with overload resolution performed in a context in which unqualified lookup for <code class="highlight"><c- n>tag_invoke</c-></code> finds only the declaration</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>tag_invoke</c-><c- p>();</c->
</pre>
       <p>Otherwise, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> is ill-formed.</p>
      <li data-md>
       <p>[Note: Diagnosable ill-formed cases above result in substitution failure when <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> appears in the immediate context of a template instantiation. —end note]</p>
     </ol>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="10" id="spec-thread"><span class="secno">10. </span><span class="content">Thread support library <b>[thread]</b></span><a class="self-link" href="#spec-thread"></a></h2>
   <h3 class="heading settled" data-level="10.1" id="spec-thread.stoptoken"><span class="secno">10.1. </span><span class="content">Stop tokens <b>[thread.stoptoken]</b></span><a class="self-link" href="#spec-thread.stoptoken"></a></h3>
   <h4 class="heading settled" data-level="10.1.1" id="spec-thread.stoptoken.syn"><span class="secno">10.1.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b></span><a class="self-link" href="#spec-thread.stoptoken.syn"></a></h4>
   <p>At the beginning of this subclause, insert the following declarations into the synopsis within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>check</c-><c- o>-</c-><c- n>type</c-><c- o>-</c-><c- n>alias</c-><c- o>-</c-><c- n>exists</c-></i><c- p>;</c-> <c- c1>// exposition-only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Initializer</c-> <c- o>=</c-> <c- n>CB</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token_for</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>unstoppable_token</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->
</pre>
    </blockquote>
   </ins>
   <p>At the end of this subclause, insert the following declarations into the synopsis of within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><c- c1>// [stoptoken.never], class never_stop_token</c->
<c- k>class</c-> <c- nc>never_stop_token</c-><c- p>;</c->

<c- c1>// [stoptoken.inplace], class in_place_stop_token</c->
<c- k>class</c-> <c- nc>in_place_stop_token</c-><c- p>;</c->

<c- c1>// [stopsource.inplace], class in_place_stop_source</c->
<c- k>class</c-> <c- nc>in_place_stop_source</c-><c- p>;</c->

<c- c1>// [stopcallback.inplace], class template in_place_stop_callback</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CB</c-><c- o>></c->
  <c- k>class</c-> <c- nc>in_place_stop_callback</c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- o>></c->
  <c- k>using</c-> <c- n>stop_callback_for_t</c-> <c- o>=</c-> <c- k>typename</c-> <c- nc>T</c-><c- o>::</c-><c- k>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-><c- p>;</c->
</pre>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="10.1.2" id="spec-thread.stoptoken.concepts"><span class="secno">10.1.2. </span><span class="content">Stop token concepts <b>[thread.stoptoken.concepts]</b></span><a class="self-link" href="#spec-thread.stoptoken.concepts"></a></h4>
   <p>Insert this section as a new subclause between Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b> and Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b>.</p>
   <ins>
    <blockquote>
     <ol>
      <li data-md>
       <p>The <code class="highlight"><c- n>stoppable_token</c-></code> concept checks for the basic interface of a stop token
that is copyable and allows polling to see if stop has been requested and
also whether a stop request is possible. For a stop token type <code class="highlight"><c- n>T</c-></code> and a type <code class="highlight"><c- n>CB</c-></code> that is callable with no arguments, the type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> is
valid and denotes the stop callback type to use to register a callback
to be executed if a stop request is ever made on a <code class="highlight"><c- n>stoppable_token</c-></code> of type <code class="highlight"><c- n>T</c-></code>. The <code class="highlight"><c- n>stoppable_token_for</c-></code> concept checks for a stop token type compatible
with a given callback type. The <code class="highlight"><c- n>unstoppable_token</c-></code> concept checks for a stop
token type that does not allow stopping.</p>
     </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token</c-> <c- o>=</c->
    <c- n>copyable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>equality_comparable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- k>const</c-> <c- n>T</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>T</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c-> <c- c1>// </c-><i><c- c1>see implicit expression variations ([concepts.equality])</c-></i>
      <c- p>{</c-> <c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-> <c- p>}</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-><c- p>;</c->
      <c- p>{</c-> <c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-> <c- p>}</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-><c- p>;</c->
      <c- k>typename</c-> <i><c- nc>check</c-><c- o>-</c-><c- n>type</c-><c- o>-</c-><c- n>alias</c-><c- o>-</c-><c- n>exists</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>::</c-><c- k>template</c-> <c- n>callback_type</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Initializer</c-> <c- o>=</c-> <c- n>CB</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token_for</c-> <c- o>=</c->
    <c- n>stoppable_token</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>invocable</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>CB</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c-> <c- k>typename</c-> <c- nc>stop_callback_for_t</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>CB</c-><c- o>></c-><c- p>;</c-> <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>stop_callback_for_t</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>CB</c-><c- o>></c-><c- p>,</c-> <c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>unstoppable_token</c-> <c- o>=</c->
    <c- n>stoppable_token</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>bool_constant</c-><c- o>&lt;</c-><c- n>T</c-><c- o>::</c-><c- n>stop_possible</c-><c- p>()</c-><c- o>></c-><c- p>{}</c-> <c- p>}</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>false_type</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->
</pre>
     <div class="ed-note">
      LWG directed me to replace <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>stop_possible</c-><c- p>()</c-></code> with <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> because
of the recent <code class="highlight"><c- k>constexpr</c-></code> changes in <a data-link-type="biblio" href="https://wg21.link/p2280r2">P2280R2</a>. However, even with those changes, a nested
requirement like <code class="highlight"><c- k>requires</c-> <c- p>(</c-><c- o>!</c-><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>())</c-></code>, where <code class="highlight"><c- n>t</c-></code> is an argument in the requirement-parameter-list, is ill-formed according to <a href="http://eel.is/c++draft/expr.prim.req#nested-2.sentence-1">[expr.prim.req.nested/p2]</a>: 
      <blockquote>
       <p>A local parameter shall only appear as an unevaluated operand within the constraint-expression.</p>
      </blockquote>
      <p>This is the subject of core issue <a data-link-type="biblio" href="https://wg21.link/cwg2517">2517</a>.</p>
     </div>
     <ol start="2">
      <li data-md>
       <p>Let <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> be distinct, valid objects of type <code class="highlight"><c- n>T</c-></code>. The type <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>stoppable_token</c-></code> only if:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> evaluates to <code class="highlight">false</code> then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same logical shared stop state, <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">false</code> and <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">false</code>.</p>
        <li data-md>
         <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> evaluates to <code class="highlight">true</code> then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same logical shared stop state, <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">true</code> and <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">true</code>.</p>
       </ol>
      <li data-md>
       <p>Let <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> be distinct, valid objects of type <code class="highlight"><c- n>T</c-></code> and let <code class="highlight"><c- n>init</c-></code> be an
object of type <code class="highlight"><c- n>Initializer</c-></code>. Then for some type <code class="highlight"><c- n>CB</c-></code>, the type <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>stoppable_token_for</c-><c- o>&lt;</c-><c- n>CB</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-></code> only if:</p>
       <ol>
        <li data-md>
         <p>The type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> models:</p>
<pre class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
<c- n>constructible_from</c-><c- o>&lt;</c-><c- n>T</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
<c- n>constructible_from</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>T</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c->
</pre>
        <li data-md>
         <p>Direct non-list initializing an object <code class="highlight"><c- n>cb</c-></code> of type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> from <code class="highlight"><c- n>t</c-><c- p>,</c-> <c- n>init</c-></code> shall, if <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> is <code class="highlight">true</code>, construct an
instance, <code class="highlight"><c- n>callback</c-></code>, of type <code class="highlight"><c- n>CB</c-></code>, direct-initialized with <code class="highlight"><c- n>init</c-></code>,
and register callback with <code class="highlight"><c- n>t</c-></code>'s shared stop state such that <code class="highlight"><c- n>callback</c-></code> will be invoked with an empty argument list if a stop request is made
on the shared stop state.</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> evaluates to <code class="highlight">true</code> at the time <code class="highlight"><c- n>callback</c-></code> is
registered then <code class="highlight"><c- n>callback</c-></code> may be invoked on the thread executing <code class="highlight"><c- n>cb</c-></code>'s constructor.</p>
          <li data-md>
           <p>If <code class="highlight"><c- n>callback</c-></code> is invoked then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same shared stop
state, an evaluation of <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> will be <code class="highlight">true</code> if the beginning of the invocation of <code class="highlight"><c- n>callback</c-></code> strongly-happens-before the evaluation of <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code>.</p>
          <li data-md>
           <p>[<em>Note:</em> If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> evaluates to <code class="highlight">false</code> then the construction of <code class="highlight"><c- n>cb</c-></code> is not required to construct and initialize <code class="highlight"><c- n>callback</c-></code>. <em>--end note</em>]</p>
         </ol>
        <li data-md>
         <p>Construction of a <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> instance shall only throw exceptions thrown by the initialization of the <code class="highlight"><c- n>CB</c-></code> instance from the value of type <code class="highlight"><c- n>Initializer</c-></code>.</p>
        <li data-md>
         <p>Destruction of the <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> object, <code class="highlight"><c- n>cb</c-></code>, removes <code class="highlight"><c- n>callback</c-></code> from the shared stop state such that <code class="highlight"><c- n>callback</c-></code> will not be invoked after the destructor returns.</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>callback</c-></code> is currently being invoked on another thread then the destructor of <code class="highlight"><c- n>cb</c-></code> will block until the invocation of <code class="highlight"><c- n>callback</c-></code> returns such that the return from the invocation of <code class="highlight"><c- n>callback</c-></code> strongly-happens-before the destruction of <code class="highlight"><c- n>callback</c-></code>.</p>
          <li data-md>
           <p>Destruction of a callback <code class="highlight"><c- n>cb</c-></code> shall not block on the completion of the invocation of some other callback registered with the same shared stop state.</p>
         </ol>
       </ol>
     </ol>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="10.1.3" id="spec-stoptoken"><span class="secno">10.1.3. </span><span class="content">Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b></span><a class="self-link" href="#spec-stoptoken"></a></h4>
   <h5 class="heading settled" data-level="10.1.3.1" id="spec-stoptoken.general"><span class="secno">10.1.3.1. </span><span class="content">General <b>[stoptoken.general]</b></span><a class="self-link" href="#spec-stoptoken.general"></a></h5>
   <p>Modify the synopsis of class <code class="highlight"><c- n>stop_token</c-></code> in section General <b>[stoptoken.general]</b> as follows:</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>stop_token</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
<ins>    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>stop_callback</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c-></ins>

    <c- c1>// [stoptoken.cons], constructors, copy, and assignment</c->
    <c- n>stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>// ...</c->
</pre>
   <h4 class="heading settled" data-level="10.1.4" id="spec-stoptoken.never"><span class="secno">10.1.4. </span><span class="content">Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b></span><a class="self-link" href="#spec-stoptoken.never"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b>, after section Class template <code class="highlight"><c- n>stop_callback</c-></code> <b>[stopcallback]</b>, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.4.1" id="spec-stoptoken.never.general"><span class="secno">10.1.4.1. </span><span class="content">General <b>[stoptoken.never.general]</b></span><a class="self-link" href="#spec-stoptoken.never.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>never_stop_token</c-></code> provides an implementation of the <code class="highlight"><c- n>unstoppable_token</c-></code> concept. It provides a stop token interface, but also provides static information that a stop is never possible nor requested.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c->
<c- p>{</c->
  <c- k>class</c-> <c- nc>never_stop_token</c-> <c- p>{</c->
    <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <i><c- nc>callback</c-></i> <c- p>{</c->
      <c- k>explicit</c-> <i><c- n>callback</c-></i><c- p>(</c-><c- n>never_stop_token</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{}</c->
    <c- p>};</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <i><c- n>callback</c-></i><c- p>;</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>friend</c-> <c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>never_stop_token</c-><c- o>&amp;</c-><c- p>,</c-> <c- k>const</c-> <c- n>never_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="10.1.5" id="spec-stoptoken.inplace"><span class="secno">10.1.5. </span><span class="content">Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b></span><a class="self-link" href="#spec-stoptoken.inplace"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b>, after the section added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.5.1" id="spec-stoptoken.inplace.general"><span class="secno">10.1.5.1. </span><span class="content">General <b>[stoptoken.inplace.general]</b></span><a class="self-link" href="#spec-stoptoken.inplace.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>in_place_stop_token</c-></code> provides an interface for querying whether a stop request has been made (<code class="highlight"><c- n>stop_requested</c-></code>) or can ever be made (<code class="highlight"><c- n>stop_possible</c-></code>) using an associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object ([stopsource.inplace]).
An <code class="highlight"><c- n>in_place_stop_token</c-></code> can also be passed to an <code class="highlight"><c- n>in_place_stop_callback</c-></code> ([stopcallback.inplace]) constructor to register a callback to be called when a stop request has been made from an associated <code class="highlight"><c- n>in_place_stop_source</c-></code>.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>in_place_stop_token</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CB</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-><c- p>;</c->

    <c- c1>// [stoptoken.inplace.cons], constructors, copy, and assignment</c->
    <c- n>in_place_stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- o>~</c-><c- n>in_place_stop_token</c-><c- p>();</c->
    <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>// [stoptoken.inplace.mem], stop handling</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>friend</c-> <c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>,</c-> <c- k>const</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>friend</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>const</c-> <c- n>in_place_stop_source</c-><c- o>*</c-> <i><c- n>source_</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <h5 class="heading settled" data-level="10.1.5.2" id="spec-stoptoken.inplace.cons"><span class="secno">10.1.5.2. </span><span class="content">Constructors, copy, and assignment <b>[stoptoken.inplace.cons]</b></span><a class="self-link" href="#spec-stoptoken.inplace.cons"></a></h5>
<pre class="highlight"><c- n>in_place_stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: initializes <code class="highlight"><i><c- n>source_</c-></i></code> with <code class="highlight"><c- k>nullptr</c-></code>.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>stop_token</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p><em>Effects</em>: Exchanges the values of <code class="highlight"><i><c- n>source_</c-></i></code> and <code class="highlight"><c- n>rhs</c-><c- p>.</c-><i><c- n>source_</c-></i></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.5.3" id="spec-stoptoken.inplace.mem"><span class="secno">10.1.5.3. </span><span class="content">Members <b>[stoptoken.inplace.mem]</b></span><a class="self-link" href="#spec-stoptoken.inplace.mem"></a></h5>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- k>return</c-> <i><c- n>source_</c-></i> <c- o>!=</c-> <c- k>nullptr</c-> <c- o>&amp;&amp;</c-> <i><c- n>source_</c-></i><c- o>-></c-><c- n>stop_requested</c-><c- p>();</c-></code></p>
    <li data-md>
     <p>[<em>Note</em>: The behavior of <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is undefined unless the call
strongly happens before the start of the destructor of the associated <code class="highlight"><c- n>in_place_stop_source</c-></code>, if any ([basic.life]). --<em>end note</em>]</p>
   </ol>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- k>return</c-> <i><c- n>source_</c-></i> <c- o>!=</c-> <c- k>nullptr</c-><c- p>;</c-></code></p>
    <li data-md>
     <p>[<em>Note</em>: The behavior of <code class="highlight"><c- n>stop_possible</c-><c- p>()</c-></code> is implementation-defined unless
the call strongly happens before the end of the storage duration of the
associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any ([basic.stc.general]). --<em>end note</em>]</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.5.4" id="spec-stoptoken.inplace.nonmembers"><span class="secno">10.1.5.4. </span><span class="content">Non-member functions <b>[stoptoken.inplace.nonmembers]</b></span><a class="self-link" href="#spec-stoptoken.inplace.nonmembers"></a></h5>
<pre class="highlight"><c- k>friend</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>y</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- n>x</c-><c- p>.</c-><c- n>swap</c-><c- p>(</c-><c- n>y</c-><c- p>)</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="10.1.6" id="spec-stopsource.inplace"><span class="secno">10.1.6. </span><span class="content">Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b></span><a class="self-link" href="#spec-stopsource.inplace"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b>, after the section added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.6.1" id="spec-stopsource.inplace.general"><span class="secno">10.1.6.1. </span><span class="content">General <b>[stopsource.inplace.general]</b></span><a class="self-link" href="#spec-stopsource.inplace.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>in_place_stop_source</c-></code> implements the semantics of making a stop request, without the need for a dynamic allocation of a shared state.
A stop request made on a <code class="highlight"><c- n>in_place_stop_source</c-></code> object is visible to all associated <code class="highlight"><c- n>in_place_stop_token</c-></code> ([stoptoken.inplace]) objects.
Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).
All uses of <code class="highlight"><c- n>in_place_stop_token</c-></code> objects associated with a given <code class="highlight"><c- n>in_place_stop_source</c-></code> object must happen before the start of the destructor of that <code class="highlight"><c- n>in_place_stop_source</c-></code> object.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>in_place_stop_source</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- c1>// [stopsource.inplace.cons], constructors, copy, and assignment</c->
    <c- n>in_place_stop_source</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>in_place_stop_source</c-><c- p>(</c-><c- n>in_place_stop_source</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
    <c- o>~</c-><c- n>in_place_stop_source</c-><c- p>();</c->

    <c- c1>//[stopsource.inplace.mem], stop handling</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- n>in_place_stop_token</c-> <c- n>get_token</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> true<c- p>;</c-> <c- p>}</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>bool</c-> <c- nf>request_stop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <ol start="2">
    <li data-md>
     <p>An instance of <code class="highlight"><c- n>in_place_stop_source</c-></code> maintains a list of registered callback invocations.
The registration of a callback invocation either succeeds or fails. When an invocation
of a callback is registered, the following happens atomically:</p>
     <ul>
      <li data-md>
       <p>The stop state is checked. If stop has not been requested, the callback invocation is
added to the list of registered callback invocations, and registration has succeeded.</p>
      <li data-md>
       <p>Otherwise, registration has failed.</p>
     </ul>
     <p>When an invocation of a callback is unregistered, the invocation is atomically removed
from the list of registered callback invocations. The removal is not blocked by the concurrent
execution of another callback invocation in the list. If the callback invocation
being unregistered is currently executing, then:</p>
     <ul>
      <li data-md>
       <p>If the execution of the callback invocation is happening concurrently on another thread,
the completion of the execution strongly happens before ([intro.races]) the end of the
callback’s lifetime.</p>
      <li data-md>
       <p>Otherwise, the execution is happening on the current thread. Removal of the
callback invocation does not block waiting for the execution to complete.</p>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="10.1.6.2" id="spec-stopsource.inplace.cons"><span class="secno">10.1.6.2. </span><span class="content">Constructors, copy, and assignment <b>[stopsource.inplace.cons]</b></span><a class="self-link" href="#spec-stopsource.inplace.cons"></a></h5>
<pre class="highlight"><c- n>in_place_stop_source</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: Initializes a new stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.</p>
    <li data-md>
     <p><em>Postconditions</em>: <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">false</code>.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.6.3" id="spec-stopsource.inplace.mem"><span class="secno">10.1.6.3. </span><span class="content">Members <b>[stopsource.inplace.mem]</b></span><a class="self-link" href="#spec-stopsource.inplace.mem"></a></h5>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- n>in_place_stop_token</c-> <c- n>get_token</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Returns</em>: A new associated <code class="highlight"><c- n>in_place_stop_token</c-></code> object.</p>
   </ol>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Returns</em>: <code class="highlight">true</code> if the stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has received a stop request; otherwise, <code class="highlight">false</code>.</p>
   </ol>
<pre class="highlight"><c- b>bool</c-> <c- nf>request_stop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="4">
    <li data-md>
     <p><em>Effects</em>: Atomically determines whether the stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has received a stop request, and if not, makes a stop request.
The determination and making of the stop request are an atomic read-modify-write operation ([intro.races]).
If the request was made, the registered invocations are executed and the evaluations of the invocations are indeterminately sequenced.
If an invocation of a callback exits via an exception then <code class="highlight"><c- n>terminate</c-></code> is invoked ([except.terminate]).</p>
    <li data-md>
     <p><em>Postconditions</em>: <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><em>Returns</em>: <code class="highlight">true</code> if this call made a stop request; otherwise <code class="highlight">false</code>.</p>
   </ol>
   <h4 class="heading settled" data-level="10.1.7" id="spec-stopcallback.inplace"><span class="secno">10.1.7. </span><span class="content">Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b></span><a class="self-link" href="#spec-stopcallback.inplace"></a></h4>
   <p>Insert a new subclause, Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b>, after the section added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.7.1" id="spec-stopcallback.inplace.general"><span class="secno">10.1.7.1. </span><span class="content">General <b>[stopcallback.inplace.general]</b></span><a class="self-link" href="#spec-stopcallback.inplace.general"></a></h5>
   <ol>
    <li data-md>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Callback</c-><c- o>></c->
  <c- k>class</c-> <c- nc>in_place_stop_callback</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>Callback</c-><c- p>;</c->

    <c- c1>// [stopcallback.inplace.cons], constructors and destructor</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>C</c-><c- o>></c->
      <c- k>explicit</c-> <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-> <c- n>st</c-><c- p>,</c-> <c- n>C</c-><c- o>&amp;&amp;</c-> <c- n>cb</c-><c- p>)</c->
        <c- k>noexcept</c-><c- p>(</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-><c- p>);</c->
    <c- o>~</c-><c- n>in_place_stop_callback</c-><c- p>();</c->

    <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_callback</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>Callback</c-> <i><c- n>callback_</c-></i><c- p>;</c->      <i><c- c1>// exposition only</c-></i>
  <c- p>};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Callback</c-><c- o>></c->
    <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- p>,</c-> <c- n>Callback</c-><c- p>)</c->
      <c- o>-></c-> <c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>;</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p><em>Mandates</em>: <code class="highlight"><c- n>in_place_stop_callback</c-></code> is instantiated with an argument for the template parameter <code class="highlight"><c- n>Callback</c-></code> that satisfies both <code class="highlight"><c- n>invocable</c-></code> and <code class="highlight"><c- n>destructible</c-></code>.</p>
    <li data-md>
     <p><em>Preconditions</em>: <code class="highlight"><c- n>in_place_stop_callback</c-></code> is instantiated with an argument for the template parameter <code class="highlight"><c- n>Callback</c-></code> that models both <code class="highlight"><c- n>invocable</c-></code> and <code class="highlight"><c- n>destructible</c-></code>.</p>
    <li data-md>
     <p><em>Recommended practice</em>: Implementations should use the storage of the <code class="highlight"><c- n>in_place_stop_callback</c-></code> objects to store the state necessary for their association with an <code class="highlight"><c- n>in_place_stop_source</c-></code> object.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.7.2" id="spec-stopcallback.inplace.cons"><span class="secno">10.1.7.2. </span><span class="content">Constructors and destructor <b>[stopcallback.inplace.cons]</b></span><a class="self-link" href="#spec-stopcallback.inplace.cons"></a></h5>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>C</c-><c- o>></c->
  <c- k>explicit</c-> <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-> <c- n>st</c-><c- p>,</c-> <c- n>C</c-><c- o>&amp;&amp;</c-> <c- n>cb</c-><c- p>)</c->
    <c- k>noexcept</c-><c- p>(</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Constraints</em>: <code class="highlight"><c- n>Callback</c-></code> and <code class="highlight"><c- n>C</c-></code> satisfy <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-></code>.</p>
    <li data-md>
     <p><em>Preconditions</em>: <code class="highlight"><c- n>Callback</c-></code> and <code class="highlight"><c- n>C</c-></code> model <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-></code>.</p>
    <li data-md>
     <p><em>Effects</em>: Initializes <code class="highlight"><i><c- n>callback_</c-></i></code> with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>C</c-><c- o>></c-><c- p>(</c-><c- n>cb</c-><c- p>)</c-></code>.
Any <code class="highlight"><c- n>in_place_stop_source</c-></code> associated with <code class="highlight"><c- n>st</c-></code> becomes associated with <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.
Registers ([stopsource.inplace.general]) the callback invocation <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>(</c-><i><c- n>callback_</c-></i><c- p>)()</c-></code> with the associated <code class="highlight"><c- n>in_place_stop_source</c-></code>, if any. If the registration fails, evaluates
the callback invocation.</p>
    <li data-md>
     <p><em>Throws</em>: Any exception thrown by the initialization of <code class="highlight"><i><c- n>callback_</c-></i></code>.</p>
    <li data-md>
     <p><em>Remarks</em>: If evaluating <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>(</c-><i><c- n>callback_</c-></i><c- p>)()</c-></code> exits via an exception, then <code class="highlight"><c- n>terminate</c-></code> is invoked ([except.terminate]).</p>
   </ol>
<pre class="highlight"><c- o>~</c-><c- n>in_place_stop_callback</c-><c- p>();</c->
</pre>
   <ol start="6">
    <li data-md>
     <p><em>Effects</em>: Unregisters ([stopsource.inplace.general]) the callback invocation from
the associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any.</p>
    <li data-md>
     <p><em>Remarks</em>: A program has undefined behavior if the start of this destructor does
not strongly happen before the start of the destructor of the associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any.</p>
   </ol>
   <h2 class="heading settled" data-level="11" id="spec-execution"><span class="secno">11. </span><span class="content">Execution control library <b>[exec]</b></span><a class="self-link" href="#spec-execution"></a></h2>
   <ol>
    <li data-md>
     <p>This Clause describes components supporting execution of function objects [function.objects].</p>
    <li data-md>
     <p>The following subclauses describe the requirements, concepts, and components for execution control primitives as summarized in Table 1.</p>
   </ol>
   <table>
    <caption>Table 1: Execution control library summary <b>[tab:execution.summary]</b></caption>
    <tbody>
     <tr>
      <th>
      <td>Subclause
      <td>Header
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.schedulers">[exec.sched]</a>
      <td>Schedulers
      <td><code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.receivers">[exec.recv]</a>
      <td>Receivers
      <td>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.op_state">[exec.op_state]</a>
      <td>Operation states
      <td>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.senders">[exec.snd]</a>
      <td>Senders
      <td>
     <tr>
      <td><a href="#spec-execution.execute">[exec.execute]</a>
      <td>One-way execution
      <td>
   </table>
   <ol start="3">
    <li data-md>
     <p>[<i>Note:</i> A large number of execution control primitives are customization point objects. For an object one might define multiple types of customization point objects, for which different rules apply. Table 2 shows the types of customization point objects used in the execution control library:</p>
   </ol>
   <table>
    <caption>Table 2: Types of customization point objects in the execution control library <b>[tab:execution.cpos]</b></caption>
    <tbody>
     <tr>
      <th>Customization point object type
      <th>Purpose
      <th>Examples
     <tr>
      <td>core
      <td>provide core execution functionality, and connection between core components
      <td><code class="highlight"><c- n>connect</c-></code>, <code class="highlight"><c- n>start</c-></code>, <code class="highlight"><c- n>execute</c-></code>
     <tr>
      <td>completion signals
      <td>called by senders to announce the completion of the work (success, error, or cancellation)
      <td><code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, <code class="highlight"><c- n>set_stopped</c-></code>
     <tr>
      <td><a href="#spec-execution.senders">senders</a>
      <td>allow the specialization of the provided sender algorithms
      <td>
       <ul>
        <li>sender factories (<code class="highlight"><c- n>schedule</c-></code>, <code class="highlight"><c- n>transfer_just</c-></code>, <code class="highlight"><c- n>read</c-></code>, ...)
        <li>sender adaptors (<code class="highlight"><c- n>transfer</c-></code>, <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>let_value</c-></code>, ...)
        <li>sender consumers (<code class="highlight"><c- n>start_detached</c-></code>, <code class="highlight"><c- n>sync_wait</c-></code>)
       </ul>
     <tr>
      <td><a href="#spec-execution.queries">queries</a>
      <td>allow querying different properties of objects
      <td>
       <ul>
        <li>general queries (<code class="highlight"><c- n>get_allocator</c-></code>, <code class="highlight"><c- n>get_stop_token</c-></code>, ...)
        <li>environment queries (<code class="highlight"><c- n>get_scheduler</c-></code>, <code class="highlight"><c- n>get_delegatee_scheduler</c-></code>, ...)
        <li>scheduler queries (<code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>, <code class="highlight"><c- n>execute_may_block_caller</c-></code>, ...)
        <li>sender queries (<code class="highlight"><c- n>get_completion_scheduler</c-></code>)
       </ul>
   </table>
   <p>-- <i>end note</i>]</p>
   <h3 class="heading settled" data-level="11.1" id="spec-execution.syn"><span class="secno">11.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis <b>[exec.syn]</b></span><a class="self-link" href="#spec-execution.syn"></a></h3>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- c1>// [exec.helpers], helper concepts</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>movable</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>From</c-><c- p>,</c-> <c- k>class</c-> <c- nc>To</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>decays</c-><c- o>-</c-><c- n>to</c-></i> <c- o>=</c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>From</c-><c- o>></c-><c- p>,</c-> <c- n>To</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>class</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c-> <c- n>is_class_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->  <i><c- c1>// exposition only</c-></i>

  <c- c1>// [exec.queryable], queryable objects</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>queryable</c-> <c- o>=</c-> <c- n>destructible</c-><t><c- p>;</c->

  <c- c1>// [exec.queries], queries</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <c- nc>forwarding_query_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_allocator_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_stop_token_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>forwarding_query_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_allocator_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_stop_token_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>forwarding_query_t</c-> <c- n>forwarding_query</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_allocator_t</c-> <c- n>get_allocator</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_stop_token_t</c-> <c- n>get_stop_token</c-><c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>using</c-> <c- n>stop_token_of_t</c-> <c- o>=</c->
      <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>()))</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>forwarding</c-><c- o>-</c-><c- n>query</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
      <c- n>forwarding_query</c-><c- p>(</c-><c- n>T</c-><c- p>{});</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</c->
  <c- c1>// [exec.queries], queries</c->
  <c- k>enum</c-> <c- k>class</c-> <c- nc>forward_progress_guarantee</c-><c- p>;</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>get_scheduler_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_delegatee_scheduler_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_forward_progress_guarantee_t</c-><c- p>;</c->
    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>CPO</c-><c- o>></c->
      <c- k>struct</c-> <c- nc>get_completion_scheduler_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_scheduler_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_delegatee_scheduler_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_forward_progress_guarantee_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_completion_scheduler_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_scheduler_t</c-> <c- n>get_scheduler</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_delegatee_scheduler_t</c-> <c- n>get_delegatee_scheduler</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_forward_progress_guarantee_t</c-> <c- n>get_forward_progress_guarantee</c-><c- p>{};</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>CPO</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_completion_scheduler_t</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-> <c- n>get_completion_scheduler</c-><c- p>{};</c->

  <c- c1>// [exec.env], execution environments</c->
  <c- k>namespace</c-> <i><c- nn>exec</c-><c- o>-</c-><c- nn>envs</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <i><c- nc>empty</c-><c- o>-</c-><c- n>env</c-></i> <c- p>{};</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>get_env_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>exec</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>;</c->
  <c- k>using</c-> <i><c- n>exec</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><c- n>get_env_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_env_t</c-> <c- n>get_env</c-> <c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>using</c-> <c- n>env_of_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.sched], schedulers</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>scheduler</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.recv], receivers</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>receiver</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Completions</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>receiver_of</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>receivers</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>set_value_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>set_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>set_stopped_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_value_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_stopped_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_value_t</c-> <c- n>set_value</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_error_t</c-> <c- n>set_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_stopped_t</c-> <c- n>set_stopped</c-><c- p>{};</c->

  <c- c1>// [exec.op_state], operation states</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>O</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>operation_state</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>op</c-><c- o>-</c-><c- nn>state</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>start_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>op</c-><c- o>-</c-><c- n>state</c-></i><c- o>::</c-><c- n>start_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>start_t</c-> <c- n>start</c-><c- p>{};</c->

  <c- c1>// [exec.snd], senders</c->
  <c- k>namespace</c-> <i><c- nn>exec</c-><c- o>-</c-><c- nn>attrs</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <i><c- nc>empty</c-><c- o>-</c-><c- n>attrs</c-></i> <c- p>{};</c->
    <c- k>struct</c-> <c- nc>get_attrs_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>exec</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i><c- p>;</c->
  <c- k>using</c-> <i><c- n>exec</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><c- n>get_attrs_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_attrs_t</c-> <c- n>get_attrs</c-> <c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>using</c-> <c- n>attrs_of_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>()));</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>sender</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
    <c- k>concept</c-> <c- nc>sender_in</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>R</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>sender_to</c-> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Sig</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
    <c- k>concept</c-> <c- nc>sender_of</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>struct</c-> <i><c- nc>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
    <c- k>using</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
    <c- k>concept</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- c1>// [exec.sndtraits], completion signatures</c->
  <c- k>namespace</c-> <i><c- nn>completion</c-><c- o>-</c-><c- nn>signatures</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>get_completion_signatures_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_completion_signatures_t</c-> <c- n>get_completion_signatures</c-> <c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
    <c- k>using</c-> <c- n>completion_signatures_of_t</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i> <c- o>=</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c->
           <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
           <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c->
           <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
    <c- k>using</c-> <c- n>value_types_of_t</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c->
           <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
           <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
    <c- k>using</c-> <c- n>error_types_of_t</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>sends_stopped</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.connect], the connect sender algorithm</c->
  <c- k>namespace</c-> <i><c- nn>senders</c-><c- o>-</c-><c- nn>connect</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>connect_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>senders</c-><c- o>-</c-><c- n>connect</c-></i><c- o>::</c-><c- n>connect_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>connect_t</c-> <c- n>connect</c-><c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>R</c-><c- o>></c->
    <c- k>using</c-> <c- n>connect_result_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(),</c-> <c- n>declval</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.factories], sender factories</c->
  <c- k>namespace</c-> <i><c- nn>senders</c-><c- o>-</c-><c- nn>factories</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>schedule_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>transfer_just_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>unspecified</c-></i> <c- n>just</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>unspecified</c-></i> <c- n>just_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>unspecified</c-></i> <c- n>just_stopped</c-><c- p>{};</c->
  <c- k>using</c-> <i><c- n>senders</c-><c- o>-</c-><c- n>factories</c-></i><c- o>::</c-><c- n>schedule_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>senders</c-><c- o>-</c-><c- n>factories</c-></i><c- o>::</c-><c- n>transfer_just_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>schedule_t</c-> <c- n>schedule</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>transfer_just_t</c-> <c- n>transfer_just</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>unspecified</c-></i> <c- n>read</c-><c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- n>scheduler</c-> <c- n>S</c-><c- o>></c->
    <c- k>using</c-> <c- n>schedule_result_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.adapt], sender adaptors</c->
  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptor</c-><c- o>-</c-><c- nn>closure</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>template</c-><c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>D</c-><c- o>></c->
      <c- k>struct</c-> <c- nc>sender_adaptor_closure</c-> <c- p>{</c-> <c- p>};</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptor</c-><c- o>-</c-><c- n>closure</c-></i><c- o>::</c-><c- n>sender_adaptor_closure</c-><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptors</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>on_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>transfer_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>schedule_from_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>then_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>upon_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>upon_stopped_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_value_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_stopped_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>bulk_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>split_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>when_all_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>when_all_with_variant_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>transfer_when_all_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>transfer_when_all_with_variant_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>into_variant_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>stopped_as_optional_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>stopped_as_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>ensure_started_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>on_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>transfer_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>schedule_from_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>then_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>upon_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>upon_stopped_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_value_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_stopped_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>bulk_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>split_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>when_all_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>when_all_with_variant_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>transfer_when_all_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>transfer_when_all_with_variant_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>into_variant_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>stopped_as_optional_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>stopped_as_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>ensure_started_t</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>on_t</c-> <c- n>on</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>transfer_t</c-> <c- n>transfer</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>schedule_from_t</c-> <c- n>schedule_from</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>then_t</c-> <c- n>then</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>upon_error_t</c-> <c- n>upon_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>upon_stopped_t</c-> <c- n>upon_stopped</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_value_t</c-> <c- n>let_value</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_error_t</c-> <c- n>let_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_stopped_t</c-> <c- n>let_stopped</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>bulk_t</c-> <c- n>bulk</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>split_t</c-> <c- n>split</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>when_all_t</c-> <c- n>when_all</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>when_all_with_variant_t</c-> <c- n>when_all_with_variant</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>transfer_when_all_t</c-> <c- n>transfer_when_all</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>transfer_when_all_with_variant_t</c->
    <c- n>transfer_when_all_with_variant</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>into_variant_t</c-> <c- n>into_variant</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>stopped_as_optional_t</c-> <c- n>stopped_as_optional</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>stopped_as_error_t</c-> <c- n>stopped_as_error</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>ensure_started_t</c-> <c- n>ensure_started</c-><c- p>{};</c->

  <c- c1>// [exec.consumers], sender consumers</c->
  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>consumers</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>start_detached_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>consumers</c-></i><c- o>::</c-><c- n>start_detached_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>start_detached_t</c-> <c- n>start_detached</c-><c- p>{};</c->

  <c- c1>// [exec.utils], sender and receiver utilities</c->
  <c- c1>// [exec.utils.rcvr_adptr]</c->
  <c- k>template</c-><c- o>&lt;</c->
      <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
      <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
    <c- k>class</c-> <c- nc>receiver_adaptor</c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>completion</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
      <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.utils.cmplsigs]</c->
  <c- k>template</c-> <c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i><c- p>...</c-> <c- n>Fns</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>completion_signatures</c-> <c- p>{};</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-> <i><c- c1>// exposition only</c-></i>
    <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c->
      <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c-> <i><c- c1>// exposition only</c-></i>
    <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i> <c- o>=</c->
      <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>Err</c-><c- p>)</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sigs</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c-> <c- c1>// exposition only</c->
    <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.utils.mkcmplsigs]</c->
  <c- k>template</c-> <c- o>&lt;</c->
    <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c->
    <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-> <c- n>AddlSigs</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>,</c->
    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetValue</c-> <c- o>=</c-> <i><c- d>/* see below */</c-></i><c- p>,</c->
    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetError</c-> <c- o>=</c-> <i><c- d>/* see below */</c-></i><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-> <c- n>SetStopped</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- k>using</c-> <c- n>make_completion_signatures</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- d>/* see below */</c-></i><c- o>></c-><c- p>;</c->

  <c- c1>// [exec.ctx], execution contexts</c->
  <c- k>class</c-> <c- nc>run_loop</c-><c- p>;</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>this_thread</c-> <c- p>{</c->
  <c- c1>// [exec.queries], queries</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <c- nc>execute_may_block_caller_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>execute_may_block_caller_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>execute_may_block_caller_t</c-> <c- n>execute_may_block_caller</c-><c- p>{};</c->

  <c- k>namespace</c-> <i><c- nn>this</c-><c- o>-</c-><c- nn>thread</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <i><c- nc>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
        <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
      <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
      <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

    <c- k>struct</c-> <c- nc>sync_wait_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>sync_wait_with_variant_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- k>this</c-><c- o>-</c-><c- kr>thread</c-></i><c- o>::</c-><c- n>sync_wait_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- k>this</c-><c- o>-</c-><c- kr>thread</c-></i><c- o>::</c-><c- n>sync_wait_with_variant_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>sync_wait_t</c-> <c- n>sync_wait</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>sync_wait_with_variant_t</c-> <c- n>sync_wait_with_variant</c-><c- p>{};</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</c->
  <c- c1>// [exec.execute], one-way execution</c->
  <c- k>namespace</c-> <i><c- nn>execute</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>execute_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>execute</c-></i><c- o>::</c-><c- n>execute_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>execute_t</c-> <c- n>execute</c-><c- p>{};</c->

  <c- c1>// [exec.as_awaitable]</c->
  <c- k>namespace</c-> <i><c- nn>coro</c-><c- o>-</c-><c- nn>utils</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>as_awaitable_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>coro</c-><c- o>-</c-><c- n>utils</c-></i><c- o>::</c-><c- n>as_awaitable_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>as_awaitable_t</c-> <c- n>as_awaitable</c-><c- p>;</c->

  <c- c1>// [exec.with_awaitable_senders]</c->
  <c- k>template</c-> <c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Promise</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>with_awaitable_senders</c-><c- p>;</c->
<c- p>}</c->
</t></pre>
   <h3 class="heading settled" data-level="11.2" id="spec-execution.helpers"><span class="secno">11.2. </span><span class="content">Helper concepts <b>[exec.helpers]</b></span><a class="self-link" href="#spec-execution.helpers"></a></h3>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>movable</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- n>T</c-><c- o>></c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="11.3" id="spec-execution.queries"><span class="secno">11.3. </span><span class="content">Queries <b>[exec.queries]</b></span><a class="self-link" href="#spec-execution.queries"></a></h3>
   <ol>
    <li data-md>
     <p>A <i>query object</i> is a customization point object
([customization.point.object]) that accepts as its
first argument a <code class="highlight"><c- n>queryable</c-></code> object, and for each such invocation that is
valid, produces a value of the corresponding property of the object.</p>
    <li data-md>
     <p>Unless otherwise specified, given a queryable object <code class="highlight"><c- n>e</c-></code>, a query object <code class="highlight"><i><c- n>Q</c-></i></code>, and a pack of subexpressions <code class="highlight"><c- n>args</c-></code>, the value
returned by the expression <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is valid as
long as <code class="highlight"><c- n>e</c-></code> is valid.</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.1" id="spec-execution.queries.queryable"><span class="secno">11.3.1. </span><span class="content"><code class="highlight"><c- n>queryable</c-></code> concept <b>[exec.queries.queryable]</b></span><a class="self-link" href="#spec-execution.queries.queryable"></a></h4>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>queryable</c-> <c- o>=</c-> <c- n>destructible</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>e</c-></code> be an object of type <code class="highlight"><c- n>E</c-></code>. The type <code class="highlight"><c- n>E</c-></code> models <code class="highlight"><c- n>queryable</c-></code> if for each callable
object <code class="highlight"><i><c- n>Q</c-></i></code> and a pack of subexpressions <code class="highlight"><c- n>args</c-></code>, if <code class="highlight"><c- k>requires</c-> <c- p>{</c-> <i><c- n>Q</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-> <c- p>}</c-></code> is <code class="highlight">true</code> then <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> meets any semantic requirements imposed by <code class="highlight"><c- n>Q</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.2" id="spec-execution.queries.forwarding_query"><span class="secno">11.3.2. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> <b>[exec.fwd_env]</b></span><a class="self-link" href="#spec-execution.queries.forwarding_query"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> is used to ask a query object whether it should be forwarded through queryable adaptors.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> denotes a query object. For some query object <code class="highlight"><c- n>q</c-></code> of type <code class="highlight"><c- n>Q</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>,</c-> <c- n>q</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The expression is a core constant expressions if <code class="highlight"><c- n>q</c-></code> is a core constant expression, has type <code class="highlight"><c- b>bool</c-></code>, and is not potentially-throwing.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight">true</code> if <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>Q</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forwarding_query_t</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight">false</code>.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.3.3" id="spec-execution.queries.get_allocator"><span class="secno">11.3.3. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> <b>[exec.queries.get_allocator]</b></span><a class="self-link" href="#spec-execution.queries.get_allocator"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> is used to ask an object for its associated allocator.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not
potentially-throwing and its type satisfies <i>Allocator</i>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.4" id="spec-execution.queries.get_stop_token"><span class="secno">11.3.4. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> <b>[exec.queries.get_stop_token]</b></span><a class="self-link" href="#spec-execution.queries.get_stop_token"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> is used to ask an object for an associated stop token.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not
potentially-throwing and its type satisfies <code class="highlight"><c- n>stoppable_token</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>never_stop_token</c-><c- p>{}</c-></code>.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.5" id="spec-execution.queries.get_scheduler"><span class="secno">11.3.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> <b>[exec.queries.get_scheduler]</b></span><a class="self-link" href="#spec-execution.queries.get_scheduler"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> is used to ask an object for its associated scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> denotes a query object. For some
subexpression <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression equivalent
to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not
potentially-throwing and its type satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.6" id="spec-execution.queries.get_delegatee_scheduler"><span class="secno">11.3.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> <b>[exec.queries.get_delegatee_scheduler]</b></span><a class="self-link" href="#spec-execution.queries.get_delegatee_scheduler"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> is used to ask an object for a scheduler that may be used to delegate work to for the purpose of forward progress delegation.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not
potentially-throwing and its type satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.7" id="spec-execution.queries.get_forward_progress_guarantee"><span class="secno">11.3.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> <b>[exec.queries.get_forward_progress_guarantee]</b></span><a class="self-link" href="#spec-execution.queries.get_forward_progress_guarantee"></a></h4>
<pre class="highlight"><c- k>enum</c-> <c- k>class</c-> <c- nc>forward_progress_guarantee</c-> <c- p>{</c->
  <c- n>concurrent</c-><c- p>,</c->
  <c- n>parallel</c-><c- p>,</c->
  <c- n>weakly_parallel</c->
<c- p>};</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> is used to ask a scheduler about the forward progress guarantees of execution agents created by that scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> is ill-formed.
Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>s</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing and its type is <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>forward_progress_guarantee</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>weakly_parallel</c-></code>.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> for some scheduler <code class="highlight"><c- n>s</c-></code> returns <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>concurrent</c-></code>, all execution agents created by that scheduler shall provide the concurrent forward progress guarantee. If it returns <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>parallel</c-></code>, all execution agents created by that scheduler shall provide at least the parallel forward progress guarantee.</p>
   </ol>
   <h4 class="heading settled" data-level="11.3.8" id="spec-execution.queries.execute_may_block_caller"><span class="secno">11.3.8. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> <b>[exec.queries.execute_may_block_caller]</b></span><a class="self-link" href="#spec-execution.queries.execute_may_block_caller"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> is used to ask a scheduler <code class="highlight"><c- n>s</c-></code> whether a call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> with any invocable <code class="highlight"><c- n>f</c-></code> may block the thread where such a call occurs.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>s</c-><c- p>))</c-></code>, if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing and its type is <code class="highlight"><c- b>bool</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight">true</code>.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> for some scheduler <code class="highlight"><c- n>s</c-></code> returns <code class="highlight">false</code>, no <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> call with some invocable <code class="highlight"><c- n>f</c-></code> shall block the calling thread.</p>
   </ol>
   <h5 class="heading settled" data-level="11.3.8.1" id="spec-execution.queries.get_completion_scheduler"><span class="secno">11.3.8.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> <b>[exec.queries.completion_scheduler]</b></span><a class="self-link" href="#spec-execution.queries.get_completion_scheduler"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> is used to obtain the <i>completion scheduler</i> for one of its signals from the sender attributes.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> denotes a query object template.
For some subexpression <code class="highlight"><c- n>q</c-></code>, let <code class="highlight"><c- n>Q</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>q</c-><c- p>))</c-></code>. If the template
argument <code class="highlight"><c- n>CPO</c-></code> in <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is not one of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-></code>, or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped_t</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>q</c-><c- p>))</c-></code> if this expression is well formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially throwing and its type satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>If, for some sender <code class="highlight"><c- n>s</c-></code> and customization point object <code class="highlight"><c- n>CPO</c-></code>, <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>CPO</c-><c- p>)</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>))</c-></code> is well-formed and results in a scheduler <code class="highlight"><c- n>sch</c-></code>, and the sender <code class="highlight"><c- n>s</c-></code> invokes <code class="highlight"><c- n>CPO</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, for some receiver <code class="highlight"><c- n>r</c-></code> that has been connected to <code class="highlight"><c- n>s</c-></code>, with additional arguments <code class="highlight"><c- n>args</c-><c- p>...</c-></code>, on an execution agent that does not belong to the associated execution context of <code class="highlight"><c- n>sch</c-></code>, the behavior is undefined.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>forwarding_query</c-><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>)</c-></code> has value <code class="highlight">true</code>.</p>
   </ol>
   <h3 class="heading settled" data-level="11.4" id="spec-execution.environment"><span class="secno">11.4. </span><span class="content">Execution environments <b>[exec.env]</b></span><a class="self-link" href="#spec-execution.environment"></a></h3>
   <ol>
    <li data-md>
     <p>An <i>execution environment</i> is a queryable object ([exec.queryable]) that contains
state associated with the completion of an asynchronous operation. Every receiver
has an associated execution environment, accessible with the <code class="highlight"><c- n>get_env</c-></code> customization
point object ([exec.get_env]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.4.1" id="spec-execution.environment.get_env"><span class="secno">11.4.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-></code> <b>[exec.get_env]</b></span><a class="self-link" href="#spec-execution.environment.get_env"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code> is a customization point object. For some subexpression <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the expression satisfies the <code class="highlight"><c- n>queryable</c-></code> concept ([exec.queryable]).</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is an lvalue, the object it refers to shall be valid while <code class="highlight"><c- n>r</c-></code> is valid.</p>
   </ol>
   <h3 class="heading settled" data-level="11.5" id="spec-execution.schedulers"><span class="secno">11.5. </span><span class="content">Schedulers <b>[exec.sched] </b></span><a class="self-link" href="#spec-execution.schedulers"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>scheduler</c-></code> concept defines the requirements of a type that allows for scheduling of work on its <i>associated execution context</i>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>scheduler</c-> <c- o>=</c->
    <c- n>queryable</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-><c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- k>const</c-> <c- n>get_completion_scheduler_t</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-> <c- n>tag</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(</c-><c- n>s</c-><c- p>))</c-> <c- p>}</c-> <c- o>-></c-> <c- n>sender</c-><c- p>;</c->
      <c- p>{</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-><c- p>(</c->
          <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(</c-><c- n>s</c-><c- p>))))</c-> <c- p>}</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>equality_comparable</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>copy_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>S</c-></code> be the type of a scheduler and let <code class="highlight"><c- n>E</c-></code> be the type of an execution environment for which <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is <code class="highlight">true</code>. Then <code class="highlight"><c- n>sender_of</c-><c- o>&lt;</c-><c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>set_value_t</c-><c- p>(),</c-> <c- n>E</c-><c- o>></c-></code> shall be <code class="highlight">true</code>.</p>
    <li data-md>
     <p>None of a scheduler’s copy constructor, destructor, equality comparison, or <code class="highlight"><c- n>swap</c-></code> member functions shall exit via an exception.</p>
    <li data-md>
     <p>None of these member functions, nor a scheduler type’s <code class="highlight"><c- n>schedule</c-></code> function, shall introduce data races as a result of concurrent invocations of those functions from different threads.</p>
    <li data-md>
     <p>For any two (possibly const) values <code class="highlight"><c- n>s1</c-></code> and <code class="highlight"><c- n>s2</c-></code> of some scheduler type <code class="highlight"><c- n>S</c-></code>, <code class="highlight"><c- n>s1</c-> <c- o>==</c-> <c- n>s2</c-></code> shall return <code class="highlight">true</code> only if both <code class="highlight"><c- n>s1</c-></code> and <code class="highlight"><c- n>s2</c-></code> are handles to the same associated execution context.</p>
    <li data-md>
     <p>For a given scheduler expression <code class="highlight"><c- n>s</c-></code>, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>s</c-><c- p>)))</c-></code> shall compare equal to <code class="highlight"><c- n>s</c-></code>.</p>
    <li data-md>
     <p>A scheduler type’s destructor shall not block pending completion of any receivers connected to the sender objects returned from <code class="highlight"><c- n>schedule</c-></code>. <span class="wg21note">The ability to wait for completion of submitted function objects may be provided by the associated execution
context of the scheduler.</span></p>
   </ol>
   <h3 class="heading settled" data-level="11.6" id="spec-execution.receivers"><span class="secno">11.6. </span><span class="content">Receivers <b>[exec.recv]</b></span><a class="self-link" href="#spec-execution.receivers"></a></h3>
   <ol>
    <li data-md>
     <p>A <i>receiver</i> represents the continuation of an asynchronous operation.
An asynchronous operation may complete with a (possibly empty) set of
values, an error, or it may be cancelled. A receiver has three principal
operations corresponding to the three ways an asynchronous operation may
complete: <code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, and <code class="highlight"><c- n>set_stopped</c-></code>. These are
collectively known as a receiver’s completion-signal operations.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>receiver</c-></code> concept defines the requirements for a receiver type with an
unknown set of completion signatures. The <code class="highlight"><c- n>receiver_of</c-></code> concept defines the
requirements for a receiver type with a known set of completion signatures.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>receiver</c-> <c- o>=</c->
    <c- k>requires</c-><c- p>(</c-><c- k>const</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <c- n>queryable</c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- n>T</c-><c- o>></c-><c- p>;</c->
        
<div class="ed-note"><c- n>Should</c-> <c- n>these</c-> <c- n>constructibility</c-> <c- n>constraints</c-> <c- n>instead</c-> <c- n>be</c-> <c- n>mandates</c->
<c- n>and</c-> <c- n>cause</c-> <c- n>hard</c-> <c- n>errors</c-> <c- n>instead</c-> <c- n>of</c-> <c- n>substitution</c-> <c- n>failures</c-><c- o>?</c-></div>

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Signature</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- k>for</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>requires</c-> <c- p>(</c-><c- n>Signature</c-><c- o>*</c-> <c- n>sig</c-><c- p>)</c-> <c- p>{</c->
        <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Ret</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>Ret</c-><c- p>(</c-><c- o>*</c-><c- p>)(</c-><c- n>Args</c-><c- p>...))</c->
            <c- k>requires</c-> <c- n>nothrow_tag_invocable</c-><c- o>&lt;</c-><c- n>Ret</c-><c- p>,</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
        <c- p>{}(</c-><c- n>sig</c-><c- p>);</c->
    <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Completions</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>receiver_of</c-> <c- o>=</c->
    <c- n>receiver</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Completions</c-><c- o>*</c-> <c- n>completions</c-><c- p>)</c-> <c- p>{</c->
        <c- p>[]</c-><c- o>&lt;</c-><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>...</c-><c- n>Sigs</c-><c- o>></c-><c- p>(</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Sigs</c-><c- p>...</c-><c- o>>*</c-><c- p>)</c->
        <c- p>{}(</c-><c- n>completions</c-><c- p>);</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p>The receiver’s completion-signal operations have semantic requirements that are collectively known as the <i>receiver contract</i>, described below:</p>
     <ol>
      <li data-md>
       <p>None of a receiver’s completion-signal operations shall be invoked before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> has been called on the operation state object that was returned by <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> to connect that receiver to a sender.</p>
      <li data-md>
       <p>Once <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> has been called on the operation state object, exactly one of the receiver’s completion-signal operations shall complete before the receiver is destroyed.</p>
     </ol>
    <li data-md>
     <p>Once one of a receiver’s completion-signal operations has completed, the receiver contract has been satisfied.</p>
    <li data-md>
     <p>Receivers have an associated execution environment ([exec.env]) that is accessible
by passing the receiver to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-></code>. A sender algorithm can obtain
information about the current execution environment by querying the environment of
the receiver to which its sender is connected.</p>
    <li data-md>
     <p>Given a non-<code class="highlight"><c- k>const</c-></code> rvalue <code class="highlight"><c- n>r</c-></code> of type <code class="highlight"><c- n>R</c-></code> where <code class="highlight"><c- n>R</c-></code> models <code class="highlight"><c- n>receiver</c-></code>,
then the expressions <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>),</c-> <i><c- n>args</c-><c- p>...</c-></i><c- p>)</c-></code> and <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>R</c-><c- o>&amp;></c-><c- p>(</c-><c- n>r</c-><c- p>)),</c-> <i><c- n>args</c-><c- p>...</c-></i><c- p>)</c-></code> shall be equivalent for any query object <code class="highlight"><i><c- n>Q</c-></i></code> and for
any pack of subexpressions <code class="highlight"><i><c- n>args</c-></i></code>.</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>r</c-></code> be a receiver, <code class="highlight"><c- n>s</c-></code> be a sender, and <code class="highlight"><c- n>op_state</c-></code> be an operation state
resulting from an <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> call. Let <code class="highlight"><c- n>token</c-></code> be a stop
token resulting from an <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code> call. <code class="highlight"><c- n>token</c-></code> must remain valid at least until a call to a receiver
completion-signal function of <code class="highlight"><c- n>r</c-></code> returns successfully. [<i>Note</i>: this
means that, unless it knows about further guarantees provided by the
receiver <code class="highlight"><c- n>r</c-></code>, the implementation of <code class="highlight"><c- n>op_state</c-></code> should not use <code class="highlight"><c- n>token</c-></code> after
it makes a call to a receiver completion-signal function of <code class="highlight"><c- n>r</c-></code>. This also
implies that any stop callbacks registered on <code class="highlight"><c- n>token</c-></code> by the implementation
of <code class="highlight"><c- n>op_state</c-></code> or <code class="highlight"><c- n>s</c-></code> must be destroyed before such a call to a receiver
completion-signal function of <code class="highlight"><c- n>r</c-></code>. --<i>end note</i>]</p>
   </ol>
   <h4 class="heading settled" data-level="11.6.1" id="spec-execution.receivers.set_value"><span class="secno">11.6.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> <b>[exec.set_value]</b></span><a class="self-link" href="#spec-execution.receivers.set_value"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> is used to send a value completion signal to a receiver.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> denotes a customization point object. The
expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>R</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...)</c-></code> for some subexpression <code class="highlight"><c- n>R</c-></code> and
pack of subexpressions <code class="highlight"><c- n>Vs</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>,</c-> <c- n>R</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...)</c-></code>, if that expression is
valid. The function selected by <code class="highlight"><c- n>tag_invoke</c-></code> shall send the
value(s) <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> to the receiver <code class="highlight"><c- n>R</c-></code>’s value channel.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>R</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.6.2" id="spec-execution.receivers.set_error"><span class="secno">11.6.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> <b>[exec.set_error]</b></span><a class="self-link" href="#spec-execution.receivers.set_error"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> is used to send an error completion signal to a receiver.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> denotes a customization point object. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>R</c-><c- p>,</c-> <c- n>E</c-><c- p>)</c-></code> for some subexpressions <code class="highlight"><c- n>R</c-></code> and <code class="highlight"><c- n>E</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>,</c-> <c- n>R</c-><c- p>,</c-> <c- n>E</c-><c- p>)</c-></code>, if that expression is valid.
The function selected by <code class="highlight"><c- n>tag_invoke</c-></code> shall send the error <code class="highlight"><c- n>E</c-></code> to the
receiver <code class="highlight"><c- n>R</c-></code>’s error channel.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>R</c-><c- p>,</c-> <c- n>E</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.6.3" id="spec-execution.receivers.set_stopped"><span class="secno">11.6.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> <b>[exec.set_stopped]</b></span><a class="self-link" href="#spec-execution.receivers.set_stopped"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> is used to send a stopped completion signal to a receiver.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> denotes a customization point object. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>R</c-><c- p>)</c-></code> for some subexpression <code class="highlight"><c- n>R</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>,</c-> <c- n>R</c-><c- p>)</c-></code>, if that expression is valid. The function selected by <code class="highlight"><c- n>tag_invoke</c-></code> shall signal the receiver <code class="highlight"><c- n>R</c-></code>’s stopped channel.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>R</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.7" id="spec-execution.op_state"><span class="secno">11.7. </span><span class="content">Operation states <b>[exec.op_state]</b></span><a class="self-link" href="#spec-execution.op_state"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>operation_state</c-></code> concept defines the requirements for an operation state type, which allows for starting the execution of work.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>O</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>operation_state</c-> <c- o>=</c->
    <c- n>queryable</c-><c- o>&lt;</c-><c- n>O</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>is_object_v</c-><c- o>&lt;</c-><c- n>O</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>O</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p>Any operation state types defined by the implementation are non-movable types.</p>
   </ol>
   <h4 class="heading settled" data-level="11.7.1" id="spec-execution.op_state.start"><span class="secno">11.7.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> <b>[exec.op_state.start]</b></span><a class="self-link" href="#spec-execution.op_state.start"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is used to start work represented by an operation state object.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> denotes a customization point object. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> for some lvalue subexpression <code class="highlight"><c- n>O</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>,</c-> <c- n>O</c-><c- p>)</c-></code>, if that expression is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not start the work represented by the operation state <code class="highlight"><c- n>O</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The <code class="highlight"><c- n>tag_invoke</c-></code> expression above is not potentially
throwing.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>The caller of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> must guarantee that the lifetime of the operation state object <code class="highlight"><c- n>O</c-></code> extends at least until one of the receiver completion-signal functions of a receiver <code class="highlight"><c- n>R</c-></code> passed into the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> call that produced <code class="highlight"><c- n>O</c-></code> is ready
to successfully return. <span class="wg21note">This allows for the receiver to manage the lifetime of the operation state object, if destroying it is the last operation it performs in its completion-signal functions.</span></p>
   </ol>
   <h3 class="heading settled" data-level="11.8" id="spec-execution.senders"><span class="secno">11.8. </span><span class="content">Senders <b>[exec.snd]</b></span><a class="self-link" href="#spec-execution.senders"></a></h3>
   <ol>
    <li data-md>
     <p>A sender describes a potentially asynchronous operation. A sender’s responsibility is to fulfill the receiver contract of a connected receiver by delivering one of the receiver completion-signals.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.1" id="spec-execution.environment.get_attrs"><span class="secno">11.8.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-></code> <b>[exec.get_attrs]</b></span><a class="self-link" href="#spec-execution.environment.get_attrs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_attrs</c-></code> is a customization point object. For some subexpression <code class="highlight"><c- n>s</c-></code>, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the expression satisfies the <code class="highlight"><c- n>queryable</c-></code> concept ([exec.queryable]).</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i><c- p>{}</c-></code> if the type of <code class="highlight"><c- n>s</c-></code> satisfies
the <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>>></c-></code> concept ([exec.complsigs]).</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is an lvalue, the object it refers to shall be valid while <code class="highlight"><c- n>s</c-></code> is valid.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.2" id="spec-execution.environment.snd_concepts"><span class="secno">11.8.2. </span><span class="content">Sender concepts <b>[exec.snd_concepts]</b></span><a class="self-link" href="#spec-execution.environment.snd_concepts"></a></h4>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender</c-></code> concept defines the requirements for a sender type.
The <code class="highlight"><c- n>sender_in</c-></code> concept defines the requirements for a sender within a
particular execution environment.
The <code class="highlight"><c- n>sender_to</c-></code> concept defines the requirements for a sender type capable of
being connected with a specific receiver type.</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>C</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <i><c- n>is</c-><c- o>-</c-><c- n>instance</c-><c- o>-</c-><c- n>of</c-></i> <c- o>=</c-> false<c- p>;</c-> <c- c1>// exposition only</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- p>,</c-> <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>C</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <i><c- n>is</c-><c- o>-</c-><c- n>instance</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><c- n>C</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>C</c-><c- o>></c-> <c- o>=</c-> true<c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sigs</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
    <i><c- n>is</c-><c- o>-</c-><c- n>instance</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><c- n>Sigs</c-><c- p>,</c-> <c- n>completion_signatures</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>sender</c-> <c- o>=</c->
    <c- k>requires</c-> <c- p>(</c-><c- k>const</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <c- n>queryable</c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
  <c- k>concept</c-> <c- nc>sender_in</c-> <c- o>=</c->
    <c- n>sender</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>E</c-><c- o>&amp;&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>get_completion_signatures</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>E</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>))</c-> <c- p>}</c-> <c- o>-></c->
        <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>E</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>R</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>sender_to</c-> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>receiver_of</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>R</c-><c- o>&amp;&amp;</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
      <c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- p>));</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p>Given a non-<code class="highlight"><c- k>const</c-></code> rvalue <code class="highlight"><c- n>s</c-></code> of type <code class="highlight"><c- n>S</c-></code> where <code class="highlight"><c- n>S</c-></code> models <code class="highlight"><c- n>sender</c-></code>,
then the expressions <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <i><c- n>args</c-><c- p>...</c-></i><c- p>)</c-></code> and <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>S</c-><c- o>&amp;></c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <i><c- n>args</c-><c- p>...</c-></i><c- p>)</c-></code> shall be equivalent for any query object <code class="highlight"><i><c- n>Q</c-></i></code> and for
any pack of subexpressions <code class="highlight"><i><c- n>args</c-></i></code>.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender_of</c-></code> concept defines the requirements for a sender type that
completes with the completion signature specified for the given completion
channel.</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>struct</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>helper</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>R</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>helper</c-></i><c- o>&lt;</c-><c- n>R</c-><c- p>(</c-><c- n>As</c-><c- p>...)</c-><c- o>></c-> <c- p>{</c->
    <c- k>using</c-> <i><c- n>tag</c-></i> <c- o>=</c-> <c- n>R</c-><c- p>;</c->

    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Bs</c-><c- o>></c->
      <c- k>using</c-> <i><c- n>as</c-><c- o>-</c-><c- n>sig</c-></i> <c- o>=</c-> <c- n>R</c-><c- p>(</c-><c- n>Bs</c-><c- p>...);</c->
  <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Sig</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
  <c- k>concept</c-> <c- nc>sender_of</c-> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>same_as</c-><c- o>&lt;</c->
      <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;</c-><c- n>Sig</c-><c- o>></c-><c- p>,</c->
      <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c->  <i><c- c1>// See [exec.utils.cmplsigs]</c-></i>
        <c- k>typename</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>helper</c-></i><c- o>&lt;</c-><c- n>Sig</c-><c- o>>::</c-><i><c- n>tag</c-></i><c- p>,</c->
        <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c->
        <i><c- n>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>helper</c-></i><c- o>&lt;</c-><c- n>Sig</c-><c- o>>::</c-><c- k>template</c-> <i><c- n>as</c-><c- o>-</c-><c- n>sig</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>>></c-><c- p>;</c->
</pre>
     <ol>
      <li data-md>
       <p>[<em>Example:</em></p>
<pre class="highlight"><c- k>auto</c-> <c- n>s1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>()</c-> <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([]{});</c->
<c- k>using</c-> <c- n>S1</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>s1</c-><c- p>);</c->

<c- k>static_assert</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S1</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>()</c-><c- o>></c-><c- p>);</c->
<c- k>static_assert</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S1</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>);</c->
<c- k>static_assert</c-><c- p>(</c-><c- o>!</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S1</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c-><c- p>);</c->

<c- k>auto</c-> <c- n>s2</c-> <c- o>=</c-> <c- n>s1</c-> <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_error</c-><c- p>([](</c-><c- k>auto</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- sc>'a'</c-><c- p>);</c-> <c- p>});</c->
<c- k>using</c-> <c- n>S2</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>s2</c-><c- p>);</c->

<c- k>static_assert</c-><c- p>(</c-><c- o>!</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>()</c-><c- o>></c-><c- p>);</c->
<c- k>static_assert</c-><c- p>(</c-><c- o>!</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- b>char</c-><c- p>)</c-><c- o>></c-><c- p>);</c->
<c- k>static_assert</c-><c- p>(</c-><c- o>!</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>);</c->
<c- k>static_assert</c-><c- p>(</c-><c- o>!</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c-><c- p>);</c->
</pre>
       <p>-- <em>end example</em>]</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.8.3" id="spec-exec.sndtraits"><span class="secno">11.8.3. </span><span class="content">Completion signatures <b>[exec.sndtraits]</b></span><a class="self-link" href="#spec-exec.sndtraits"></a></h4>
   <h5 class="heading settled" data-level="11.8.3.1" id="spec-exec.complsigs"><span class="secno">11.8.3.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures_of_t</c-></code> <b>[exec.complsigs]</b></span><a class="self-link" href="#spec-exec.complsigs"></a></h5>
   <ol>
    <li data-md>
     <p>The alias template <code class="highlight"><c- n>completion_signatures_of_t</c-></code> is used to obtain from a sender the list of completion signatures it may complete with.</p>
    <li data-md>
     <p><code class="highlight"><c- n>completion_signatures_of_t</c-></code> also recognizes awaitables as senders. For this clause ([exec]):</p>
     <ol>
      <li data-md>
       <p>An <i>awaitable</i> is an expression that would be well-formed as the operand of a <code class="highlight"><c- k>co_await</c-></code> expression within a given context.</p>
      <li data-md>
       <p>For any type <code class="highlight"><c- n>T</c-></code>, <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is <code class="highlight">true</code> if and only if an expression of that type is an awaitable as described above within the context of a coroutine whose promise type does not define a member <code class="highlight"><c- n>await_transform</c-></code>. For a coroutine promise type <code class="highlight"><c- n>P</c-></code>, <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> is <code class="highlight">true</code> if and only if an expression of that type is an awaitable as described above within the context of a coroutine whose promise type is <code class="highlight"><c- n>P</c-></code>.</p>
      <li data-md>
       <p>For an awaitable <code class="highlight"><c- n>a</c-></code> such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>a</c-><c- p>))</c-></code> is type <code class="highlight"><c- n>A</c-></code>, <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>A</c-><c- o>></c-></code> is an alias for <code class="highlight"><c- k>decltype</c-><c- p>(</c-><i><c- n>e</c-></i><c- p>)</c-></code>, where <code class="highlight"><i><c- n>e</c-></i></code> is <code class="highlight"><c- n>a</c-></code>'s <i>await-resume</i> expression ([expr.await]) within the context of a coroutine whose promise type does not define a member <code class="highlight"><c- n>await_transform</c-></code>. For a coroutine promise type <code class="highlight"><c- n>P</c-></code>, <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>A</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> is an alias for <code class="highlight"><c- k>decltype</c-><c- p>(</c-><i><c- n>e</c-></i><c- p>)</c-></code>, where <code class="highlight"><i><c- n>e</c-></i></code> is <code class="highlight"><c- n>a</c-></code>'s <i>await-resume</i> expression ([expr.await]) within the context of a coroutine whose promise type is <code class="highlight"><c- n>P</c-></code>.</p>
     </ol>
    <li data-md>
     <p>For types <code class="highlight"><c- n>S</c-></code> and <code class="highlight"><c- n>E</c-></code>, the type <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is an
alias for <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(),</c-> <c- n>declval</c-><c- o>&lt;</c-><c- n>E</c-><c- o>></c-><c- p>()))</c-></code> if that expression is well-formed.</p>
    <li data-md>
     <p>Given an execution environment type <code class="highlight"><c- n>Env</c-></code>, let <code class="highlight"><c- n>p</c-></code> be a non-<code class="highlight"><c- k>const</c-></code> lvalue
of type <code class="highlight"><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-></code>, where <code class="highlight"><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-></code> names a class type such that:</p>
     <ol>
      <li data-md>
       <p>For some subexpression <code class="highlight"><c- n>e</c-></code>, the expression <code class="highlight"><c- n>p</c-><c- p>.</c-><c- n>await_transform</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> is
expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>as_awaitable</c-><c- p>,</c-> <c- n>e</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> if that
expression is well-formed ([exec.as_awaitable]); otherwise, <code class="highlight"><c- n>e</c-></code>.</p>
      <li data-md>
       <p><code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>as_const</c-><c- p>(</c-><c- n>p</c-><c- p>)))</c-></code> names the type <code class="highlight"><c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-></code>.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_signatures</c-></code> is a customization point object. Let <code class="highlight"><c- n>s</c-></code> be an expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code> is <code class="highlight"><c- n>S</c-></code>, and let <code class="highlight"><c- n>e</c-></code> be an
expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code> is <code class="highlight"><c- n>E</c-></code>. Then <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-><c- p>{}</c-></code> if that expression is well-formed,</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>instance</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><c- n>Sigs</c-><c- p>,</c-> <c- n>completion_signatures</c-><c- o>></c-></code>, where <code class="highlight"><c- n>Sigs</c-></code> names the type <code class="highlight"><c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, if <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>::</c-><c- n>completion_signatures</c-></code> is well-formed
and names a type, then a value-initialized prvalue of type <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>::</c-><c- n>completion_signatures</c-></code>,</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>instance</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><c- n>Sigs</c-><c- p>,</c-> <c- n>completion_signatures</c-><c- o>></c-></code>, where <code class="highlight"><c- n>Sigs</c-></code> names the type <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>::</c-><c- n>completion_signatures</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, if <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>E</c-><c- o>>></c-></code> is <code class="highlight">true</code>, then</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>E</c-><c- o>>></c-></code> is <code class="highlight"><i><c- n>cv</c-></i> <c- b>void</c-></code> then a prvalue of a type equivalent to:</p>
<pre class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c->
  <c- n>set_value_t</c-><c- p>(),</c->
  <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
  <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c->
</pre>
        <li data-md>
         <p>Otherwise, a prvalue of a type equivalent to:</p>
<pre class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c->
  <c- n>set_value_t</c-><c- p>(</c-><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>E</c-><c- o>>></c-><c- p>),</c->
  <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
  <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c->
</pre>
       </ol>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>The exposition-only type <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> is
 defined as follows:</p>
     <ol>
      <li data-md>
       <p>If <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Ts</c-><c- p>)</c-></code> is greater than zero, <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> names the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>Us</c-><c- p>...</c-><c- o>></c-></code> where <code class="highlight"><c- n>Us</c-><c- p>...</c-></code> is the pack <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-></code> with duplicate types removed.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> names an implementation defined class type equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>empty</c-><c- o>-</c-><c- n>variant</c-></i> <c- p>{</c->
  <i><c- n>empty</c-><c- o>-</c-><c- n>variant</c-></i><c- p>()</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
<c- p>};</c->
</pre>
     </ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>r</c-></code> be an rvalue receiver of type <code class="highlight"><c- n>R</c-></code>, and let <code class="highlight"><c- n>S</c-></code> be the type of a
sender. If <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> is well
formed, it shall name the type <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;</c-><c- n>Args</c-><i><sub><c- n>0</c-></sub></i><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>Tuple</c-><c- o>&lt;</c-><c- n>Args</c-><i><sub><c- n>1</c-></sub></i><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- p>...,</c-> <c- n>Tuple</c-><c- o>&lt;</c-><c- n>Args</c-><i><sub><c- n>N</c-></sub></i><c- p>...</c-><c- o>>>></c-></code>, where the type packs <code class="highlight"><c- n>Args</c-><i><sub><c- n>0</c-></sub></i></code> through <code class="highlight"><c- n>Args</c-><i><sub><c- n>N</c-></sub></i></code> are the packs of types the sender <code class="highlight"><c- n>S</c-></code> passes as arguments to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> (besides the receiver object).
Such a sender <code class="highlight"><c- n>S</c-></code> shall not odr-use ([basic.def.odr]) <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, where <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>args</c-><c- p>)...</c-></code> is not one of the type packs <code class="highlight"><c- n>Args</c-><i><sub><c- n>0</c-></sub></i><c- p>...</c-></code> through <code class="highlight"><c- n>Args</c-><i><sub><c- n>N</c-></sub></i><c- p>...</c-></code> (ignoring differences in
rvalue-reference qualification).</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>r</c-></code> be an rvalue receiver of type <code class="highlight"><c- n>R</c-></code>, and let <code class="highlight"><c- n>S</c-></code> be the type of a
sender. If <code class="highlight"><c- n>error_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> is well formed, it
shall name the type <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>E</c-><i><sub><c- n>0</c-></sub></i><c- p>,</c-> <c- n>E</c-><i><sub><c- n>1</c-></sub></i><c- p>,</c-> <c- p>...,</c-> <c- n>E</c-><i><sub><c- n>N</c-></sub></i><c- o>></c-></code>, where the types <code class="highlight"><c- n>E</c-><i><sub><c- n>0</c-></sub></i></code> through <code class="highlight"><c- n>E</c-><i><sub><c- n>N</c-></sub></i></code> are the types the sender <code class="highlight"><c- n>S</c-></code> passes as arguments to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> (besides the receiver object). Such a sender <code class="highlight"><c- n>S</c-></code> shall not odr-use <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>, where <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> is not one of the types <code class="highlight"><c- n>E</c-><i><sub><c- n>0</c-></sub></i></code> through <code class="highlight"><c- n>E</c-><i><sub><c- n>N</c-></sub></i></code> (ignoring differences in rvalue-reference qualification).</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>r</c-></code> be an rvalue receiver of type <code class="highlight"><c- n>R</c-></code>, and let <code class="highlight"><c- n>S</c-></code> be the type of a
sender. If <code class="highlight"><c- n>sends_stopped</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-></code> is well formed and <code class="highlight">false</code>, such a sender <code class="highlight"><c- n>S</c-></code> shall not odr-use <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>[<i>Note</i>: The types <code class="highlight"><c- n>Args</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> and <code class="highlight"><c- n>E</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> captured in <code class="highlight"><c- n>value_types</c-></code> and <code class="highlight"><c- n>error_types</c-></code> can appear in any order.
 For example, a sender that can yield, in case of an error, either <code class="highlight"><c- n>exception_ptr</c-></code> or <code class="highlight"><c- n>error_code</c-></code> can have <code class="highlight"><c- n>error_types</c-></code> be either <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>exception_ptr</c-><c- p>,</c-> <c- n>error_code</c-><c- o>></c-></code> or <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>error_code</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>></c-></code>. --<i>end note</i>]</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.4" id="spec-execution.senders.connect"><span class="secno">11.8.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> <b>[exec.connect]</b></span><a class="self-link" href="#spec-execution.senders.connect"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> is used to <i>connect</i> a sender with a receiver, producing an operation state object that represents the work that needs to be performed to satisfy the receiver contract of the receiver with values that are the result of the operations described by the sender.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>r</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code> and <code class="highlight"><c- n>R</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>r</c-><c- p>))</c-></code>, and let <code class="highlight"><c- n>S</c->'</code> and <code class="highlight"><c- n>R</c->'</code> be the decayed types of <code class="highlight"><c- n>S</c-></code> and <code class="highlight"><c- n>R</c-></code>, respectively. If <code class="highlight"><c- n>R</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, if the constraints below are satisfied. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return an operation state for which <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> starts work described by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Constraints:</i></p>
<pre class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
<c- n>receiver_of</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>>></c-> <c- o>&amp;&amp;</c->
<c- n>tag_invocable</c-><c- o>&lt;</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>></c->
</pre>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>operation_state</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> if <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>></c-></code> is <code class="highlight">true</code> and that expression is valid, where <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> is a coroutine equivalent to the following:</p>
<pre class="highlight"><i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>S</c->' <c- n>s</c-><c- p>,</c-> <c- n>R</c->' <c- n>r</c-><c- p>)</c-> <c- k>requires</c-> <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i> <c- p>{</c->
  <c- n>exception_ptr</c-> <c- n>ep</c-><c- p>;</c->
  <c- k>try</c-> <c- p>{</c->
    <i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>expr</c-></i>
  <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>ep</c-> <c- o>=</c-> <c- n>current_exception</c-><c- p>();</c->
  <c- p>}</c->
  <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>expr</c-></i>
<c- p>}</c->
</pre>
       <p>where <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i></code> is the promise type of <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code>, and where <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> suspends at the <i>initial suspends point</i> ([dcl.fct.def.coroutine]), and:</p>
       <ol>
        <li data-md>
         <p><i>set-value-expr</i> first evaluates <code class="highlight"><c- k>co_await</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>, then suspends the coroutine and evaluates <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code> if <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>></c-></code> is <code class="highlight"><i><c- n>cv</c-></i> <c- b>void</c-></code>; otherwise, it evaluates <code class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>res</c-> <c- o>=</c-> <c- k>co_await</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>, then suspends the coroutine and evaluates <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>res</c-><c- p>)</c-><c- o>></c-><c- p>(</c-><c- n>res</c-><c- p>))</c-></code>.</p>
         <p>If the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> exits with an exception, the coroutine is resumed and the exception is immediately propagated in the context of the coroutine.</p>
         <p>[<i>Note</i>: If the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> exits normally, then the <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> coroutine is never resumed. --<i>end note</i>]</p>
        <li data-md>
         <p><i>set-error-expr</i> first suspends the coroutine and then executes <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>ep</c-><c- p>))</c-></code>.</p>
         <p>[<i>Note</i>: The <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> coroutine is never resumed after the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code>. --<i>end note</i>]</p>
        <li data-md>
         <p><code class="highlight"><i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i></code> is a type that models <code class="highlight"><c- n>operation_state</c-></code>. Its <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> resumes the <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> coroutine, advancing it past the initial suspend point.</p>
        <li data-md>
         <p>Let <code class="highlight"><c- n>p</c-></code> be an lvalue reference to the promise of the <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> coroutine, let <code class="highlight"><c- n>b</c-></code> be a <code class="highlight"><c- k>const</c-></code> lvalue reference to the receiver <code class="highlight"><c- n>r</c-></code>. Then <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>p</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>b</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>The expression <code class="highlight"><c- n>p</c-><c- p>.</c-><c- n>unhandled_stopped</c-><c- p>()</c-></code> is expression-equivalent to <code class="highlight"><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>)),</c-> <c- n>noop_coroutine</c-><c- p>())</c-></code>.</p>
        <li data-md>
         <p>For some expression <code class="highlight"><c- n>e</c-></code>, the expression <code class="highlight"><c- n>p</c-><c- p>.</c-><c- n>await_transform</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>as_awaitable</c-><c- p>,</c-> <c- n>e</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> if that expression is well-formed ([exec.as_awaitable]); otherwise, it is expression-equivalent to <code class="highlight"><c- n>e</c-></code>.</p>
       </ol>
       <p>Let <code class="highlight"><c- n>Res</c-></code> be <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>></c-></code>, and let <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> be an empty parameter pack if <code class="highlight"><c- n>Res</c-></code> is <code class="highlight"><i><c- n>cv</c-></i> <c- b>void</c-></code>, or a pack containing the single type <code class="highlight"><c- n>Res</c-></code> otherwise. The operand of the <i>requires-clause</i> of <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> is equivalent to <code class="highlight"><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>Sigs</c-><c- o>></c-></code> where <code class="highlight"><c- n>Sigs</c-></code> names the type:</p>
<pre class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c->
  <c- n>set_value_t</c-><c- p>(</c-><c- n>Vs</c-><c- p>...),</c->
  <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
  <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c->
</pre>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>Standard sender types shall always expose an rvalue-qualified overload of a customization of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>. Standard sender types shall only expose an lvalue-qualified overload of a customization of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> if they are copyable.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.5" id="spec-execution.senders.factories"><span class="secno">11.8.5. </span><span class="content">Sender factories <b>[exec.factories]</b></span><a class="self-link" href="#spec-execution.senders.factories"></a></h4>
   <h5 class="heading settled" data-level="11.8.5.1" id="spec-execution.senders.factories.general"><span class="secno">11.8.5.1. </span><span class="content">General <b>[exec.factories.general]</b></span><a class="self-link" href="#spec-execution.senders.factories.general"></a></h5>
   <ol>
    <li data-md>
     <p>Subclause [exec.factories] defines <i>sender factories</i>, which are utilities that return senders without accepting senders as arguments.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.5.2" id="spec-execution.senders.schedule"><span class="secno">11.8.5.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> <b>[exec.schedule]</b></span><a class="self-link" href="#spec-execution.senders.schedule"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> is used to obtain a sender associated with a scheduler, which can be used to describe work to be started on that scheduler’s associated execution context.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> denotes a customization point object. For some subexpression <code class="highlight"><c- n>s</c-></code>, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a sender whose <code class="highlight"><c- n>set_value</c-></code> completion scheduler is equivalent to <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.5.3" id="spec-execution.senders.just"><span class="secno">11.8.5.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> <b>[exec.just]</b></span><a class="self-link" href="#spec-execution.senders.just"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code> is used to create a sender that propagates a set of values to a connected receiver. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code> is used to create a sender that propagates an error to a connected receiver. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> is used to create a sender that propagates a stopped signal to a connected receiver.</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>just</c-><c- o>-</c-><c- n>sender</c-></code> be the class template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CPO</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>just</c-><c- o>-</c-><c- n>sender</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>completion_signatures</c-> <c- o>=</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>CPO</c-><c- p>(</c-><c- n>Ts</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

  <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-> <c- n>vs_</c-><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>R</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>operation_state</c-> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-> <c- n>vs_</c-><c- p>;</c-> <c- c1>// exposition only</c->
    <c- n>R</c-> <c- n>r_</c-><c- p>;</c-> <c- c1>// exposition only</c->

    <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>start_t</c-><c- p>,</c-> <c- n>operation_state</c-><c- o>&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- n>apply</c-><c- p>([</c-><c- o>&amp;</c-><c- n>s</c-><c- p>](</c-><c- n>Ts</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>values_</c-><c- p>)</c-> <c- p>{</c->
        <c- n>CPO</c-><c- p>{}(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>r_</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>values_</c-><c- p>)...);</c->
      <c- p>},</c-> <c- n>s</c-><c- p>.</c-><c- n>vs_</c-><c- p>);</c->
    <c- p>}</c->
  <c- p>};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>completion_signatures</c-><c- o>></c-> <c- n>R</c-><c- o>></c->
    <c- k>requires</c-> <c- p>(</c-><c- n>copy_constructible</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-> <c- o>&amp;&amp;</c-><c- p>...)</c->
  <c- k>friend</c-> <c- n>operation_state</c-><c- o>&lt;</c-><c- n>decay_t</c-><r><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>connect_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>R</c-> <c- o>&amp;&amp;</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{</c-> <c- n>s</c-><c- p>.</c-><c- n>vs_</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- p>)</c-> <c- p>};</c->
  <c- p>}</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>completion_signatures</c-><c- o>></c-> <c- n>R</c-><c- o>></c->
  <c- k>friend</c-> <c- n>operation_state</c-><c- o>&lt;</c-><c- n>decay_t</c-><r><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>connect_t</c-><c- p>,</c-> <i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>R</c-> <c- o>&amp;&amp;</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>vs_</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- p>)</c-> <c- p>};</c->
  <c- p>}</c->

  <c- k>friend</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_attrs_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{};</c->
  <c- p>}</c->
<c- p>};</c->
</r></r></pre>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>vs</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>vs</c-><c- p>))...</c-></code>. If any type <code class="highlight"><c- n>V</c-></code> in <code class="highlight"><c- n>Vs</c-></code> does not satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>vs</c-><c- p>...)</c-></code> is ill-formed.
Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>vs</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-><c- p>(</c-><c- n>vs</c-><c- p>...)</c-></code>.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code> denotes a customization point object. For some subexpression <code class="highlight"><c- n>err</c-></code>, let <code class="highlight"><c- n>Err</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>err</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Err</c-></code> does not satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code> is ill-formed.
Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>>></c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Then name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> denotes a customization point object. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- o>></c-><c- p>()</c-></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.5.4" id="spec-execution.senders.transfer_just"><span class="secno">11.8.5.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code> <b>[exec.transfer_just]</b></span><a class="self-link" href="#spec-execution.senders.transfer_just"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code> is used to create a sender that propagates a set of values to a connected receiver on an execution agent belonging to the associated execution context of a specified scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>vs</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>vs</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, or any type <code class="highlight"><c- n>V</c-></code> in <code class="highlight"><c- n>Vs</c-></code> does not
satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code>, if that expression is
valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a sender
whose <code class="highlight"><c- n>set_value</c-></code> completion scheduler is equivalent to <code class="highlight"><c- n>s</c-></code> and sends
values equivalent to <code class="highlight"><c- k>auto</c-><c- p>(</c-><c- n>vs</c-><c- p>)...</c-></code> to a receiver connected to it, the
behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_just</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>vs</c-><c- p>))...)</c-><c- o>></c-></code>, where <code class="highlight"><c- n>R</c-></code> is the type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>vs</c-><c- p>...),</c-> <c- n>s</c-><c- p>)</c-></code>.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.5.5" id="spec-execution.senders.read"><span class="secno">11.8.5.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> <b>[exec.read]</b></span><a class="self-link" href="#spec-execution.senders.read"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> is used to create a sender that retrieves a value from the receiver’s associated environment and sends it back to the receiver through the value channel.</p>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> is a customization point object of an unspecified class type equivalent to:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>read</c-><c- o>-</c-><c- n>sender</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>struct</c-> <i><c- nc>read</c-><c- o>-</c-><c- n>t</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
    <i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-> <c- k>operator</c-><c- p>()(</c-><c- n>Tag</c-><c- p>)</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- p>{};</c-> <c- p>}</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p><code class="highlight"><i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i></code> is an exposition only class template equivalent to:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>read</c-><c- o>-</c-><c- n>sender</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>R</c-><c- o>></c->
      <c- k>struct</c-> <i><c- nc>operation</c-><c- o>-</c-><c- n>state</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
        <c- n>R</c-> <c- n>r_</c-><c- p>;</c-> <c- c1>// exposition only</c->

        <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>start_t</c-><c- p>,</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-></i><c- o>&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
          <i><c- n>TRY</c-><c- o>-</c-><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>r_</c-><c- p>),</c-> <c- k>auto</c-><c- p>(</c-><c- n>Tag</c-><c- p>{}(</c-><c- n>get_env</c-><c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>r_</c-><c- p>))));</c->
        <c- p>}</c->
      <c- p>};</c->

    <c- k>template</c-><c- o>&lt;</c-><c- n>receiver</c-> <c- n>R</c-><c- o>></c->
    <c- k>friend</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>connect_t</c-><c- p>,</c-> <i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i><c- p>,</c-> <c- n>R</c-> <c- o>&amp;&amp;</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
      <c- k>return</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- p>)</c-> <c- p>};</c->
    <c- p>}</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Env</c-><c- o>></c->
        <c- k>requires</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
      <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
        <c- o>-></c-> <c- n>completion_signatures</c-><c- o>&lt;</c->
          <c- n>set_value_t</c-><c- p>(</c-><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>),</c-> <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// not defined</c-></i>

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Env</c-><c- o>></c->
        <c- k>requires</c-> <i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
      <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
        <c- o>-></c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>)</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// not defined</c-></i>

    <c- k>friend</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_attrs_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>read</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- k>return</c-> <c- p>{};</c->
    <c- p>}</c->
  <c- p>};</c->
</pre>
     <p>where <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>, for two subexpressions <code class="highlight"><c- n>r</c-></code> and <code class="highlight"><c- n>e</c-></code>,
is equivalent to:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>);</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
</pre>
     <p>if <code class="highlight"><c- n>e</c-></code> is potentially throwing; or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> otherwise.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.6" id="spec-execution.senders.adapt"><span class="secno">11.8.6. </span><span class="content">Sender adaptors <b>[exec.adapt]</b></span><a class="self-link" href="#spec-execution.senders.adapt"></a></h4>
   <h5 class="heading settled" data-level="11.8.6.1" id="spec-execution.senders.adapt.general"><span class="secno">11.8.6.1. </span><span class="content">General <b>[exec.adapt.general]</b></span><a class="self-link" href="#spec-execution.senders.adapt.general"></a></h5>
   <ol>
    <li data-md>
     <p>Subclause [exec.adapt] defines <i>sender adaptors</i>, which are utilities that transform one or more senders into a sender with custom behaviors. When they accept a single sender argument, they can be chained to create sender chains.</p>
    <li data-md>
     <p>The bitwise OR operator is overloaded for the purpose of creating sender chains. The adaptors also support function call syntax with equivalent semantics.</p>
    <li data-md>
     <p>Unless otherwise specified, a sender adaptor is required to not begin executing any functions which would observe or modify any of the arguments of the adaptor before the returned sender is connected with a receiver using <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on the resulting operation state. This requirement applies to any function that is selected by the implementation of the sender adaptor.</p>
    <li data-md>
     <p>Unless otherwise specified, all sender adaptors that accept a single <code class="highlight"><c- n>sender</c-></code> argument return sender objects that delegate <code class="highlight"><c- n>get_attrs</c-></code> to that single sender argument. Unless otherwise specified, all sender adaptors that accept more than one <code class="highlight"><c- n>sender</c-></code> argument return sender objects that return <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i></code> from <code class="highlight"><c- n>get_attrs</c-></code>. These requirements apply to any function that is selected by the implementation of the
sender adaptor.</p>
    <li data-md>
     <p>Unless otherwise specified, whenever a sender adaptor constructs a receiver that it passes to another sender’s connect, that receiver shall delegate <code class="highlight"><c- n>get_env</c-></code> to a receiver accepted as an argument of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>. This requirements
applies to any sender returned from a function that is selected by the implementation of such sender adaptor.</p>
    <li data-md>
     <p>For any sender type, receiver type, operation state type, execution environment type, or coroutine promise type that is part of the implementation of any sender adaptor in this subclause and that is a class template, the template arguments do not contribute to the associated entities ([basic.lookup.argdep]) of a function call where a specialization of the class template is an associated entity.</p>
     <p>[<em>Example:</em></p>
<pre class="highlight"><c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptors</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sch</c-><c- p>,</c-> <c- k>class</c-> <c- nc>S</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>class</c-> <i><c- nc>on</c-><c- o>-</c-><c- n>sender</c-></i> <c- p>{</c->
    <c- c1>// ...</c->
  <c- p>};</c->

  <c- k>struct</c-> <c- nc>on_t</c-> <c- p>{</c->
    <c- k>template</c-> <c- o>&lt;</c-><c- n>scheduler</c-> <c- n>Sch</c-><c- p>,</c-> <c- n>sender</c-> <c- n>S</c-><c- o>></c->
    <i><c- n>on</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Sch</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-> <c- k>operator</c-><c- p>()(</c-><c- n>Sch</c-><c- o>&amp;&amp;</c-> <c- n>sch</c-><c- p>,</c-> <c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
      <c- c1>// ...</c->
    <c- p>}</c->
  <c- p>};</c->
<c- p>}</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>on_t</c-> <c- n>on</c-><c- p>{};</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>If the specification of a sender adaptor requires that the implementation of the <code class="highlight"><c- n>get_completion_signatures</c-></code> customization point adds the signature <code class="highlight"><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-></code> as an additional signature, but a customization of that sender adaptor never
calls the <code class="highlight"><c- n>exception_ptr</c-></code> overload of <code class="highlight"><c- n>set_error</c-></code>, that customization is allowed to omit the <code class="highlight"><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-></code> additional signature from its implementation of the <code class="highlight"><c- n>get_completion_signatures</c-></code> sender query.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.2" id="spec-execution.senders.adaptor.objects"><span class="secno">11.8.6.2. </span><span class="content">Sender adaptor closure objects <b>[exec.adapt.objects]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.objects"></a></h5>
   <ol>
    <li data-md>
     <p>A <i>pipeable sender adaptor closure object</i> is a function object that accepts one or more <code class="highlight"><c- n>sender</c-></code> arguments and returns a <code class="highlight"><c- n>sender</c-></code>. For a sender adaptor closure object <code class="highlight"><c- n>C</c-></code> and an expression <code class="highlight"><c- n>S</c-></code> such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>S</c-><c- p>))</c-></code> models <code class="highlight"><c- n>sender</c-></code>, the following
expressions are equivalent and yield a <code class="highlight"><c- n>sender</c-></code>:</p>
<pre class="highlight"><c- n>C</c-><c- p>(</c-><c- n>S</c-><c- p>)</c->
<c- n>S</c-> <c- o>|</c-> <c- n>C</c->
</pre>
     <p>Given an additional pipeable sender adaptor closure object <code class="highlight"><c- n>D</c-></code>, the expression <code class="highlight"><c- n>C</c-> <c- o>|</c-> <c- n>D</c-></code> produces another pipeable sender adaptor closure object <code class="highlight"><c- n>E</c-></code>:</p>
     <p><code class="highlight"><c- n>E</c-></code> is a perfect forwarding call wrapper ([func.require]) with the following properties:</p>
     <ul>
      <li data-md>
       <p>Its target object is an object <code class="highlight"><c- n>d</c-></code> of type <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>D</c-><c- p>))</c-><c- o>></c-></code> direct-non-list-initialized with <code class="highlight"><c- n>D</c-></code>.</p>
      <li data-md>
       <p>It has one bound argument entity, an object <code class="highlight"><c- n>c</c-></code> of type <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>C</c-><c- p>))</c-><c- o>></c-></code> direct-non-list-initialized with <code class="highlight"><c- n>C</c-></code>.</p>
      <li data-md>
       <p>Its call pattern is <code class="highlight"><c- n>d</c-><c- p>(</c-><c- n>c</c-><c- p>(</c-><c- n>arg</c-><c- p>))</c-></code>, where <code class="highlight"><c- n>arg</c-></code> is the argument used in a function call expression of <code class="highlight"><c- n>E</c-></code>.</p>
     </ul>
     <p>The expression <code class="highlight"><c- n>C</c-> <c- o>|</c-> <c- n>D</c-></code> is well-formed if and only if the initializations of the state entities of <code class="highlight"><c- n>E</c-></code> are all well-formed.</p>
    <li data-md>
     <p>An object <code class="highlight"><c- n>t</c-></code> of type <code class="highlight"><c- n>T</c-></code> is a pipeable sender adaptor closure object if <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, <code class="highlight"><c- n>T</c-></code> has no other base
classes of type <code class="highlight"><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code> for any other type <code class="highlight"><c- n>U</c-></code>, and <code class="highlight"><c- n>T</c-></code> does not model <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p>The template parameter <code class="highlight"><c- n>D</c-></code> for <code class="highlight"><c- n>sender_adaptor_closure</c-></code> may be an incomplete type. Before any expression of type <code class="highlight"><i><c- n>cv</c-></i> <c- n>D</c-></code> appears as
an operand to the <code class="highlight"><c- o>|</c-></code> operator, <code class="highlight"><c- n>D</c-></code> shall be complete and model <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>D</c-><c- o>>></c-></code>. The behavior of an expression involving an
object of type <code class="highlight"><i><c- n>cv</c-></i> <c- n>D</c-></code> as an operand to the <code class="highlight"><c- o>|</c-></code> operator is undefined if overload resolution selects a program-defined <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> function.</p>
    <li data-md>
     <p>A <i>pipeable sender adaptor object</i> is a customization point object that accepts a <code class="highlight"><c- n>sender</c-></code> as its first argument and returns a <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p>If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object.</p>
    <li data-md>
     <p>If a pipeable sender adaptor object <code class="highlight"><c- n>adaptor</c-></code> accepts more than one argument, then let <code class="highlight"><c- n>s</c-></code> be an expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code> models <code class="highlight"><c- n>sender</c-></code>,
let <code class="highlight"><c- n>args</c-><c- p>...</c-></code> be arguments such that <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is a well-formed expression as specified in the rest of this subclause
([exec.adapt.objects]), and let <code class="highlight"><c- n>BoundArgs</c-></code> be a pack that denotes <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>args</c-><c- p>))</c-><c- o>></c-><c- p>...</c-></code>. The expression <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>args</c-><c- p>...)</c-></code> produces a pipeable sender adaptor closure object <code class="highlight"><c- n>f</c-></code> that is a perfect forwarding call wrapper with the following properties:</p>
     <ul>
      <li data-md>
       <p>Its target object is a copy of <code class="highlight"><c- n>adaptor</c-></code>.</p>
      <li data-md>
       <p>Its bound argument entities <code class="highlight"><c- n>bound_args</c-></code> consist of objects of types <code class="highlight"><c- n>BoundArgs</c-><c- p>...</c-></code> direct-non-list-initialized with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>args</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...</c-></code>, respectively.</p>
      <li data-md>
       <p>Its call pattern is <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>bound_args</c-><c- p>...)</c-></code>, where <code class="highlight"><c- n>r</c-></code> is the argument used in a function call expression of <code class="highlight"><c- n>f</c-></code>.</p>
     </ul>
     <p>The expression <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>args</c-><c- p>...)</c-></code> is well-formed if and only if the initializations of the bound argument entities of the result, as specified above,
 are all well-formed.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.3" id="spec-execution.senders.adapt.on"><span class="secno">11.8.6.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> <b>[exec.on]</b></span><a class="self-link" href="#spec-execution.senders.adapt.on"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> is used to adapt a sender into a sender that will start the input sender on an execution agent belonging to a specific execution context.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>replace</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> be an expression denoting an object <code class="highlight"><c- n>e</c->'</code> such that <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> returns a copy of <code class="highlight"><c- n>sch</c-></code>, and <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <c- n>e</c->'<c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag</c-><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> for all arguments <code class="highlight"><c- n>args</c-><c- p>...</c-></code> and for all <code class="highlight"><c- n>tag</c-></code> whose type satisfies <code class="highlight"><i><c- n>forwarding</c-><c- o>-</c-><c- n>query</c-></i></code> and is not <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler_t</c-></code>.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, or <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>on</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid. If the function selected above does not return a sender which starts <code class="highlight"><c- n>s</c-></code> on an execution agent of the associated execution context of <code class="highlight"><c- n>sch</c-></code> when
started, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s1</c-></code>. When <code class="highlight"><c- n>s1</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is called, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r2</c-><c- p>)</c-></code>, where <code class="highlight"><c- n>r2</c-></code> is as specified below, which results in <code class="highlight"><c- n>op_state3</c-></code>. It calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state3</c-><c- p>)</c-></code>. If any of these throws an exception, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> on <code class="highlight"><c- n>out_r</c-></code>, passing <code class="highlight"><c- n>current_exception</c-><c- p>()</c-></code> as the second argument.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code>, which results in <code class="highlight"><c- n>s2</c-></code>. It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s2</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in <code class="highlight"><c- n>op_state2</c-></code>.</p>
        <li data-md>
         <p><code class="highlight"><c- n>op_state2</c-></code> is wrapped by a new operation state, <code class="highlight"><c- n>op_state1</c-></code>, that is returned to the caller.</p>
        <li data-md>
         <p><code class="highlight"><c- n>r2</c-></code> is a receiver that wraps a reference to <code class="highlight"><c- n>out_r</c-></code> and forwards all
receiver completion-signals to it. In addition, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>r2</c-><c- p>)</c-></code> returns <code class="highlight"><i><c- n>replace</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on <code class="highlight"><c- n>op_state1</c-></code>, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> on <code class="highlight"><c- n>op_state2</c-></code>.</p>
        <li data-md>
         <p>The lifetime of <code class="highlight"><c- n>op_state2</c-></code>, once constructed, lasts until either <code class="highlight"><c- n>op_state3</c-></code> is constructed or <code class="highlight"><c- n>op_state1</c-></code> is destroyed, whichever comes first. The lifetime of <code class="highlight"><c- n>op_state3</c-></code>, once constructed, lasts until <code class="highlight"><c- n>op_state1</c-></code> is destroyed.</p>
       </ol>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s1</c-></code> and <code class="highlight"><c- n>e</c-></code>, where <code class="highlight"><c- n>s1</c-></code> is a sender returned from <code class="highlight"><c- n>on</c-></code> or a copy of such, let <code class="highlight"><c- n>S1</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s1</c-><c- p>))</c-></code>.
Let <code class="highlight"><c- n>E</c->'</code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><i><c- n>replace</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>sch</c-><c- p>)))</c-></code>.
Then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s1</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S1</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c->
  <c- n>E</c->'<c- p>,</c->
  <c- n>make_completion_signatures</c-><c- o>&lt;</c->
    <c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>,</c->
    <c- n>E</c-><c- p>,</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
    <i><c- n>no</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i><c- o>>></c-><c- p>;</c->
</pre>
       <p>where <code class="highlight"><i><c- n>no</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code> for any set of types <code class="highlight"><c- n>As</c-><c- p>...</c-></code>.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.4" id="spec-execution.senders.adapt.transfer"><span class="secno">11.8.6.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> <b>[exec.transfer]</b></span><a class="self-link" href="#spec-execution.senders.adapt.transfer"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> is used to adapt a sender into a sender with a different associated <code class="highlight"><c- n>set_value</c-></code> completion scheduler. [<i>Note</i>: it results in a transition between different execution contexts when executed. --<i>end note</i>]</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, or <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>.</p>
     </ol>
     <p>If the function selected above does not return a sender which is a result of
a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s2</c-><c- p>)</c-></code>, where <code class="highlight"><c- n>s2</c-></code> is a sender which
sends values equivalent to those sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> is undefined.</p>
    <li data-md>
     <p>For a sender <code class="highlight"><c- n>t</c-></code> returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> shall
return a queryable object <code class="highlight"><c- n>q</c-></code> such that <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> returns
a copy of <code class="highlight"><c- n>sch</c-></code>, where <code class="highlight"><c- n>CPO</c-></code> is either <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>. The <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- o>></c-></code> query is not implemented, as the scheduler
cannot be guaranteed in case an error is thrown while trying to schedule work on
the given scheduler object. For all other query objects <code class="highlight"><i><c- n>Q</c-></i></code> whose type satisfies <code class="highlight"><c- n>forwarding_query</c-></code>, the expression <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> shall be equivalent to <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.5" id="spec-execution.senders.adaptors.schedule_from"><span class="secno">11.8.6.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> <b>[exec.schedule_from]</b></span><a class="self-link" href="#spec-execution.senders.adaptors.schedule_from"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> is used to schedule work dependent on the completion of a sender onto a scheduler’s associated execution context. [<i>Note</i>: <code class="highlight"><c- n>schedule_from</c-></code> is not meant to be used in user code; it is used in the implementation of <code class="highlight"><c- n>transfer</c-></code>. -<i>end note</i>]</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code>, or <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a sender which completes on an execution agent belonging to the associated
execution context of <code class="highlight"><c- n>sch</c-></code> and sends signals equivalent to those sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that when a receiver completion-signal <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, it decay-copies <code class="highlight"><c- n>args</c-><c- p>...</c-></code> into <code class="highlight"><c- n>op_state</c-></code> (see below) as <code class="highlight"><c- n>args</c->'<c- p>...</c-></code> and constructs a receiver <code class="highlight"><c- n>r2</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r2</c-><c- p>)</c-></code> is called, it calls <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>args</c->'<c- p>)...)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r2</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
         </ol>
         <p>It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code>, resulting in a sender <code class="highlight"><c- n>s3</c-></code>. It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s3</c-><c- p>,</c-> <c- n>r2</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state3</c-></code>. It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state3</c-><c- p>)</c-></code>. If any of these throws an exception,
it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>. If any of these expressions would be ill-formed, then <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is ill-formed.</p>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> resulting in an operation state <code class="highlight"><c- n>op_state2</c-></code>. If this expression would be ill-formed, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s2</c-><c- p>,</c-> <c- n>out_r</c-><c- p>)</c-></code> is ill-formed.</p>
        <li data-md>
         <p>Returns an operation state <code class="highlight"><c- n>op_state</c-></code> that contains <code class="highlight"><c- n>op_state2</c-></code>. When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code>. The lifetime of <code class="highlight"><c- n>op_state3</c-></code> ends when <code class="highlight"><c- n>op_state</c-></code> is destroyed.</p>
       </ol>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code>, where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>schedule_from</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. Then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c->
  <c- n>E</c-><c- p>,</c->
  <c- n>make_completion_signatures</c-><c- o>&lt;</c->
    <c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>,</c->
    <c- n>E</c-><c- p>,</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
    <i><c- n>no</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i><c- o>>></c-><c- p>;</c->
</pre>
       <p>where <code class="highlight"><i><c- n>no</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code> for any set of types <code class="highlight"><c- n>As</c-><c- p>...</c-></code>.</p>
     </ol>
    <li data-md>
     <p>For a sender <code class="highlight"><c- n>t</c-></code> returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> shall
return a queryable object <code class="highlight"><c- n>q</c-></code> such that <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> returns
a copy of <code class="highlight"><c- n>sch</c-></code>, where <code class="highlight"><c- n>CPO</c-></code> is either <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>. The <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- o>></c-></code> query is not implemented, as the scheduler
cannot be guaranteed in case an error is thrown while trying to schedule work on
the given scheduler object. For all other query objects <code class="highlight"><i><c- n>Q</c-></i></code> whose type satisfies <code class="highlight"><c- n>forwarding_query</c-></code>, the expression <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> shall be equivalent to <code class="highlight"><i><c- n>Q</c-></i><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.6" id="spec-execution.senders.adaptor.then"><span class="secno">11.8.6.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> <b>[exec.then]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.then"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> is used to attach an invocable as a continuation for the successful completion of the input sender.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> denotes a customization point object. For some
subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>F</c-></code> be the
decayed type of <code class="highlight"><c- n>f</c-></code>, and let <code class="highlight"><c- n>f</c->'</code> be an xvalue refering to an object
decay-copied from <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, or <code class="highlight"><c- n>F</c-></code> does not model <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> is
ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, let <code class="highlight"><c- n>v</c-></code> be the
expression <code class="highlight"><c- n>invoke</c-><c- p>(</c-><c- n>f</c->'<c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>. If <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>v</c-><c- p>)</c-></code> is <code class="highlight"><c- b>void</c-></code>,
calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>; otherwise, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>v</c-><c- p>)</c-></code>. If any of these throw an
exception, it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>. If any of these expressions would be
ill-formed, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is
ill-formed.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Returns an expression equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>Let <code class="highlight"><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code> name the type <code class="highlight"><c- n>Tag</c-><c- p>()</c-></code> if <code class="highlight"><c- n>Args</c-><c- p>...</c-></code> is a template paramter pack containing the
single type <code class="highlight"><c- b>void</c-></code>; otherwise, <code class="highlight"><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-></code>. Given
subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>then</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent
to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i><c- p>,</c->
    <i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i><c- o>></c-><c- p>;</c->
</pre>
         <p>where <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i></code> is an alias for:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>completions</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>As</c-><c- p>...</c-><c- o>>>></c->
</pre>
         <p>and <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i></code> is an alias for <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-></code> if any of the types
in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code> are <code class="highlight"><c- n>true_type</c-></code>; otherwise, <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code>, where <code class="highlight"><i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i></code> is the template alias:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i> <c- o>=</c->
    <c- n>bool_constant</c-><c- o>&lt;!</c-><c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>As</c-><c- p>...</c-><c- o>>></c-><c- p>;</c->
</pre>
       </ol>
     </ol>
     <p>If the function selected above does not return a sender that invokes <code class="highlight"><c- n>f</c-></code> with the result of the <code class="highlight"><c- n>set_value</c-></code> signal of <code class="highlight"><c- n>s</c-></code>, passing the return value as the value to any connected receivers, and propagates the other completion-signals sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.7" id="spec-execution.senders.adaptor.upon_error"><span class="secno">11.8.6.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code> <b>[exec.upon_error]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.upon_error"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code> is used to attach an invocable as a continuation for the unsuccessful completion of the input sender.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code> denotes a customization point object. For
some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>F</c-></code> be the
decayed type of <code class="highlight"><c- n>f</c-></code>, and let <code class="highlight"><c- n>f</c->'</code> be an xvalue refering to an object
decay-copied from <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, or <code class="highlight"><c- n>F</c-></code> does not model <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code> is
ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is called, let <code class="highlight"><c- n>v</c-></code> be the
expression <code class="highlight"><c- n>invoke</c-><c- p>(</c-><c- n>f</c->'<c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>. If <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>v</c-><c- p>)</c-></code> is <code class="highlight"><c- b>void</c-></code>, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>; otherwise, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>v</c-><c- p>)</c-></code>. If any of these throw an
exception, it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>. If any of these expressions would be
ill-formed, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is
ill-formed.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Returns an expression equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>Let <code class="highlight"><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code> name the type <code class="highlight"><c- n>Tag</c-><c- p>()</c-></code> if <code class="highlight"><c- n>Args</c-><c- p>...</c-></code> is a template paramter pack containing the
single type <code class="highlight"><c- b>void</c-></code>; otherwise, <code class="highlight"><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-></code>. Given
subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>upon_error</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent
to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i><c- p>,</c->
    <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i><c- p>,</c-> <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>completion</c-></i><c- o>></c-><c- p>;</c->
</pre>
         <p>where <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>completion</c-></i></code> is the template alias:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>completion</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>E</c-><c- o>>>></c->
</pre>
         <p>and <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i></code> is an alias for <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-></code> if any of the types
in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><c- n>error_types_of_t</c-><c- o>&lt;</c-><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i><c- o>></c-></code> are <code class="highlight"><c- n>true_type</c-></code>; otherwise, <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code>, where <code class="highlight"><i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i></code> is the template alias:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Es</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>potentially</c-><c- o>-</c-><c- n>throwing</c-></i> <c- o>=</c->
    <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;!</c-><c- n>bool_constant</c-><c- o>&lt;</c-><c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>Es</c-><c- o>>></c-><c- p>...</c-><c- o>></c-><c- p>;</c->
</pre>
       </ol>
     </ol>
     <p>If the function selected above does not return a sender which invokes <code class="highlight"><c- n>f</c-></code> with the result of the <code class="highlight"><c- n>set_error</c-></code> signal of <code class="highlight"><c- n>s</c-></code>, passing the return value as the value to any connected receivers, and propagates the other completion-signals sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.8" id="spec-execution.senders.adaptor.upon_stopped"><span class="secno">11.8.6.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> <b>[exec.upon_stopped]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.upon_stopped"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> is used to attach an invocable as a continuation for the completion of the input sender using the "stopped" channel.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> denotes a customization point object. For
some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>F</c-></code> be the
decayed type of <code class="highlight"><c- n>f</c-></code>, and let <code class="highlight"><c- n>f</c->'</code> be an xvalue refering to an object
decay-copied from <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, or <code class="highlight"><c- n>F</c-></code> does not model both <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code> and <code class="highlight"><c- n>invocable</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol start="2">
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
          <li data-md>
           <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is called, let <code class="highlight"><c- n>v</c-></code> be the
expression <code class="highlight"><c- n>invoke</c-><c- p>(</c-><c- n>f</c->'<c- p>)</c-></code>. If <code class="highlight"><c- n>v</c-></code> has type <code class="highlight"><c- b>void</c-></code>, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>; otherwise, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>v</c-><c- p>)</c-></code>. If any of these throw an
exception, it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>. If any of these expressions would be
ill-formed, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is
ill-formed.</p>
         </ol>
        <li data-md>
         <p>Returns an expression equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>Let <code class="highlight"><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code> name the type <code class="highlight"><c- n>Tag</c-><c- p>()</c-></code> if <code class="highlight"><c- n>Args</c-><c- p>...</c-></code> is a template paramter pack containing the
single type <code class="highlight"><c- b>void</c-></code>; otherwise, <code class="highlight"><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-></code>. Given
subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>upon_stopped</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent
to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i><c- p>,</c->
    <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i><c- p>,</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i><c- p>,</c-> <i><c- n>set</c-><c- o>-</c-><c- n>stopped</c-><c- o>-</c-><c- n>completions</c-></i><c- o>></c-><c- p>;</c->
</pre>
         <p>where <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>stopped</c-><c- o>-</c-><c- n>completions</c-></i></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- n>compl</c-><c- o>-</c-><c- n>sig</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>>></c-></code>, and <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>error</c-><c- o>-</c-><c- n>signature</c-></i></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-></code> if <code class="highlight"><c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-></code> is <code class="highlight">true</code>, or <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code> otherwise.</p>
       </ol>
     </ol>
     <p>If the function selected above does not return a sender which invokes <code class="highlight"><c- n>f</c-></code> when <code class="highlight"><c- n>s</c-></code> completes by calling <code class="highlight"><c- n>set_stopped</c-></code>, passing the return value as the value to any connected receivers, and propagates the other completion-signals sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.9" id="spec-execution.senders.adapt.let"><span class="secno">11.8.6.9. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <b>[exec.let]</b></span><a class="self-link" href="#spec-execution.senders.adapt.let"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code> is used to insert continuations creating more work dependent on the results of their input senders into a sender chain. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code> is used to insert continuations creating more work dependent on the error of its input senders into a sender chain. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code> is used to insert continuations creating more work dependent on the stopped signal of its input senders into a sender chain.</p>
    <li data-md>
     <p>The names <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code> denote a customization point object.
Let the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i></code> be one of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>.
For some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>F</c-></code> be the decayed type of <code class="highlight"><c- n>f</c-></code>, and let <code class="highlight"><c- n>f</c->'</code> be an xvalue that refers to an object decay-copied from <code class="highlight"><c- n>f</c-></code>.
If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed.
If <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><c- n>invocable</c-></code>, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed.
Otherwise, the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, given a receiver <code class="highlight"><c- n>out_r</c-></code> and an lvalue <code class="highlight"><c- n>out_r</c->'</code> refering to an object decay-copied from <code class="highlight"><c- n>out_r</c-></code>.</p>
       <ol>
        <li data-md>
         <p>For <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, let <code class="highlight"><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></code> be <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code>.
For <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, let <code class="highlight"><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></code> be <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code>.
For <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, let <code class="highlight"><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></code> be <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>.
Let <code class="highlight"><i><c- n>signal</c-></i></code> be one of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code>, or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>.</p>
        <li data-md>
         <p>Let <code class="highlight"><c- n>r</c-></code> be an rvalue of a receiver type <code class="highlight"><c- n>R</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, the receiver <code class="highlight"><c- n>r</c-></code> decay-copies <code class="highlight"><c- n>args</c-><c- p>...</c-></code> into <code class="highlight"><c- n>op_state2</c-></code> as <code class="highlight"><c- n>args</c->'<c- p>...</c-></code>, then calls <code class="highlight"><c- n>invoke</c-><c- p>(</c-><c- n>f</c->'<c- p>,</c-> <c- n>args</c->'<c- p>...)</c-></code>, resulting in a sender <code class="highlight"><c- n>s3</c-></code>.
It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s3</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>out_r</c->'<c- p>))</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state3</c-></code>. <code class="highlight"><c- n>op_state3</c-></code> is saved as a part of <code class="highlight"><c- n>op_state2</c-></code>.
It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state3</c-><c- p>)</c-></code>.
If any of these throws an exception, it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>out_r</c->'<c- p>),</c-> <c- n>current_exception</c-><c- p>())</c-></code>.
If any of these expressions would be ill-formed, <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is ill-formed.</p>
          <li data-md>
           <p><code class="highlight"><i><c- n>signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>signal</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>out_r</c->'<c- p>),</c-> <c- n>args</c-><c- p>...)</c-></code>, when <code class="highlight"><i><c- n>signal</c-></i></code> is different from <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code>.</p>
         </ol>
        <li data-md>
         <p><code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> returns a sender <code class="highlight"><c- n>s2</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>If the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code> is ill-formed, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s2</c-><c- p>,</c-> <c- n>out_r</c-><c- p>)</c-></code> is ill-formed.</p>
          <li data-md>
           <p>Otherwise, let <code class="highlight"><c- n>op_state2</c-></code> be the result of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s2</c-><c- p>,</c-> <c- n>out_r</c-><c- p>)</c-></code> returns an operation state <code class="highlight"><c- n>op_state</c-></code> that stores <code class="highlight"><c- n>op_state2</c-></code>. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code>, where <code class="highlight"><c- n>s2</c-></code> is a sender returned
from <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>, and let <code class="highlight"><c- n>S</c->'</code> be <code class="highlight"><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-></code>. Then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is specified as
follows:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c->'<c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is <code class="highlight">false</code>, the expression <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is ill-formed.</p>
          <li data-md>
           <p>Otherwise, let <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> be the set of template arguments of the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c->'<c- p>,</c-> <c- n>E</c-><c- o>></c-></code>,
let <code class="highlight"><c- n>Sigs2</c-><c- p>...</c-></code> be the set of function types in <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> whose return type
is <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code>, and let <code class="highlight"><c- n>Rest</c-><c- p>...</c-></code> be the set of function types
in <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> but not <code class="highlight"><c- n>Sigs2</c-><c- p>...</c-></code>.</p>
          <li data-md>
           <p>For each <code class="highlight"><c- n>Sig2</c-><i><sub><c- n>i</c-></sub></i></code> in <code class="highlight"><c- n>Sigs2</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>Vs</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be the set of function
arguments in <code class="highlight"><c- n>Sig2</c-><i><sub><c- n>i</c-></sub></i></code> and let <code class="highlight"><c- n>S3</c-><i><sub><c- n>i</c-></sub></i></code> be <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Vs</c-><i><sub><c- n>i</c-></sub></i><c- o>>&amp;</c-><c- p>...</c-><c- o>></c-></code>. If <code class="highlight"><c- n>S3</c-><i><sub><c- n>i</c-></sub></i></code> is ill-formed, or if <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S3</c-><i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is not satisfied,
then the expression <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is ill-formed.</p>
          <li data-md>
           <p>Otherwise, let <code class="highlight"><c- n>Sigs3</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be the
set of template arguments of the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S3</c-><i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>E</c-><c- o>></c-></code>. Then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent to <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Sigs3</c-><i><sub><c- n>0</c-></sub></i><c- p>...,</c-> <c- n>Sigs3</c-><i><sub><c- n>1</c-></sub></i><c- p>...,</c-> <c- p>...</c-> <c- n>Sigs3</c-><i><sub><c- n>n</c-><c- mf>-1</c-></sub></i><c- mf>.</c-><c- p>..,</c-> <c- n>Rest</c-><c- p>...,</c-> <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-></code>, where <code class="highlight"><i><c- n>n</c-></i></code> is <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Sigs2</c-><c- p>)</c-></code>.</p>
         </ol>
       </ol>
     </ol>
     <p>If <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> does not return a sender that invokes <code class="highlight"><c- n>f</c-></code> when <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code> is called, and makes its completion dependent on the completion of a sender returned by <code class="highlight"><c- n>f</c-></code>, and propagates the other completion-signals sent by <code class="highlight"><c- n>s</c-></code>, the behavior of calling <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.10" id="spec-execution.senders.adapt.bulk"><span class="secno">11.8.6.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> <b>[exec.bulk]</b></span><a class="self-link" href="#spec-execution.senders.adapt.bulk"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> is used to run a task repeatedly for every index in an index space.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> denotes a customization point object. For some
subexpressions <code class="highlight"><c- n>s</c-></code>, <code class="highlight"><c- n>shape</c-></code>, and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>, <code class="highlight"><c- n>Shape</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>shape</c-><c- p>))</c-></code>, and <code class="highlight"><c- n>F</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code> or <code class="highlight"><c- n>Shape</c-></code> does not satisfy <code class="highlight"><c- n>integral</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>,</c-> <c- n>s</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code>:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, calls <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>i</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> for each <code class="highlight"><c- n>i</c-></code> of type <code class="highlight"><c- n>Shape</c-></code> from <code class="highlight"><c- mi>0</c-></code> to <code class="highlight"><c- n>shape</c-></code>, then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>. If any of these throws an exception, it catches it and calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, which results in an operation state <code class="highlight"><c- n>op_state2</c-></code>.</p>
        <li data-md>
         <p>Returns an operation state <code class="highlight"><c- n>op_state</c-></code> that contains <code class="highlight"><c- n>op_state2</c-></code>. When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned
from <code class="highlight"><c- n>bulk</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>S</c->'</code> be <code class="highlight"><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-></code>, let <code class="highlight"><c- n>Shape</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>shape</c-><c- p>))</c-></code> and let <code class="highlight"><i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i></code> be the alias template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i> <c- o>=</c->
    <c- n>bool_constant</c-><c- o>&lt;</c-><c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>>&amp;</c-><c- p>,</c-> <c- n>Shape</c-><c- p>,</c-> <c- n>As</c-><c- p>...</c-><c- o>>></c-><c- p>;</c->
</pre>
         <ol>
          <li data-md>
           <p>If any of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c->'<c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code> are <code class="highlight"><c- n>false_type</c-></code>, then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be
equivalent to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>S</c->'<c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>>></c->
</pre>
          <li data-md>
           <p>Otherwise, the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent to <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c->'<c- p>,</c-> <c- n>E</c-><c- o>></c-></code>.</p>
         </ol>
       </ol>
      <li data-md>
       <p>If the function selected above does not return a sender which invokes <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>i</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> for each <code class="highlight"><c- n>i</c-></code> of type <code class="highlight"><c- n>Shape</c-></code> from <code class="highlight"><c- mi>0</c-></code> to <code class="highlight"><c- n>shape</c-></code> when
the input sender sends values <code class="highlight"><c- n>args</c-><c- p>...</c-></code>, or does not propagate the
values of the signals sent by the input sender to a connected receiver,
the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is undefined.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.11" id="spec-execution.senders.adapt.split"><span class="secno">11.8.6.11. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> <b>[exec.split]</b></span><a class="self-link" href="#spec-execution.senders.adapt.split"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> is used to adapt an arbitrary sender into a sender that can be connected multiple times.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>split</c-><c- o>-</c-><c- n>env</c-></i></code> be the type of an execution environment such that, given an instance <code class="highlight"><c- n>e</c-></code>, the expression <code class="highlight"><c- n>get_stop_token</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> is well formed and has type <code class="highlight"><c- n>stop_token</c-></code>.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> denotes a customization point object. For some
subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>split</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> or <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>attrs_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-><c- p>,</c-> <c- n>attrs_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>split</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>)</c-></code>,
if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>split</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>, which:</p>
       <ol>
        <li data-md>
         <p>Creates an object <code class="highlight"><c- n>sh_state</c-></code> that contains a <code class="highlight"><c- n>stop_source</c-></code>, a list of
pointers to operation states awaiting the completion of <code class="highlight"><c- n>s</c-></code>, and that
also reserves space for storing:</p>
         <ul>
          <li data-md>
           <p>the operation state that results from connecting <code class="highlight"><c- n>s</c-></code> with <code class="highlight"><c- n>r</c-></code> described below, and</p>
          <li data-md>
           <p>the sets of values and errors with which <code class="highlight"><c- n>s</c-></code> may complete, with
the addition of <code class="highlight"><c- n>exception_ptr</c-></code>.</p>
          <li data-md>
           <p>the result of decay-copying <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>.</p>
         </ul>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, decay-copies
the expressions <code class="highlight"><c- n>args</c-><c- p>...</c-></code> into <code class="highlight"><c- n>sh_state</c-></code>. It then notifies all
the operation states in <code class="highlight"><c- n>sh_state</c-></code>'s list of operation states
that the results are ready. If any exceptions are thrown, the
exception is caught and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code> is called instead.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is called, decay-copies <code class="highlight"><c- n>e</c-></code> into <code class="highlight"><c- n>sh_state</c-></code>. It then notifies the operation states in <code class="highlight"><c- n>sh_state</c-></code>'s list of operation states that the results are ready.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is called, it then notifies the
operation states in <code class="highlight"><c- n>sh_state</c-></code>'s list of operation states that
the results are ready.</p>
          <li data-md>
           <p><code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is an expression <code class="highlight"><i><c- n>e</c-></i></code> of type <code class="highlight"><i><c- n>split</c-><c- o>-</c-><c- n>env</c-></i></code> such that <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><i><c- n>e</c-></i><c- p>)</c-></code> is well-formed
and returns the results of calling <code class="highlight"><c- n>get_token</c-><c- p>()</c-></code> on <code class="highlight"><c- n>sh_state</c-></code>'s
stop source.</p>
         </ol>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> and decay-copies the result into <code class="highlight"><c- n>sh_state</c-></code>.</p>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state2</c-></code>. <code class="highlight"><c- n>op_state2</c-></code> is saved in <code class="highlight"><c- n>sh_state</c-></code>.</p>
        <li data-md>
         <p>When <code class="highlight"><c- n>s2</c-></code> is connected with a receiver <code class="highlight"><c- n>out_r</c-></code> of type <code class="highlight"><c- n>OutR</c-></code>, it
returns an operation state object <code class="highlight"><c- n>op_state</c-></code> that contains:</p>
         <ul>
          <li data-md>
           <p>An object <code class="highlight"><c- n>out_r</c->'</code> of type <code class="highlight"><c- n>OutR</c-></code> decay-copied from <code class="highlight"><c- n>out_r</c-></code>,</p>
          <li data-md>
           <p>A reference to <code class="highlight"><c- n>sh_state</c-></code>,</p>
          <li data-md>
           <p>A stop callback of type <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>OutR</c-><c- o>>>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- o>>></c-></code>,
where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i></code> is an implementation
defined class type equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i> <c- p>{</c->
  <c- n>stop_source</c-><c- o>&amp;</c-> <c- n>stop_src_</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>stop_src_</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
         </ul>
        <li data-md>
         <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called:</p>
         <ul>
          <li data-md>
           <p>If <code class="highlight"><c- n>r</c-></code>'s receiver contract has already been satisfied, then let <code class="highlight"><i><c- n>Signal</c-></i></code> be whichever receiver completion-signal
was used to complete r’s receiver contract ([exec.recv]). Calls <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>out_r</c->'<c- p>,</c-> <c- n>args2</c-><c- p>...)</c-></code>, where <code class="highlight"><c- n>args2</c-><c- p>...</c-></code> is a
pack of const lvalues referencing the subobjects of <code class="highlight"><c- n>sh_state</c-></code> that
have been saved by the original call to <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> and returns.</p>
          <li data-md>
           <p>Otherwise, it emplace constructs the stop callback optional with
the arguments <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>out_r</c->'<c- p>))</c-></code> and <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- p>{</c-><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>}</c-></code>, where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i></code> refers to the stop source of <code class="highlight"><c- n>sh_state</c-></code>.</p>
          <li data-md>
           <p>Otherwise, it adds a pointer to <code class="highlight"><c- n>op_state</c-></code> to the list of
operation states in <code class="highlight"><c- n>sh_state</c-></code>. If <code class="highlight"><c- n>op_state</c-></code> is the first such
state added to the list:</p>
           <ul>
            <li data-md>
             <p>If <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>,
  all of the operation states in <code class="highlight"><c- n>sh_state</c-></code>'s list of operation
  states are notified as if <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> had
  been called.</p>
            <li data-md>
             <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code> is called.</p>
           </ul>
         </ul>
        <li data-md>
         <p>When <code class="highlight"><c- n>r</c-></code> completes it will notify <code class="highlight"><c- n>op_state</c-></code> that the result are
ready. Let <code class="highlight"><i><c- n>Signal</c-></i></code> be whichever receiver
completion-signal was used to complete <code class="highlight"><c- n>r</c-></code>'s receiver contract
([exec.recv]). <code class="highlight"><c- n>op_state</c-></code>'s stop callback optional is reset. Then <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>out_r</c->'<c- p>),</c-> <c- n>args2</c-><c- p>...)</c-></code> is called,
where <code class="highlight"><c- n>args2</c-><c- p>...</c-></code> is a pack of const lvalues referencing the subobjects of <code class="highlight"><c- n>sh_state</c-></code> that have been saved by the original call to <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
        <li data-md>
         <p>Ownership of <code class="highlight"><c- n>sh_state</c-></code> is shared by <code class="highlight"><c- n>s2</c-></code> and by every <code class="highlight"><c- n>op_state</c-></code> that results from connecting <code class="highlight"><c- n>s2</c-></code> to a receiver.</p>
       </ol>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>split</c-></code> or a copy of such, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s2</c-><c- p>)</c-></code> shall return an lvalue reference to the
object in <code class="highlight"><c- n>sh_state</c-></code> that was initialized with the result of <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned
from <code class="highlight"><c- n>split</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent
to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c->
  <c- n>E</c-><c- p>,</c->
  <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
                        <c- n>set_error_t</c-><c- p>(</c-><i><c- n>Es</c-></i><c- p>)...</c-><c- o>></c-><c- p>,</c->
  <i><c- n>value</c-><c- o>-</c-><c- n>signatures</c-></i><c- p>,</c->
  <i><c- n>error</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>></c-><c- p>;</c->
</pre>
       <p>where <code class="highlight"><i><c- n>Es</c-></i></code> is a (possibly empty) template parameter pack, <code class="highlight"><i><c- n>value</c-><c- o>-</c-><c- n>signatures</c-></i></code> is the alias template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>value</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- k>const</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>>&amp;</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->
</pre>
       <p>and <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>signatures</c-></i></code> is the alias template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>error</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- k>const</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>E</c-><c- o>>&amp;</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
</pre>
      <li data-md>
       <p>Let <code class="highlight"><c- n>s</c-></code> be a sender expression, <code class="highlight"><c- n>r</c-></code> be an instance of the receiver type
described above, <code class="highlight"><c- n>s2</c-></code> be a sender returned
from <code class="highlight"><c- n>split</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> or a copy of such, <code class="highlight"><c- n>r2</c-></code> is the receiver
to which <code class="highlight"><c- n>s2</c-></code> is connected, and <code class="highlight"><c- n>args</c-></code> is the pack of subexpressions
passed to <code class="highlight"><c- n>r</c-></code>'s completion-signal operation <code class="highlight"><i><c- n>CSO</c-></i></code> when <code class="highlight"><c- n>s</c-></code> completes. <code class="highlight"><c- n>s2</c-></code> shall satisfy <code class="highlight"><c- n>r2</c-></code>'s receiver contract
([exec.recv]) by invoking <code class="highlight"><i><c- n>CSO</c-></i><c- p>(</c-><c- n>r2</c-><c- p>,</c-> <c- n>args2</c-><c- p>...)</c-></code> where <code class="highlight"><c- n>args2</c-></code> is a pack of const lvalue references to objects decay-copied from <code class="highlight"><c- n>args</c-></code>, or by calling <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>r2</c-><c- p>,</c-> <c- n>e2</c-><c- p>)</c-></code> for some subexpression <code class="highlight"><c- n>e2</c-></code>. The objects passed to <code class="highlight"><c- n>r2</c-></code>'s completion-signal operation shall
be valid until after the completion of the invocation of <code class="highlight"><c- n>r2</c-></code>'s completion-
signal operation.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.12" id="spec-execution.senders.adaptor.when_all"><span class="secno">11.8.6.12. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> <b>[exec.when_all]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.when_all"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> is used to join multiple sender chains and create a sender whose execution is dependent on all of the input senders that only send a single set of values. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-></code> is used to join multiple sender chains and create a sender whose execution is dependent on all of the input senders, each of which may have one or more sets of sent values.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code>, let <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>))...</c-></code>. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is ill-formed if any of the following is true:</p>
     <ul>
      <li data-md>
       <p>If the number of subexpressions <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> is 0, or</p>
      <li data-md>
       <p>If any type <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
     </ul>
     <p>Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>,</c-> <c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code>, if
that expression is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does
not return a sender that sends a concatenation of values sent by <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> when they all complete with <code class="highlight"><c- n>set_value</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>w</c-></code> of type <code class="highlight"><c- n>W</c-></code>. When <code class="highlight"><c- n>w</c-></code> is connected
with some receiver <code class="highlight"><c- n>out_r</c-></code> of type <code class="highlight"><c- n>OutR</c-></code>, it returns an operation state <code class="highlight"><c- n>op_state</c-></code> specified as below:</p>
       <ol>
        <li data-md>
         <p>For each sender <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i></code>, constructs a receiver <code class="highlight"><c- n>r</c-><i><sub><c- n>i</c-></sub></i></code> such that:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>t</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is called for every <code class="highlight"><c- n>r</c-><i><sub><c- n>i</c-></sub></i></code>, <code class="highlight"><c- n>op_state</c-></code>'s associated stop callback optional is reset and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>t</c-><i><sub><c- n>0</c-></sub></i><c- p>...,</c-> <c- n>t</c-><i><sub><c- n>1</c-></sub></i><c- p>...,</c-> <c- p>...,</c-> <c- n>t</c-><i><sub><c- n>n</c-><c- mf>-1</c-></sub></i><c- mf>.</c-><c- p>..)</c-></code> is called, where <code class="highlight"><c- n>n</c-></code> the number of subexpressions in <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code>.</p>
          <li data-md>
           <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> was called for at least one receiver <code class="highlight"><c- n>r</c-><i><sub><c- n>i</c-></sub></i></code>. If the first such to complete did so with the call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>, <code class="highlight"><c- n>request_stop</c-></code> is called on <code class="highlight"><c- n>op_state</c-></code>'s associated stop source. When all child operations have completed, <code class="highlight"><c- n>op_state</c-></code>'s associated stop callback optional is reset and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is called.</p>
          <li data-md>
           <p>Otherwise, <code class="highlight"><c- n>request_stop</c-></code> is called on <code class="highlight"><c- n>op_state</c-></code>'s associated stop source. When all child operations have completed, <code class="highlight"><c- n>op_state</c-></code>'s associated stop callback optional is reset and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code> is called.</p>
          <li data-md>
           <p>For each receiver <code class="highlight"><c- n>r</c-><i><sub><c- n>i</c-></sub></i></code>, <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><i><sub><c- n>i</c-></sub></i><c- p>)</c-></code> is an expression <code class="highlight"><i><c- n>e</c-></i></code> such that <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><i><c- n>e</c-></i><c- p>)</c-></code> is well-formed and returns the results of calling <code class="highlight"><c- n>get_token</c-><c- p>()</c-></code> on <code class="highlight"><c- n>op_state</c-></code>'s associated stop source, and for which <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <i><c- n>e</c-></i><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>out_r</c-><c- p>),</c-> <c- n>args</c-><c- p>...)</c-></code> for all arguments <code class="highlight"><c- n>args</c-><c- p>...</c-></code> and all <code class="highlight"><c- n>tag</c-></code> whose type satisfies <code class="highlight"><i><c- n>forwarding</c-><c- o>-</c-><c- n>query</c-></i></code> and is not <code class="highlight"><c- n>get_stop_token_t</c-></code>.</p>
         </ol>
        <li data-md>
         <p>For each sender <code class="highlight"><c- n>s</c-><i><sub><c- n>i</c-></sub></i></code>, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>r</c-><i><sub><c- n>i</c-></sub></i><c- p>)</c-></code>, resulting in operation states <code class="highlight"><c- n>child_op</c-><i><sub><c- n>i</c-></sub></i></code>.</p>
        <li data-md>
         <p>Returns an operation state <code class="highlight"><c- n>op_state</c-></code> that contains:</p>
         <ul>
          <li data-md>
           <p>Each operation state <code class="highlight"><c- n>child_op</c-><i><sub><c- n>i</c-></sub></i></code>,</p>
          <li data-md>
           <p>A stop source of type <code class="highlight"><c- n>in_place_stop_source</c-></code>,</p>
          <li data-md>
           <p>A stop callback of type <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>OutR</c-><c- o>>>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- o>>></c-></code>, where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i></code> is an implementation defined class type equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i> <c- p>{</c->
  <c- n>in_place_stop_source</c-><c- o>&amp;</c-> <c- n>stop_src_</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>stop_src_</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
         </ul>
        <li data-md>
         <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called it:</p>
         <ul>
          <li data-md>
           <p>Emplace constructs the stop callback optional with the arguments <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>out_r</c-><c- p>))</c-></code> and <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- p>{</c-><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>}</c-></code>, where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i></code> refers to the stop source of <code class="highlight"><c- n>op_state</c-></code>.</p>
          <li data-md>
           <p>Then, it checks to see if <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> is true. If so, it calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
          <li data-md>
           <p>Otherwise, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>child_op</c-><i><sub><c- n>i</c-></sub></i><c- p>)</c-></code> for each <code class="highlight"><c- n>child_op</c-><i><sub><c- n>i</c-></sub></i></code>.</p>
         </ul>
        <li data-md>
         <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned
from <code class="highlight"><c- n>when_all</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>, and let <code class="highlight"><c- n>Ss</c-><c- p>...</c-></code> be the decayed types of the
arguments to the <code class="highlight"><c- n>when_all</c-></code> expression that created <code class="highlight"><c- n>s2</c-></code>. Let <code class="highlight"><c- n>WE</c-></code> be a type such that <code class="highlight"><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>WE</c-><c- o>></c-></code> is <code class="highlight"><c- n>in_place_stop_token</c-></code> and <code class="highlight"><c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>WE</c-><c- p>,</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-></code> names the type, if any, of <code class="highlight"><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-></code> for all types <code class="highlight"><c- n>As</c-><c- p>...</c-></code> and all types <code class="highlight"><c- n>Tag</c-></code> besides <code class="highlight"><c- n>get_stop_token_t</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be as follows:</p>
         <ol>
          <li data-md>
           <p>For each type <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i></code> in <code class="highlight"><c- n>Ss</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>S</c->'<i><sub><c- n>i</c-></sub></i></code> name the type <code class="highlight"><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><i><sub><c- n>i</c-></sub></i><c- o>></c-></code>. If for
any type <code class="highlight"><c- n>S</c->'<i><sub><c- n>i</c-></sub></i></code>, the type <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c->'<i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>WE</c-><c- o>></c-></code> is ill-formed, the expression of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is
ill-formed.</p>
          <li data-md>
           <p>Otherwise, for each type <code class="highlight"><c- n>S</c->'<i><sub><c- n>i</c-></sub></i></code>, let <code class="highlight"><c- n>Sigs</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be the set of template
arguments in the instantiation of <code class="highlight"><c- n>completion_signatures</c-></code> named
by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c->'<i><sub><c- n>i</c-></sub></i><c- p>,</c-> <c- n>WE</c-><c- o>></c-></code>, and let <code class="highlight"><c- n>C</c-><i><sub><c- n>i</c-></sub></i></code> be the
count of function types in <code class="highlight"><c- n>Sigs</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> for which the return
type is <code class="highlight"><c- n>set_value_t</c-></code>. If any <code class="highlight"><c- n>C</c-><i><sub><c- n>i</c-></sub></i></code> is two or greater, then the
expression <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is
ill-formed.</p>
          <li data-md>
           <p>Otherwise, let <code class="highlight"><c- n>Sigs2</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be the set of
function types in <code class="highlight"><c- n>Sigs</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> whose
return types are <i>not</i> <code class="highlight"><c- n>set_value_t</c-></code>, and let <code class="highlight"><c- n>Ws</c-><c- p>...</c-></code> be
the unique set of types in <code class="highlight"><c- p>[</c-><c- n>Sigs2</c-><i><sub><c- n>0</c-></sub></i><c- p>...,</c-> <c- n>Sigs2</c-><i><sub><c- n>1</c-></sub></i><c- p>...,</c-> <c- p>...</c-> <c- n>Sigs2</c-><i><sub><c- n>n</c-><c- mf>-1</c-></sub></i><c- mf>.</c-><c- p>..,</c-> <c- n>set_stopped_t</c-><c- p>()]</c-></code>, where <code class="highlight"><i><c- n>n</c-></i></code> is <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Ss</c-><c- p>)</c-></code>. If any <code class="highlight"><c- n>C</c-><i><sub><c- n>i</c-></sub></i></code> is <code class="highlight"><c- mi>0</c-></code>, then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Ws</c-><c- p>...</c-><c- o>></c-></code>.</p>
          <li data-md>
           <p>Otherwise, let <code class="highlight"><c- n>V</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be the
function argument types of the single type in <code class="highlight"><c- n>Sigs</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> for which the return
type is <code class="highlight"><c- n>set_value_t</c-></code>. Then the type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Ws</c-><c- p>...,</c-> <c- n>set_value_t</c-><c- p>(</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>V</c-><i><sub><c- n>0</c-></sub></i><c- o>>&amp;&amp;</c-><c- p>...,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>V</c-><i><sub><c- n>1</c-></sub></i><c- o>>&amp;&amp;</c-><c- p>...,</c-> <c- p>...</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>V</c-><i><sub><c- n>n</c-><c- mi>-1</c-></sub></i><c- o>>&amp;&amp;</c-><c- p>...)</c-><c- o>></c-></code>.</p>
         </ol>
       </ol>
     </ol>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>s</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If any type <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i></code> in <code class="highlight"><c- n>S</c-><c- p>...</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-><c- p>(</c-><c- n>s</c-><c- p>...)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code>, if that expression
is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a
sender that, when connected with a receiver of type <code class="highlight"><c- n>R</c-></code>, sends the types <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-><c- p>...</c-></code> when they
all complete with <code class="highlight"><c- n>set_value</c-></code>, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>s</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)...)</c-></code>.</p>
     </ol>
    <li data-md>
     <p>For a sender <code class="highlight"><c- n>s2</c-></code> returned from <code class="highlight"><c- n>when_all</c-></code> or <code class="highlight"><c- n>when_all_with_variant</c-></code>, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s2</c-><c- p>)</c-></code> shall return an instance of a class equivalent to <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>attrs</c-></i></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.13" id="spec-execution.senders.adaptor.transfer_when_all"><span class="secno">11.8.6.13. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code> <b>[exec.transfer_when_all]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.transfer_when_all"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code> is used to join multiple sender chains and
create a sender whose execution is dependent on all of the input senders
that only send a single set of values each, while also making sure that they
complete on the specified scheduler. <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-></code> is used to join multiple sender
chains and create a sender whose execution is dependent on all of the input
senders, which may have one or more sets of sent values. [<i>Note:</i> this
can allow for better customization of the adaptors. --<i>end note</i>]</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>s</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> and <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, or any type <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i></code> in <code class="highlight"><c- n>S</c-><c- p>...</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code>, if that expression
is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a
sender that sends a concatenation of values sent by <code class="highlight"><c- n>s</c-><c- p>...</c-></code> when they all
complete with <code class="highlight"><c- n>set_value</c-></code>, or does not send its completion signals,
other than ones resulting from a scheduling error, on an execution agent
belonging to the associated execution context of <code class="highlight"><c- n>sch</c-></code>, the behavior of
calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>s</c-><c- p>...),</c-> <c- n>sch</c-><c- p>)</c-></code>.</p>
     </ol>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-></code> denotes a customization
point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>s</c-><c- p>...</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If any type <code class="highlight"><c- n>S</c-><i><sub><c- n>i</c-></sub></i></code> in <code class="highlight"><c- n>S</c-><c- p>...</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-></code> is
ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code> is expression-equivalent
to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code>, if that
expression is valid. If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not
return a sender that, when connected with a receiver of type <code class="highlight"><c- n>R</c-></code>, sends
the types <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-><c- p>...</c-></code> when they all complete with <code class="highlight"><c- n>set_value</c-></code>, the behavior
of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all_with_variant</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)...)</c-></code>.</p>
     </ol>
    <li data-md>
     <p>For a sender <code class="highlight"><c- n>t</c-></code> returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer_when_all</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>s</c-><c- p>...)</c-></code>, <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> shall
return a queryable object <code class="highlight"><c- n>q</c-></code> such that <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> returns
a copy of <code class="highlight"><c- n>sch</c-></code>, where <code class="highlight"><c- n>CPO</c-></code> is either <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>. The <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- o>></c-></code> query is not implemented, as the scheduler
cannot be guaranteed in case an error is thrown while trying to schedule work on
the given scheduler object.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.14" id="spec-execution.senders.adapt.into_variant"><span class="secno">11.8.6.14. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> <b>[exec.into_variant]</b></span><a class="self-link" href="#spec-execution.senders.adapt.into_variant"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> can be used to turn a sender which sends multiple sets of values into a sender which sends a variant of all of those sets of values.</p>
    <li data-md>
     <p>The template <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i></code> is used to compute the type sent by a sender returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c->
    <c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> is a customization point object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> returns
a sender <code class="highlight"><c- n>s2</c-></code>. When <code class="highlight"><c- n>s2</c-></code> is connected with some receiver <code class="highlight"><c- n>out_r</c-></code>, it:</p>
     <ol>
      <li data-md>
       <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code>:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>ts</c-><c- p>...)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>r</c-><c- p>))</c-><c- o>>></c-><c- p>(</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>ts</c-><c- p>)...</c-><c- o>></c-><c- p>(</c-><c- n>ts</c-><c- p>...)))</c-></code>. If this expression throws an exception, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code>.</p>
        <li data-md>
         <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>out_r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c-><c- p>)</c-></code>.</p>
       </ol>
      <li data-md>
       <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state2</c-></code>.</p>
      <li data-md>
       <p>Returns an operation state <code class="highlight"><c- n>op_state</c-></code> that contains <code class="highlight"><c- n>op_state2</c-></code>. When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called, calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code>, where <code class="highlight"><c- n>s2</c-></code> is a sender returned from <code class="highlight"><c- n>into_variant</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>.
Let <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i></code> be the class template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i> <c- p>{</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- p>...</c-><c- n>Args</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>apply</c-></i> <c- o>=</c-> <c- n>set_value_t</c-><c- p>(</c-><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-><c- p>);</c->
<c- p>};</c->
</pre>
       <p>Let <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>is</c-><c- o>-</c-><c- n>nothrow</c-></i></code> be the class template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>is</c-><c- o>-</c-><c- n>nothrow</c-></i> <c- p>{</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
      <c- k>requires</c-> <c- n>constructible_from</c-><c- o>&lt;</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>apply</c-></i> <c- o>=</c-> <c- n>bool_constant</c-><c- o>&lt;</c-><c- k>noexcept</c-><c- p>(</c->
      <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-><c- p>(</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>()...)))</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->
</pre>
       <p>Let <code class="highlight"><i><c- n>INTO</c-><c- o>-</c-><c- n>VARIANT</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>SIGNATURES</c-></i><c- p>(</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>)</c-></code> be <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-></code> if any of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>is</c-><c- o>-</c-><c- n>nothrow</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>>::</c-><c- k>template</c-> <i><c- n>apply</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code> are <code class="highlight"><c- n>false_type</c-></code>; otherwise, <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code>.</p>
       <p>The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures_t</c-><c- p>{},</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
    <c- n>S2</c-><c- p>,</c->
    <c- n>E</c-><c- p>,</c->
    <i><c- n>INTO</c-><c- o>-</c-><c- n>VARIANT</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>SIGNATURES</c-></i><c- p>(</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>),</c->
    <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>E</c-><c- o>>::</c-><c- k>template</c-> <i><c- n>apply</c-></i>
<c- o>></c->
</pre>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.15" id="spec-execution.senders.adapt.stopped_as_optional"><span class="secno">11.8.6.15. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> <b>[exec.stopped_as_optional]</b></span><a class="self-link" href="#spec-execution.senders.adapt.stopped_as_optional"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> is used to handle a stopped signal by mapping it into the value channel as an empty optional. The value channel is also converted into an optional. The result is a sender that never completes with stopped, reporting cancellation by completing with an empty optional.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> denotes a customization point object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. Let <code class="highlight"><i><c- n>get</c-><c- o>-</c-><c- n>env</c-><c- o>-</c-><c- n>sender</c-></i></code> be an expression such that, when it is <code class="highlight"><c- n>connect</c-></code>ed with a receiver <code class="highlight"><c- n>r</c-></code>, <code class="highlight"><c- n>start</c-></code> on the resulting operation state completes immediately by calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code>. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>env</c-><c- o>-</c-><c- n>sender</c-></i><c- p>,</c->
  <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c-><c- p>(</c-><c- k>const</c-> <c- n>E</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>requires</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-><c- p>(</c->
      <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>s</c-><c- p>,</c->
        <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c->
          <c- k>return</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>>>></c-><c- p>{</c->
            <c- k>static_cast</c-><c- o>&lt;</c-><c- n>T</c-><c- o>&amp;&amp;></c-><c- p>(</c-><c- n>t</c-><c- p>)</c->
          <c- p>};</c->
        <c- p>}</c->
      <c- p>),</c->
      <c- p>[]</c-> <c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>>>></c-><c- p>{});</c->
      <c- p>}</c->
    <c- p>);</c->
  <c- p>}</c->
<c- p>)</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.16" id="spec-execution.senders.adapt.stopped_as_error"><span class="secno">11.8.6.16. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> <b>[exec.stopped_as_error]</b></span><a class="self-link" href="#spec-execution.senders.adapt.stopped_as_error"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> is used to handle a stopped signal by mapping it into the error channel as a custom exception type. The result is a sender that never completes with stopped, reporting cancellation by completing with an error.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>s</c-></code> and <code class="highlight"><c- n>e</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. If the type <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code> or if the type <code class="highlight"><c- n>E</c-></code> doesn’t satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>just_error</c-><c- p>(</c-><c- n>e</c-><c- p>);</c-> <c- p>})</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="11.8.6.17" id="spec-execution.senders.adapt.ensure_started"><span class="secno">11.8.6.17. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> <b>[exec.ensure_started]</b></span><a class="self-link" href="#spec-execution.senders.adapt.ensure_started"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> is used to eagerly start the execution of a sender, while also providing a way to attach further work to execute once it has completed.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>env</c-></i></code> be the type of an execution
environment such that, given an instance <code class="highlight"><c- n>e</c-></code>, the expression <code class="highlight"><c- n>get_stop_token</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code> is well formed and has type <code class="highlight"><c- n>stop_token</c-></code>.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> denotes a customization point object.
For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> or <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>attrs_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-><c- p>,</c-> <c- n>attrs_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed. Otherwise, the
expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above satisfies <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, constructs a sender <code class="highlight"><c- n>s2</c-></code>, which:</p>
       <ol>
        <li data-md>
         <p>Creates an object <code class="highlight"><c- n>sh_state</c-></code> that contains a <code class="highlight"><c- n>stop_source</c-></code>, an
initially null pointer to an operation state awaitaing completion,
and that also reserves space for storing:</p>
         <ul>
          <li data-md>
           <p>the operation state that results from connecting <code class="highlight"><c- n>s</c-></code> with <code class="highlight"><c- n>r</c-></code> described below, and</p>
          <li data-md>
           <p>the sets of values and errors with which <code class="highlight"><c- n>s</c-></code> may complete, with
the addition of <code class="highlight"><c- n>exception_ptr</c-></code>.</p>
          <li data-md>
           <p>the result of decay-copying <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>.</p>
         </ul>
         <p><code class="highlight"><c- n>s2</c-></code> shares ownership of <code class="highlight"><c- n>sh_state</c-></code> with <code class="highlight"><c- n>r</c-></code> described below.</p>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is called, decay-copies
the expressions <code class="highlight"><c- n>args</c-><c- p>...</c-></code> into <code class="highlight"><c- n>sh_state</c-></code>. It then checks <code class="highlight"><c- n>sh_state</c-></code> to see if there is an operation state awaiting
completion; if so, it notifies the operation state that the
results are ready. If any exceptions are thrown, the exception
is caught and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>())</c-></code> is
called instead.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is called, decay-copies <code class="highlight"><c- n>e</c-></code> into <code class="highlight"><c- n>sh_state</c-></code>. If there is an operation state awaiting completion,
it then notifies the operation state that the results are ready.</p>
          <li data-md>
           <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is called, it then notifies any
awaiting operation state that the results are ready.</p>
          <li data-md>
           <p><code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is an expression <code class="highlight"><i><c- n>e</c-></i></code> of type <code class="highlight"><i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>env</c-></i></code> such that <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><i><c- n>e</c-></i><c- p>)</c-></code> is well-formed
and returns the results of calling <code class="highlight"><c- n>get_token</c-><c- p>()</c-></code> on <code class="highlight"><c- n>sh_state</c-></code>'s
stop source.</p>
          <li data-md>
           <p><code class="highlight"><c- n>r</c-></code> shares ownership of <code class="highlight"><c- n>sh_state</c-></code> with <code class="highlight"><c- n>s2</c-></code>. After <code class="highlight"><c- n>r</c-></code>'s
receiver contract has been completed, it releases its ownership
of <code class="highlight"><c- n>sh_state</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> and decay-copies the result into <code class="highlight"><c- n>sh_state</c-></code>.</p>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state2</c-></code>. <code class="highlight"><c- n>op_state2</c-></code> is saved in <code class="highlight"><c- n>sh_state</c-></code>. It then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state2</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>When <code class="highlight"><c- n>s2</c-></code> is connected with a receiver <code class="highlight"><c- n>out_r</c-></code> of type <code class="highlight"><c- n>OutR</c-></code>, it
returns an operation state object <code class="highlight"><c- n>op_state</c-></code> that contains:</p>
         <ul>
          <li data-md>
           <p>An object <code class="highlight"><c- n>out_r</c->'</code> of type <code class="highlight"><c- n>OutR</c-></code> decay-copied from <code class="highlight"><c- n>out_r</c-></code>,</p>
          <li data-md>
           <p>A reference to <code class="highlight"><c- n>sh_state</c-></code>,</p>
          <li data-md>
           <p>A stop callback of type <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>OutR</c-><c- o>>>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- o>>></c-></code>,
where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i></code> is an implementation
defined class type equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i> <c- p>{</c->
  <c- n>stop_source</c-><c- o>&amp;</c-> <c- n>stop_src_</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>stop_src_</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
         </ul>
         <p><code class="highlight"><c- n>s2</c-></code> transfers its ownership of <code class="highlight"><c- n>sh_state</c-></code> to <code class="highlight"><c- n>op_state</c-></code>.</p>
        <li data-md>
         <p>When <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code> is called:</p>
         <ul>
          <li data-md>
           <p>If <code class="highlight"><c- n>r</c-></code>'s receiver contract has already been satisfied, then let <code class="highlight"><i><c- n>Signal</c-></i></code> be whichever receiver completion-signal
was used to complete <code class="highlight"><c- n>r</c-></code>'s receiver contract ([exec.recv]). Calls <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>out_r</c->'<c- p>,</c-> <c- n>args2</c-><c- p>...)</c-></code>, where <code class="highlight"><c- n>args2</c-><c- p>...</c-></code> is a
pack of xvalues referencing the subobjects of <code class="highlight"><c- n>sh_state</c-></code> that have
been saved by the original call to <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> and returns.</p>
          <li data-md>
           <p>Otherwise, it emplace constructs the stop callback optional with
the arguments <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>out_r</c->'<c- p>))</c-></code> and <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>callback</c-><c- o>-</c-><c- n>fn</c-></i><c- p>{</c-><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>}</c-></code>, where <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i></code> refers to the stop source of <code class="highlight"><c- n>sh_state</c-></code>.</p>
          <li data-md>
           <p>Then, it checks to see if <code class="highlight"><i><c- n>stop</c-><c- o>-</c-><c- n>src</c-></i><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>. If so, it
calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>out_r</c->'<c- p>)</c-></code>.</p>
          <li data-md>
           <p>Otherwise, it sets <code class="highlight"><c- n>sh_state</c-></code> operation state pointer to the
address of <code class="highlight"><c- n>op_state</c-></code>, registering itself as awaiting the result
of the completion of <code class="highlight"><c- n>r</c-></code>.</p>
         </ul>
        <li data-md>
         <p>When <code class="highlight"><c- n>r</c-></code> completes it will notify <code class="highlight"><c- n>op_state</c-></code> that the result are
ready. Let <code class="highlight"><i><c- n>Signal</c-></i></code> be whichever receiver
completion-signal was used to complete <code class="highlight"><c- n>r</c-></code>'s receiver contract
([exec.recv]). <code class="highlight"><c- n>op_state</c-></code>'s stop callback optional is reset. Then <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>out_r</c->'<c- p>),</c-> <c- n>args2</c-><c- p>...)</c-></code> is called,
where <code class="highlight"><c- n>args2</c-><c- p>...</c-></code> is a pack of xvalues referencing the subobjects of <code class="highlight"><c- n>sh_state</c-></code> that have been saved by the original call to <code class="highlight"><i><c- n>Signal</c-></i><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
        <li data-md>
         <p>[<em>Note:</em> If sender <code class="highlight"><c- n>s2</c-></code> is destroyed without being connected to a
receiver, or if it is connected but the operation state is destroyed
without having been started, then when <code class="highlight"><c- n>r</c-></code>'s receiver contract
completes and it releases its shared ownership of <code class="highlight"><c- n>sh_state</c-></code>, <code class="highlight"><c- n>sh_state</c-></code> will be destroyed and the results of the operation are
discarded. -- <em>end note</em>]</p>
       </ol>
      <li data-md>
       <p>Given a subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>s2</c-></code> be the result of <code class="highlight"><c- n>ensure_started</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>.
The result of <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s2</c-><c- p>)</c-></code> shall return an lvalue reference to the
object in <code class="highlight"><c- n>sh_state</c-></code> that was initialized with the result of <code class="highlight"><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>Given subexpressions <code class="highlight"><c- n>s2</c-></code> and <code class="highlight"><c- n>e</c-></code> where <code class="highlight"><c- n>s2</c-></code> is a sender returned
from <code class="highlight"><c- n>ensure_started</c-></code> or a copy of such, let <code class="highlight"><c- n>S2</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s2</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>E</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code>. The type of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_signatures</c-><c- p>,</c-> <c- n>s2</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> shall be equivalent
to:</p>
<pre class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>S2</c-><c- p>,</c-> <c- n>S</c-><c- o>></c-><c- p>,</c->
  <i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
  <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- o>&amp;&amp;</c-><c- p>),</c->
                        <c- n>set_error_t</c-><c- p>(</c-><i><c- n>Es</c-></i><c- p>)...</c-><c- o>></c-><c- p>,</c->
  <i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>signature</c-></i><c- p>,</c->
  <i><c- n>error</c-><c- o>-</c-><c- n>types</c-></i><c- o>></c->
</pre>
       <p>where <code class="highlight"><i><c- n>Es</c-></i></code> is a (possibly empty) template parameter pack, <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>signature</c-></i></code> is the alias template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>set</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>>&amp;&amp;</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->
</pre>
       <p>and <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>types</c-></i></code> is the alias template:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>error</c-><c- o>-</c-><c- n>types</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>E</c-><c- o>>&amp;&amp;</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
</pre>
     </ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>s</c-></code> be a sender expression, <code class="highlight"><c- n>r</c-></code> be an instance of the receiver type
  described above, <code class="highlight"><c- n>s2</c-></code> be a sender returned
  from <code class="highlight"><c- n>ensure_started</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> or a copy of such, <code class="highlight"><c- n>r2</c-></code> is the receiver
  to which <code class="highlight"><c- n>s2</c-></code> is connected, and <code class="highlight"><c- n>args</c-></code> is the pack of subexpressions
  passed to <code class="highlight"><c- n>r</c-></code>'s completion-signal operation <code class="highlight"><i><c- n>CSO</c-></i></code> when <code class="highlight"><c- n>s</c-></code> completes. <code class="highlight"><c- n>s2</c-></code> shall satisfy <code class="highlight"><c- n>r2</c-></code>'s receiver contract
  ([exec.recv]) by invoking <code class="highlight"><i><c- n>CSO</c-></i><c- p>(</c-><c- n>r2</c-><c- p>,</c-> <c- n>args2</c-><c- p>...)</c-></code> where <code class="highlight"><c- n>args2</c-></code> is a pack of xvalue references to objects decay-copied from <code class="highlight"><c- n>args</c-></code>, or by calling <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>r2</c-><c- p>,</c-> <c- n>e2</c-><c- p>)</c-></code> for some subexpression <code class="highlight"><c- n>e2</c-></code>. The objects passed to <code class="highlight"><c- n>r2</c-></code>'s completion-signal operation shall
  be valid until after the completion of the invocation of <code class="highlight"><c- n>r2</c-></code>'s completion-
  signal operation.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.7" id="spec-execution.senders.consumers"><span class="secno">11.8.7. </span><span class="content">Sender consumers <b>[exec.consumers]</b></span><a class="self-link" href="#spec-execution.senders.consumers"></a></h4>
   <h5 class="heading settled" data-level="11.8.7.1" id="spec-execution.senders.consumers.start_detached"><span class="secno">11.8.7.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> <b>[exec.start_detached]</b></span><a class="self-link" href="#spec-execution.senders.consumers.start_detached"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> is used to eagerly start a sender without the caller needing to manage the lifetimes of any objects.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> denotes a customization point object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>S</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><c- b>void</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if that expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><c- b>void</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise:</p>
       <ol>
        <li data-md>
         <p>Let <code class="highlight"><c- n>R</c-></code> be the type of a receiver, let <code class="highlight"><c- n>r</c-></code> be an rvalue of type <code class="highlight"><c- n>R</c-></code>, and let <code class="highlight"><c- n>cr</c-></code> be a
lvalue reference to <code class="highlight"><c- k>const</c-> <c- n>R</c-></code> such that:</p>
         <ol>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is not potentially throwing and has no effect,</p>
          <li data-md>
           <p>For any subexpression <code class="highlight"><c- n>e</c-></code>, the expression <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> is expression-equivalent
to <code class="highlight"><c- n>terminate</c-><c- p>()</c-></code>,</p>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is not potentially throwing and has no effect, and</p>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>cr</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>{}</c-></code>.</p>
         </ol>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state</c-></code>, then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code>. The lifetime of <code class="highlight"><c- n>op_state</c-></code> lasts until one of the receiver completion-signals of <code class="highlight"><c- n>r</c-></code> is called.</p>
       </ol>
     </ol>
     <p>If the function selected above does not eagerly start the sender <code class="highlight"><c- n>s</c-></code> after
connecting it with a receiver which ignores the <code class="highlight"><c- n>set_value</c-></code> and <code class="highlight"><c- n>set_stopped</c-></code> signals and calls <code class="highlight"><c- n>terminate</c-><c- p>()</c-></code> on the <code class="highlight"><c- n>set_error</c-></code> signal,
the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h5 class="heading settled" data-level="11.8.7.2" id="spec-execution.senders.consumers.sync_wait"><span class="secno">11.8.7.2. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> <b>[exec.sync_wait]</b></span><a class="self-link" href="#spec-execution.senders.consumers.sync_wait"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code> are used to block a current thread until a sender passed into it as an argument has completed, and to obtain the values (if any) it completed with.</p>
    <li data-md>
     <p>For any receiver <code class="highlight"><c- n>r</c-></code> created by an implementation of <code class="highlight"><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>sync_wait_with_variant</c-></code>, the expressions <code class="highlight"><c- n>get_scheduler</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code> and <code class="highlight"><c- n>get_delegatee_scheduler</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>))</c-></code> shall be well-formed. For a receiver
created by the default implementation of <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, these
expressions shall return a scheduler to the same thread-safe,
first-in-first-out queue of work such that tasks scheduled to the queue
execute on the thread of the caller of <code class="highlight"><c- n>sync_wait</c-></code>. [<i>Note:</i> The
scheduler for an instance of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code> that is a local variable
within <code class="highlight"><c- n>sync_wait</c-></code> is one valid implementation. -- <i>end note</i>]</p>
    <li data-md>
     <p>The templates <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i></code> and <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i></code> are used to determine the
return types of <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code>. Let <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i></code> be the type of the expression <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> where <code class="highlight"><c- n>r</c-></code> is an instance of the
receiver created by the default implementation of <code class="highlight"><c- n>sync_wait</c-></code>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>sender_in</c-><c- o>&lt;</c-><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-> <c- n>S</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c->
    <c- n>optional</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c-> <c- n>type_identity_t</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- n>sender_in</c-><c- o>&lt;</c-><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-> <c- n>S</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> denotes a customization point object. For
some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>s</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> is <code class="highlight">false</code>,
or the number of the arguments <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>>::</c-><c- n>value_types</c-></code> passed into the <code class="highlight"><c- n>Variant</c-></code> template
parameter is not 1, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>)</c-></code>, if this expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if this expression is valid and its type is.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise:</p>
       <ol>
        <li data-md>
         <p>Constructs a receiver <code class="highlight"><c- n>r</c-></code>.</p>
        <li data-md>
         <p>Calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s</c-><c- p>,</c-> <c- n>r</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state</c-></code>, then calls <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code>.</p>
        <li data-md>
         <p>Blocks the current thread until a receiver completion-signal of <code class="highlight"><c- n>r</c-></code> is called. When it is:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>ts</c-><c- p>...)</c-></code> has been called, returns <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-><c- p>{</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>ts</c-><c- p>)...</c-><c- o>></c-><c- p>{</c-><c- n>ts</c-><c- p>...}}</c-></code>. If that expression exits exceptionally, the exception is propagated to the caller of <code class="highlight"><c- n>sync_wait</c-></code>.</p>
          <li data-md>
           <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code> has been called, let <code class="highlight"><c- n>E</c-></code> be the decayed type of <code class="highlight"><c- n>e</c-></code>. If <code class="highlight"><c- n>E</c-></code> is <code class="highlight"><c- n>exception_ptr</c-></code>, calls <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>rethrow_exception</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code>. Otherwise, if the <code class="highlight"><c- n>E</c-></code> is <code class="highlight"><c- n>error_code</c-></code>, throws <code class="highlight"><c- n>system_error</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code>. Otherwise, throws <code class="highlight"><c- n>e</c-></code>.</p>
          <li data-md>
           <p>If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> has been called, returns <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-><c- p>{}</c-></code>.</p>
         </ol>
       </ol>
     </ol>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code> denotes a customization point
object. For some subexpression <code class="highlight"><c- n>s</c-></code>, let <code class="highlight"><c- n>S</c-></code> be the type of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code>. If <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>,</c-> <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><c- n>s</c-><c- p>)),</c-> <c- n>s</c-><c- p>)</c-></code>, if this expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, if this expression is valid.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-><c- p>(</c-><c- n>s</c-><c- p>))</c-></code>.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.9" id="spec-execution.execute"><span class="secno">11.9. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> <b>[exec.execute]</b></span><a class="self-link" href="#spec-execution.execute"></a></h3>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> is used to create fire-and-forget tasks on a specified scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>F</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-></code> or <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><c- n>invocable</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>execute</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code>, if that expression is valid. If
the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not invoke the function <code class="highlight"><c- n>f</c-></code> (or an object decay-copied from <code class="highlight"><c- n>f</c-></code>) on an execution agent belonging to
the associated execution context of <code class="highlight"><c- n>sch</c-></code>, or if it does not call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> if an error occurs after control is returned to the
caller, the behavior of calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above is <code class="highlight"><c- b>void</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>),</c-> <c- n>f</c-><c- p>))</c-></code>.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.10" id="spec-execution.snd_rec_utils"><span class="secno">11.10. </span><span class="content">Sender/receiver utilities <b>[exec.utils]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils"></a></h3>
   <ol>
    <li data-md>
     <p>This section makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- c1>// [</c-><i><c- c1>Editorial note:</c-></i><c- c1> copy_cvref_t as in [[P1450R3]] -- </c-><i><c- c1>end note</c-></i><c- c1>]</c->
<c- c1>// Mandates: is_base_of_v&lt;T, remove_reference_t&lt;U>> is true</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-><c- o>></c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <i><c- n>c</c-><c- o>-</c-><c- n>style</c-><c- o>-</c-><c- n>cast</c-></i><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- k>noexcept</c-> <c- k>requires</c-> <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- p>(</c-><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-><c- p>)</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>(</c-><c- n>u</c-><c- p>);</c->
  <c- p>}</c->
</pre>
    <li data-md>
     <p>
      [<i>Note:</i> The C-style cast in 
      <tt><i>c-style-cast</i></tt>
       is to disable accessibility checks. -- <i>end note</i>]
     </p>
   </ol>
   <h4 class="heading settled" data-level="11.10.1" id="spec-execution.snd_rec_utils.rcvr_adptr"><span class="secno">11.10.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> <b>[exec.utils.rcvr_adptr]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.rcvr_adptr"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c->
    <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
    <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>class</c-> <c- nc>receiver_adaptor</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-></code> is used to simplify the implementation of one receiver type in terms of another. It defines <code class="highlight"><c- n>tag_invoke</c-></code> overloads that forward to named members if they exist, and to the adapted receiver otherwise.</p>
    <li data-md>
     <p>If <code class="highlight"><c- n>Base</c-></code> is an alias for the unspecified default template argument, then:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i></code> be <code class="highlight">false</code>, and</p>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>d</c-><c- p>)</c-></code> be <code class="highlight"><c- n>d</c-><c- p>.</c-><c- n>base</c-><c- p>()</c-></code>.</p>
     </ul>
     <p>otherwise, let:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i></code> be <code class="highlight">true</code>, and</p>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>d</c-><c- p>)</c-></code> be <code class="highlight"><i><c- n>c</c-><c- o>-</c-><c- n>style</c-><c- o>-</c-><c- n>cast</c-></i><c- o>&lt;</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>Derived</c-><c- p>,</c-> <c- n>Base</c-><c- o>>></c-><c- p>(</c-><c- n>d</c-><c- p>).</c-><c- n>base</c-><c- p>()</c-></code>.</p>
     </ul>
     <p>Let <code class="highlight"><i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>D</c-><c- p>)</c-></code> be the type of <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>D</c-><c- o>></c-><c- p>())</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>Derived</c-><c- p>,</c-> <c- n>Base</c-><c- o>></c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c->
  <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
  <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
<c- k>class</c-> <c- nc>receiver_adaptor</c-> <c- p>{</c->
  <c- k>friend</c-> <c- n>Derived</c-><c- p>;</c->
 <c- k>public</c-><c- o>:</c->
  <c- c1>// Constructors</c->
  <c- n>receiver_adaptor</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>B</c-><c- o>></c->
      <c- k>requires</c-> <i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i> <c- o>&amp;&amp;</c-> <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Base</c-><c- p>,</c-> <c- n>B</c-><c- o>></c->
    <c- k>explicit</c-> <c- n>receiver_adaptor</c-><c- p>(</c-><c- n>B</c-><c- o>&amp;&amp;</c-> <c- n>base</c-><c- p>)</c-> <c- o>:</c-> <c- n>base_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>B</c-><c- o>></c-><c- p>(</c-><c- n>base</c-><c- p>))</c-> <c- p>{}</c->

 <c- k>private</c-><c- o>:</c->
  <c- k>using</c-> <c- n>set_value</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>set_error</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>set_stopped</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>get_env</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->

  <c- c1>// Member functions</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Self</c-><c- o>></c->
    <c- k>requires</c-> <i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i>
  <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>base</c-><c- p>(</c-><c- k>this</c-> <c- n>Self</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Self</c-><c- o>></c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>base_</c-><c- p>);</c->
  <c- p>}</c->

  <c- c1>// [exec.utils.rcvr_adptr.nonmembers] Non-member functions</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
    <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c->
    <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>E</c-><c- o>&amp;&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c->
      <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->

  <c- k>template</c-> <c- o>&lt;</c-><i><c- n>forwarding</c-><c- o>-</c-><c- n>query</c-></i> <c- n>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
      <c- k>requires</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>),</c-> <c- n>As</c-><c- p>...</c-><c- o>></c->
    <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-> <c- n>tag</c-><c- p>,</c-> <c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c->
      <c- k>noexcept</c-><c- p>(</c-><i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>),</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-><c- p>)</c->
      <c- o>-></c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>),</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-> <c- p>{</c->
      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>tag</c-><c- p>)(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>self</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>As</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...);</c->
    <c- p>}</c->

  <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>Base</c-> <c- n>base_</c-><c- p>;</c-> <c- c1>// present if and only if </c-><i><c- c1>HAS-BASE</c-></i><c- c1> is true</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>[<i>Note:</i> <code class="highlight"><c- n>receiver_adaptor</c-></code> provides <code class="highlight"><c- n>tag_invoke</c-></code> overloads on behalf of
the derived class <code class="highlight"><c- n>Derived</c-></code>, which is incomplete when <code class="highlight"><c- n>receiver_adaptor</c-></code> is
instantiated.]</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- k>using</c-> <c- n>_int_completion</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>_int_completion</c-><c- o>></c-> <c- n>R</c-><c- o>></c->
  <c- k>class</c-> <c- nc>my_receiver</c-> <c- o>:</c-> <c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>,</c-> <c- n>R</c-><c- o>></c-> <c- p>{</c->
    <c- k>friend</c-> <c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>;</c->
    <c- b>void</c-> <c- nf>set_value</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- p>{</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- mi>42</c-><c- p>);</c->
    <c- p>}</c->
   <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>>::</c-><c- n>receiver_adaptor</c-><c- p>;</c->
  <c- p>};</c->
</pre>
     <p>-- <i>end example</i>]</p>
   </ol>
   <h5 class="heading settled" data-level="11.10.1.1" id="spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"><span class="secno">11.10.1.1. </span><span class="content">Non-member functions <b>[exec.utils.rcvr_adptr.nonmembers]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"></a></h5>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>As</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...)</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_value</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>),</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></code>, if that expression is valid, is not potentially throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>As</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...)</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>E</c-><c- o>&amp;&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>E</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>))</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_error</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>),</c-> <c- n>E</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-></code>, if that expression is valid, is not potentially throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>E</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>))</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_stopped</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_stopped</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>)</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-></code>, if that expression is valid, is not potentially throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)))</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c->
  <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>get_env</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>get_env_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>)</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression, <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>self</c-><c- p>))</c-></code>.</p>
     </ul>
    <li data-md>
     <p><i>Remarks:</i> The expression in the <code class="highlight"><c- k>noexcept</c-></code> clause is:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression, <code class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>())</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>self</c-><c- p>)))</c-></code>.</p>
     </ul>
   </ol>
   <h4 class="heading settled" data-level="11.10.2" id="spec-execution.snd_rec_utils.completion_sigs"><span class="secno">11.10.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> <b>[exec.utils.cmplsigs]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.completion_sigs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>completion_signatures</c-></code> is used to describe the completion signals of a receiver that
a sender may invoke. Its template argument list is a list of function types corresponding
to the signatures of the receiver’s completion signals.</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- k>class</c-> <c- nc>my_sender</c-> <c- p>{</c->
  <c- k>using</c-> <c- n>completion_signatures</c-> <c- o>=</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(),</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>float</c-><c- p>),</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>error_code</c-><c- p>),</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->

<c- c1>// Declares my_sender to be a sender that can complete by calling</c->
<c- c1>// one of the following for a receiver expression R:</c->
<c- c1>//    execution::set_value(R)</c->
<c- c1>//    execution::set_value(R, int{...}, float{...})</c->
<c- c1>//    execution::set_error(R, exception_ptr{...})</c->
<c- c1>//    execution::set_error(R, error_code{...})</c->
<c- c1>//    execution::set_stopped(R)</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>This section makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>completion</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
</pre>
     <ol>
      <li data-md>
       <p>A type <code class="highlight"><c- n>Fn</c-></code> satisfies <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i></code> if and only if it is a function type with one of the following forms:</p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>set_value_t</c-><c- p>(</c-><i><c- n>Vs</c-></i><c- p>...)</c-></code>, where <code class="highlight"><i><c- n>Vs</c-></i></code> is an arbitrary parameter pack.</p>
        <li data-md>
         <p><code class="highlight"><c- n>set_error_t</c-><c- p>(</c-><i><c- n>E</c-></i><c- p>)</c-></code>, where <code class="highlight"><i><c- n>E</c-></i></code> is an arbitrary type.</p>
        <li data-md>
         <p><code class="highlight"><c- n>set_stopped_t</c-><c- p>()</c-></code></p>
       </ul>
     </ol>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>S</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>E</c-><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
</pre>
     <ol start="2">
      <li data-md>
       <p>Let <code class="highlight"><c- n>Fns</c-><c- p>...</c-></code> be a template parameter pack of the arguments of the <code class="highlight"><c- n>completion_signatures</c-></code> instantiation named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code>, let <code class="highlight"><i><c- n>TagFns</c-></i></code> be a
template parameter pack of the function types in <code class="highlight"><c- n>Fns</c-></code> whose return types
are <code class="highlight"><c- n>Tag</c-></code>, and let <code class="highlight"><i><c- n>Ts</c-><i><sub><c- n>n</c-></sub></i></i></code> be a template parameter
pack of the function argument types in the <code class="highlight"><i><c- n>n</c-></i></code>-th type
in <code class="highlight"><i><c- n>TagFns</c-></i></code>. Then, given two variadic templates <code class="highlight"><i><c- n>Tuple</c-></i></code> and <code class="highlight"><i><c- n>Variant</c-></i></code>, the type <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>Tuple</c-></i><c- p>,</c-> <i><c- n>Variant</c-></i><c- o>></c-></code> names the type <code class="highlight"><i><c- n>Variant</c-></i><c- o>&lt;</c-><i><c- n>Tuple</c-></i><c- o>&lt;</c-><i><c- n>Ts</c-><i><sub><c- n>0</c-></sub></i></i><c- p>...</c-><c- o>></c-><c- p>,</c-> <i><c- n>Tuple</c-></i><c- o>&lt;</c-><i><c- n>Ts</c-><i><sub><c- n>1</c-></sub></i></i><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- p>...</c-> <i><c- n>Tuple</c-></i><c- o>&lt;</c-><i><c- n>Ts</c-><i><sub><c- n>m</c-><c- mf>-1</c-></sub></i></i><c- mf>.</c-><c- p>..</c-><c- o>>></c-></code>, where <code class="highlight"><i><c- n>m</c-></i></code> is the size of the parameter pack <code class="highlight"><i><c- n>TagFns</c-></i></code>.</p>
     </ol>
    <li data-md>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i><c- p>...</c-> <c- n>Fns</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>completion_signatures</c-> <c- p>{};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
  <c- k>using</c-> <c- n>value_types_of_t</c-> <c- o>=</c->
      <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
  <c- k>using</c-> <c- n>error_types_of_t</c-> <c- o>=</c->
      <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>type_identity_t</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>sends_stopped</c-> <c- o>=</c->
      <c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c->
        <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;></c-><c- p>,</c->
        <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>>></c-><c- p>;</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.10.3" id="spec-execution.snd_rec_utils.make_completion_sigs"><span class="secno">11.10.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>make_completion_signatures</c-></code> <b>[exec.utils.mkcmplsigs]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.make_completion_sigs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>make_completion_signatures</c-></code> is an alias template used to adapt the
completion signatures of a sender. It takes a sender, and environment, and
several other template arguments that apply modifications to the sender’s
completion signatures to generate a new instantiation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code>.</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- c1>// Given a sender S and an environment Env, adapt a S’s completion</c->
<c- c1>// signatures by lvalue-ref qualifying the values, adding an additional</c->
<c- c1>// exception_ptr error completion if its not already there, and leaving the</c->
<c- c1>// other signals alone.</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>using</c-> <c- n>my_set_value_t</c-> <c- o>=</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>add_lvalue_reference_t</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

<c- k>using</c-> <c- n>my_completion_signals</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>make_completion_signatures</c-><c- o>&lt;</c->
    <c- n>S</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
    <c- n>my_set_value_t</c-><c- o>></c-><c- p>;</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>This section makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>As</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c->
  <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i> <c- o>=</c->
    <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>Err</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c->
          <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-> <c- n>AddlSigs</c-> <c- o>=</c->
              <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetValue</c-> <c- o>=</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i><c- p>,</c->
          <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetError</c-> <c- o>=</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i><c- p>,</c->
          <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-> <c- n>SetStopped</c-> <c- o>=</c->
              <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
<c- k>using</c-> <c- n>make_completion_signatures</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- d>/* see below */</c-></i><c- o>></c-><c- p>;</c->
</pre>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- n>SetValue</c-></code> shall name an alias template such that for any template
parameter pack <code class="highlight"><c- n>As</c-><c- p>...</c-></code>, the type <code class="highlight"><c- n>SetValue</c-><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-></code> is either ill-formed
or else <code class="highlight"><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>SetValue</c-><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is satisfied.</p>
      <li data-md>
       <p><code class="highlight"><c- n>SetError</c-></code> shall name an alias template such that for any type <code class="highlight"><c- n>Err</c-></code>, <code class="highlight"><c- n>SetError</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> is either ill-formed or else <code class="highlight"><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>SetError</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is satisfied.</p>
     </ul>
     <p>Then:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> be a pack of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named
by <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code>.</p>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Es</c-><c- p>...</c-></code> be a pack of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><c- n>error_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code>, where <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i></code> is an
alias template such that <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></code> names <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;</c-><c- n>SetError</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>.</p>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Ss</c-></code> name the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code> if <code class="highlight"><c- n>sends_stopped</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">false</code>; otherwise, <code class="highlight"><c- n>SetStopped</c-></code>.</p>
     </ul>
     <p>Then:</p>
     <ol>
      <li data-md>
       <p>If any of the above types are ill-formed, then <code class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>AddlSigs</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <c- n>SetError</c-><c- p>,</c-> <c- n>SetStopped</c-><c- o>></c-></code> is ill-formed,</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>make_completion_signatures</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>AddlSigs</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <c- n>SetError</c-><c- p>,</c-> <c- n>SetStopped</c-><c- o>></c-></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Sigs</c-><c- p>...</c-><c- o>></c-></code> where <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> is the unique set of types in all the template arguments
of all the <code class="highlight"><c- n>completion_signatures</c-></code> instantiations in <code class="highlight"><c- p>[</c-><c- n>AddlSigs</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...,</c-> <c- n>Es</c-><c- p>...,</c-> <c- n>Ss</c-><c- p>]</c-></code>.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.11" id="spec-execution.contexts"><span class="secno">11.11. </span><span class="content">Execution contexts <b>[exec.ctx]</b></span><a class="self-link" href="#spec-execution.contexts"></a></h3>
   <ol>
    <li data-md>
     <p>This section specifies some execution contexts on which work can be scheduled.</p>
   </ol>
   <h4 class="heading settled" data-level="11.11.1" id="spec-execution.contexts.run_loop"><span class="secno">11.11.1. </span><span class="content"><code class="highlight"><c- n>run_loop</c-></code> <b>[exec.run_loop]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop"></a></h4>
   <ol>
    <li data-md>
     <p>A <code class="highlight"><c- n>run_loop</c-></code> is an execution context on which work can be scheduled. It maintains a simple, thread-safe first-in-first-out queue of work. Its <code class="highlight"><c- n>run</c-><c- p>()</c-></code> member function removes elements from the queue and executes them in a loop on whatever thread of execution calls <code class="highlight"><c- n>run</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p>A <code class="highlight"><c- n>run_loop</c-></code> instance has an associated <i>count</i> that corresponds to the number of work items that are in its queue. Additionally, a <code class="highlight"><c- n>run_loop</c-></code> has an associated <i>state</i> that can be one of <i>starting</i>, <i>running</i>, or <i>finishing</i>.</p>
    <li data-md>
     <p>Concurrent invocations of the member functions of <code class="highlight"><c- n>run_loop</c-></code>, other than <code class="highlight"><c- n>run</c-></code> and its destructor, do not introduce data races. The member functions <code class="highlight"><c- n>pop_front</c-></code>, <code class="highlight"><c- n>push_back</c-></code>, and <code class="highlight"><c- n>finish</c-></code> execute atomically.</p>
    <li data-md>
     <p>[<i>Note:</i> Implementations are encouraged to use an intrusive queue of operation states to hold the work units to make scheduling allocation-free. — <i>end note</i>]</p>
<pre class="highlight"><c- k>class</c-> <c- nc>run_loop</c-> <c- p>{</c->
  <c- c1>// [exec.run_loop.types] Associated types</c->
  <c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>struct</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>virtual</c-> <c- b>void</c-> <c- nf>execute</c-><c- p>()</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
    <c- n>run_loop</c-><c- o>*</c-> <c- n>loop_</c-><c- p>;</c->
    <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>next_</c-><c- p>;</c->
  <c- p>};</c->
  <c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-> <c- n>R</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- c1>// [exec.run_loop.members] Member functions:</c->
  <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>pop_front</c-><c- p>();</c-> <c- c1>// exposition only</c->
  <c- b>void</c-> <c- nf>push_back</c-><c- p>(</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-><c- p>);</c-> <c- c1>// exposition only</c->

 <c- k>public</c-><c- o>:</c->
  <c- c1>// [exec.run_loop.ctor] construct/copy/destroy</c->
  <c- n>run_loop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- n>run_loop</c-><c- p>(</c-><c- n>run_loop</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
  <c- o>~</c-><c- n>run_loop</c-><c- p>();</c->

  <c- c1>// [exec.run_loop.members] Member functions:</c->
  <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i> <c- n>get_scheduler</c-><c- p>();</c->
  <c- b>void</c-> <c- nf>run</c-><c- p>();</c->
  <c- b>void</c-> <c- nf>finish</c-><c- p>();</c->
<c- p>};</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="11.11.1.1" id="spec-execution.contexts.run_loop.types"><span class="secno">11.11.1.1. </span><span class="content">Associated types <b>[exec.run_loop.types]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.types"></a></h5>
<pre class="highlight"><c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> is an implementation defined type that models the <code class="highlight"><c- n>scheduler</c-></code> concept.</p>
    <li data-md>
     <p>Instances of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> remain valid until the end of the lifetime of the <code class="highlight"><c- n>run_loop</c-></code> instance from which they were obtained.</p>
    <li data-md>
     <p>Two instances of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> compare equal if and only if they were obtained from the same <code class="highlight"><c- n>run_loop</c-></code> instance.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>sch</c-></i></code> be an expression of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code>. The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><i><c- n>sch</c-></i><c- p>)</c-></code> is not potentially throwing and has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code>.</p>
   </ol>
<pre class="highlight"><c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code> is an implementation-defined type such that <code class="highlight"><c- n>sender_of</c-><c- o>&lt;</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- p>,</c-> <c- n>set_value_t</c-><c- p>()</c-><c- o>></c-></code> is <code class="highlight">true</code>. Additionally, the types reported by its <code class="highlight"><c- n>error_types</c-></code> associated type is <code class="highlight"><c- n>exception_ptr</c-></code>, and the value of its <code class="highlight"><c- n>sends_stopped</c-></code> trait is <code class="highlight">true</code>.</p>
    <li data-md>
     <p>An instance of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code> remains valid until the end of the lifetime of its associated <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code> instance.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>s</c-></i></code> be an expression of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code>, let <code class="highlight"><i><c- n>r</c-></i></code> be an expression such that <code class="highlight"><c- k>decltype</c-><c- p>(</c-><i><c- n>r</c-></i><c- p>)</c-></code> models the <code class="highlight"><c- n>receiver_of</c-></code> concept, and let <code class="highlight"><c- n>C</c-></code> be either <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>. Then:</p>
     <ul>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><i><c- n>s</c-></i><c- p>,</c-> <i><c- n>r</c-></i><c- p>)</c-></code> has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><i><c- n>r</c-></i><c- p>)</c-><c- o>>></c-></code> and is potentially throwing if and only if the initialiation of <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><i><c- n>r</c-></i><c- p>)</c-><c- o>></c-></code> from <code class="highlight"><i><c- n>r</c-></i></code> is potentially throwing.</p>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>C</c-><c- o>></c-><c- p>(</c-><c- n>get_attrs</c-><c- p>(</c-><i><c- n>s</c-></i><c- p>))</c-></code> is not potentially throwing, has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code>, and compares equal to the <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> instance from which <code class="highlight"><i><c- n>s</c-></i></code> was obtained.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-> <c- n>R</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>struct</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><i><c- n>R</c-></i><c- o>></c-></code> inherits unambiguously from <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i></code>.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>o</c-></i></code> be a non-<code class="highlight"><c- k>const</c-></code> lvalue of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>R</c-><c- o>></c-></code>, and let <code class="highlight"><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> be a non-<code class="highlight"><c- k>const</c-></code> lvalue reference to an instance of type <code class="highlight"><i><c- n>R</c-></i></code> that was initialized with the expression <code class="highlight"><i><c- n>r</c-></i></code> passed to the invocation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> that returned <code class="highlight"><i><c- n>o</c-></i></code>. Then:</p>
     <ul>
      <li data-md>
       <p>The object to which <code class="highlight"><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> refers remains valid for the lifetime of the object to which <code class="highlight"><i><c- n>o</c-></i></code> refers.</p>
      <li data-md>
       <p>The type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>R</c-><c- o>></c-></code> overrides <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>::</c-><c- n>execute</c-><c- p>()</c-></code> such that <code class="highlight"><i><c- n>o</c-></i><c- p>.</c-><c- n>execute</c-><c- p>()</c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>if</c-> <c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)).</c-><c- n>stop_requested</c-><c- p>())</c-> <c- p>{</c->
  <c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)));</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)));</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <i><c- n>o</c-></i><c- p>.</c-><c- n>loop_</c-><c- o>-></c-><c- n>push_back</c-><c- p>(</c-><c- o>&amp;</c-><i><c- n>o</c-></i><c- p>);</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)),</c-> <c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
</pre>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="11.11.1.2" id="spec-execution.contexts.run_loop.ctor"><span class="secno">11.11.1.2. </span><span class="content">Constructor and destructor <b>[exec.run_loop.ctor]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.ctor"></a></h5>
<pre class="highlight"><c- n>run_loop</c-><c- o>::</c-><c- n>run_loop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Postconditions:</i> <i>count</i> is <code class="highlight"><c- mi>0</c-></code> and <i>state</i> is <i>starting</i>.</p>
   </ol>
<pre class="highlight"><c- n>run_loop</c-><c- o>::~</c-><c- n>run_loop</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> If <i>count</i> is not <code class="highlight"><c- mi>0</c-></code> or if <i>state</i> is <i>running</i>, invokes <code class="highlight"><c- n>terminate</c-><c- p>()</c-></code>. Otherwise, has no effects.</p>
   </ol>
   <h5 class="heading settled" data-level="11.11.1.3" id="spec-execution.contexts.run_loop.members"><span class="secno">11.11.1.3. </span><span class="content">Member functions <b>[exec.run_loop.members]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.members"></a></h5>
<pre class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>run_loop</c-><c- o>::</c-><c- n>pop_front</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Blocks ([defns.block]) until one of the following conditions is <code class="highlight">true</code>:</p>
     <ul>
      <li data-md>
       <p><i>count</i> is <code class="highlight"><c- mi>0</c-></code> and <i>state</i> is <i>finishing</i>, in which case <code class="highlight"><c- n>pop_front</c-></code> returns <code class="highlight"><c- k>nullptr</c-></code>; or</p>
      <li data-md>
       <p><i>count</i> is greater than <code class="highlight"><c- mi>0</c-></code>, in which case an item is removed from the front of the queue, <i>count</i> is decremented by <code class="highlight"><c- mi>1</c-></code>, and the removed item is returned.</p>
     </ul>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::push_back</c-><c- p>(</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>item</c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Adds <code class="highlight"><c- n>item</c-></code> to the back of the queue and increments <i>count</i> by <code class="highlight"><c- mi>1</c-></code>.</p>
    <li data-md>
     <p><i>Synchronization:</i> This operation synchronizes with the <code class="highlight"><c- n>pop_front</c-></code> operation that obtains <code class="highlight"><c- n>item</c-></code>.</p>
   </ol>
<pre class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i> <c- n>run_loop</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> an instance of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> that can be used to schedule work onto this <code class="highlight"><c- n>run_loop</c-></code> instance.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::run</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
<pre class="highlight"><c- k>while</c-> <c- p>(</c-><c- k>auto</c-><c- o>*</c-> <c- n>op</c-> <c- o>=</c-> <c- n>pop_front</c-><c- p>())</c-> <c- p>{</c->
  <c- n>op</c-><c- o>-></c-><c- n>execute</c-><c- p>();</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p><i>Precondition:</i> <i>state</i> is <i>starting</i>.</p>
    <li data-md>
     <p><i>Postcondition:</i> <i>state</i> is <i>finishing</i>.</p>
    <li data-md>
     <p><i>Remarks:</i> While the loop is executing, <i>state</i> is <i>running</i>. When <i>state</i> changes, it does so without introducing data races.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::finish</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Changes <i>state</i> to <i>finishing</i>.</p>
    <li data-md>
     <p><i>Synchronization:</i> This operation synchronizes with all <code class="highlight"><c- n>pop_front</c-></code> operations on this object.</p>
   </ol>
   <h3 class="heading settled" data-level="11.12" id="spec-execution.coro_utils"><span class="secno">11.12. </span><span class="content">Coroutine utilities <b>[exec.coro_utils]</b></span><a class="self-link" href="#spec-execution.coro_utils"></a></h3>
   <h4 class="heading settled" data-level="11.12.1" id="spec-execution.coro_utils.as_awaitable"><span class="secno">11.12.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>as_awaitable</c-></code> <b>[exec.as_awaitable]</b></span><a class="self-link" href="#spec-execution.coro_utils.as_awaitable"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>as_awaitable</c-></code> is used to transform an object into one that is awaitable within a particular coroutine. This section makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>E</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c-> <c- k>typename</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-><c- p>;</c-> <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>P</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c->
    <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>ENV_OF</c-></i><c- p>(</c-><c- n>P</c-><c- p>)</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>sender_to</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-> <c- o>&amp;&amp;</c-> <c- c1>// see below</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>P</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>p</c-><c- p>.</c-><c- n>unhandled_stopped</c-><c- p>()</c-> <c- p>}</c-> <c- o>-></c-> <c- n>convertible_to</c-><c- o>&lt;</c-><c- n>coroutine_handle</c-><c- o>&lt;>></c-><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>P</c-><c- o>></c->
  <c- k>class</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>;</c->
</pre>
     <p>where <code class="highlight"><i><c- n>ENV_OF</c-></i><c- p>(</c-><c- n>P</c-><c- p>)</c-></code> names the type <code class="highlight"><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>P</c-><c- o>></c-></code> if that type
is well-formed, or <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i></code> otherwise.</p>
     <ol>
      <li data-md>
       <p>Alias template <i>single-sender-value-type</i> is defined as follows:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> would have the form <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, then <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is an alias for type <code class="highlight"><c- n>T</c-></code>.</p>
        <li data-md>
         <p>Otherwise, if <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> would have the form <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;>></c-></code> or <code class="highlight"><c- n>Variant</c-><c- o>&lt;></c-></code>, then <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is an alias for type <code class="highlight"><c- b>void</c-></code>.</p>
        <li data-md>
         <p>Otherwise, <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>E</c-><c- o>></c-></code> is ill-formed.</p>
       </ol>
      <li data-md>
       <p>The type <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- p>,</c-> <c- k>class</c-> <c- nc>P</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
<c- k>class</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>awaitable</c-></i> <c- p>{</c->
  <c- k>struct</c-> <c- nc>unit</c-> <c- p>{};</c->
  <c- k>using</c-> <c- n>value_t</c-> <c- o>=</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>ENV_OF</c-></i><c- p>(</c-><c- n>P</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
  <c- k>using</c-> <c- n>result_t</c-> <c- o>=</c-> <c- n>conditional_t</c-><c- o>&lt;</c-><c- n>is_void_v</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>></c-><c- p>,</c-> <c- n>unit</c-><c- p>,</c-> <c- n>value_t</c-><c- o>></c-><c- p>;</c->
  <c- k>struct</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>;</c->

  <c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>result_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>></c-> <c- n>result_</c-><c- p>{};</c->
  <c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-> <c- n>state_</c-><c- p>;</c->

 <c- k>public</c-><c- o>:</c->
  <i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>P</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>await_ready</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->
  <c- b>void</c-> <c- nf>await_suspend</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>P</c-><c- o>></c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>start</c-><c- p>(</c-><c- n>state_</c-><c- p>);</c-> <c- p>}</c->
  <c- n>value_t</c-> <c- nf>await_resume</c-><c- p>();</c->
<c- p>};</c->
</pre>
       <ol>
        <li data-md>
         <p><code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i> <c- p>{</c->
  <c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>result_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>>*</c-> <c- n>result_ptr_</c-><c- p>;</c->
  <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>P</c-><c- o>></c-> <c- n>continuation_</c-><c- p>;</c->
  <c- c1>// ... </c-><i><c- c1>see below</c-></i>
<c- p>};</c->
</pre>
         <p>Let <code class="highlight"><c- n>r</c-></code> be an rvalue expression of type <code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i></code>, let <code class="highlight"><c- n>cr</c-></code> be a <code class="highlight"><c- k>const</c-></code> lvalue that refers to <code class="highlight"><c- n>r</c-></code>, let <code class="highlight"><c- n>vs</c-><c- p>...</c-></code> be an arbitrary function parameter pack of types <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code>, and let <code class="highlight"><c- n>err</c-></code> be an arbitrary expression of type <code class="highlight"><c- n>Err</c-></code>. Then:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>result_t</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...</c-><c- o>></c-></code> is satisfied, the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is not potentially throwing and is equivalent to:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>r</c-><c- p>.</c-><c- n>result_ptr_</c-><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>1</c-><c- o>></c-><c- p>(</c-><c- n>vs</c-><c- p>...);</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>r</c-><c- p>.</c-><c- n>result_ptr_</c-><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
<c- n>r</c-><c- p>.</c-><c- n>continuation_</c-><c- p>.</c-><c- n>resume</c-><c- p>();</c->
</pre>
           <p>Otherwise, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is ill-formed.</p>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> is not potentially throwing and is equivalent to:</p>
<pre class="highlight"><c- n>r</c-><c- p>.</c-><c- n>result_ptr_</c-><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><i><c- n>AS_EXCEPT_PTR</c-></i><c- p>(</c-><c- n>err</c-><c- p>));</c->
<c- n>r</c-><c- p>.</c-><c- n>continuation_</c-><c- p>.</c-><c- n>resume</c-><c- p>();</c->
</pre>
           <p>where <code class="highlight"><i><c- n>AS_EXCEPT_PTR</c-></i><c- p>(</c-><c- n>err</c-><c- p>)</c-></code> is:</p>
           <ol>
            <li data-md>
             <p><code class="highlight"><c- n>err</c-></code> if <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> names the same type as <code class="highlight"><c- n>exception_ptr</c-></code>,</p>
            <li data-md>
             <p>Otherwise, <code class="highlight"><c- n>make_exception_ptr</c-><c- p>(</c-><c- n>system_error</c-><c- p>(</c-><c- n>err</c-><c- p>))</c-></code> if <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> names the same type as <code class="highlight"><c- n>error_code</c-></code>,</p>
            <li data-md>
             <p>Otherwise, <code class="highlight"><c- n>make_exception_ptr</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code>.</p>
           </ol>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> is not potentially throwing and is equivalent to <code class="highlight"><c- k>static_cast</c-><c- o>&lt;</c-><c- n>coroutine_handle</c-><c- o>&lt;>></c-><c- p>(</c-><c- n>r</c-><c- p>.</c-><c- n>continuation_</c-><c- p>.</c-><c- n>promise</c-><c- p>().</c-><c- n>unhandled_stopped</c-><c- p>()).</c-><c- n>resume</c-><c- p>()</c-></code>.</p>
          <li data-md>
           <p>For any expression <code class="highlight"><c- n>tag</c-></code> whose type satisfies <code class="highlight"><i><c- n>forwarding</c-><c- o>-</c-><c- n>query</c-></i></code> and for any pack of subexpressions <code class="highlight"><c- n>as</c-></code>, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <c- n>get_env</c-><c- p>(</c-><c- n>cr</c-><c- p>),</c-> <c- n>as</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>as_const</c-><c- p>(</c-><c- n>cr</c-><c- p>.</c-><c- n>continuation_</c-><c- p>.</c-><c- n>promise</c-><c- p>())),</c-> <c- n>as</c-><c- p>...)</c-></code> when that expression is well-formed.</p>
         </ol>
        <li data-md>
         <p><b><code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>::</c-><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>,</c-> <c- n>P</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-></code></b></p>
         <ul>
          <li data-md>
           <p><i>Effects:</i> initializes <code class="highlight"><c- n>state_</c-></code> with <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>S</c-><c- o>></c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>{</c-><c- o>&amp;</c-><c- n>result_</c-><c- p>,</c-> <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>P</c-><c- o>>::</c-><c- n>from_promise</c-><c- p>(</c-><c- n>p</c-><c- p>)})</c-></code>.</p>
         </ul>
        <li data-md>
         <p><b><code class="highlight"><c- n>value_t</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>::</c-><c- n>await_resume</c-><c- p>()</c-></code></b></p>
         <ul>
          <li data-md>
           <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><c- k>if</c-> <c- p>(</c-><c- n>result_</c-><c- p>.</c-><c- n>index</c-><c- p>())</c-> <c- o>==</c-> <c- mi>2</c-><c- p>)</c->
  <c- n>rethrow_exception</c-><c- p>(</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><c- n>result_</c-><c- p>));</c->
<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- o>!</c-><c- n>is_void_v</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>></c-><c- p>)</c->
  <c- k>return</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>&amp;&amp;></c-><c- p>(</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>1</c-><c- o>></c-><c- p>(</c-><c- n>result_</c-><c- p>));</c->
</pre>
         </ul>
       </ol>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>as_awaitable</c-></code> is a customization point object. For some subexpressions <code class="highlight"><c- n>e</c-></code> and <code class="highlight"><c- n>p</c-></code> where <code class="highlight"><c- n>p</c-></code> is an lvalue, <code class="highlight"><c- n>E</c-></code> names the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>e</c-><c- p>))</c-></code> and <code class="highlight"><c- n>P</c-></code> names the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>p</c-><c- p>))</c-></code>, <code class="highlight"><c- n>as_awaitable</c-><c- p>(</c-><c- n>e</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> is expression-equivalent to the following:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>as_awaitable</c-><c- p>,</c-> <c- n>e</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>A</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> is <code class="highlight">true</code>, where <code class="highlight"><c- n>A</c-></code> is the type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>e</c-></code> if <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>E</c-><c- o>></c-></code> is <code class="highlight">true</code>. <span class="wg21note">The condition is not <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>E</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> as that creates the potential for constraint recursion.</span></p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>{</c-><c- n>e</c-><c- p>,</c-> <c- n>p</c-><c- p>}</c-></code> if <code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>E</c-><c- p>,</c-> <c- n>P</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>e</c-></code>.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.12.2" id="spec-execution.coro_utils.with_awaitable_senders"><span class="secno">11.12.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> <b>[exec.with_awaitable_senders]</b></span><a class="self-link" href="#spec-execution.coro_utils.with_awaitable_senders"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>with_awaitable_senders</c-></code>, when used as the base class of a coroutine promise type, makes senders awaitable in that coroutine type.</p>
     <p>In addition, it provides a default implementation of <code class="highlight"><c- n>unhandled_stopped</c-><c- p>()</c-></code> such that if a sender completes by calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>, it is treated as if an uncatchable "stopped" exception were thrown from the <i>await-expression</i>. In practice, the coroutine is never resumed, and the <code class="highlight"><c- n>unhandled_stopped</c-></code> of the coroutine caller’s promise type is called.</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Promise</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>with_awaitable_senders</c-> <c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c->
      <c- k>requires</c-> <c- p>(</c-><c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- p>,</c-> <c- b>void</c-><c- o>></c-><c- p>)</c->
    <c- b>void</c-> <c- n>set_continuation</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c-> <c- n>h</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>continuation</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>continuation_</c-><c- p>;</c-> <c- p>}</c->

    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>unhandled_stopped</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- k>return</c-> <c- n>stopped_handler_</c-><c- p>(</c-><c- n>continuation_</c-><c- p>.</c-><c- n>address</c-><c- p>());</c->
    <c- p>}</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Value</c-><c- o>></c->
    <i><c- n>see</c-><c- o>-</c-><c- n>below</c-></i> <c- n>await_transform</c-><c- p>(</c-><c- n>Value</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>);</c->

   <c- k>private</c-><c- o>:</c->
    <c- c1>// exposition only</c->
    <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- k>static</c-> <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>default_unhandled_stopped</c-><c- p>(</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- n>terminate</c-><c- p>();</c->
    <c- p>}</c->
    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>continuation_</c-><c- p>{};</c-> <c- c1>// exposition only</c->
    <c- c1>// exposition only</c->
    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- p>(</c-><c- o>*</c-><c- n>stopped_handler_</c-><c- p>)(</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>default_unhandled_stopped</c-><c- p>;</c->
  <c- p>};</c->
</pre>
    <li data-md>
     <p><b><code class="highlight"><c- b>void</c-> <c- n>set_continuation</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c-> <c- n>h</c-><c- p>)</c-> <c- k>noexcept</c-></code></b></p>
     <ul>
      <li data-md>
       <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><c- n>continuation_</c-> <c- o>=</c-> <c- n>h</c-><c- p>;</c->
<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-> <c- k>requires</c-><c- p>(</c-><c- n>OtherPromise</c-><c- o>&amp;</c-> <c- n>other</c-><c- p>)</c-> <c- p>{</c-> <c- n>other</c-><c- p>.</c-><c- n>unhandled_stopped</c-><c- p>();</c-> <c- p>}</c-> <c- p>)</c-> <c- p>{</c->
  <c- n>stopped_handler_</c-> <c- o>=</c-> <c- p>[](</c-><c- b>void</c-><c- o>*</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- p>{</c->
    <c- k>return</c-> <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>>::</c-><c- n>from_address</c-><c- p>(</c-><c- n>p</c-><c- p>)</c->
      <c- p>.</c-><c- n>promise</c-><c- p>().</c-><c- n>unhandled_stopped</c-><c- p>();</c->
  <c- p>};</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- n>stopped_handler_</c-> <c- o>=</c-> <c- n>default_unhandled_stopped</c-><c- p>;</c->
<c- p>}</c->
</pre>
     </ul>
    <li data-md>
     <p><b><code class="highlight"><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>as_awaitable_t</c-><c- p>,</c-> <c- n>Value</c-><c- p>,</c-> <c- n>Promise</c-><c- o>&amp;></c-> <c- n>await_transform</c-><c- p>(</c-><c- n>Value</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>)</c-></code></b></p>
     <ul>
      <li data-md>
       <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><c- k>return</c-> <c- n>as_awaitable</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- n>Value</c-><c- o>&amp;&amp;></c-><c- p>(</c-><c- n>value</c-><c- p>),</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>&amp;></c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>));</c->
</pre>
     </ul>
   </ol>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="#algorithm">algorithm</a><span>, in § 3.2</span>
   <li><a href="#completion-schedulers">completion schedulers</a><span>, in § 4.5</span>
   <li><a href="#connect">connect</a><span>, in § 5.3</span>
   <li><a href="#execution-context">execution context</a><span>, in § 4.1</span>
   <li><a href="#multi-shot-sender">multi-shot sender</a><span>, in § 4.7</span>
   <li><a href="#operation-state">operation state</a><span>, in § 5.2</span>
   <li><a href="#pipeable">pipeable</a><span>, in § 4.13</span>
   <li><a href="#piped">piped</a><span>, in § 4.13</span>
   <li><a href="#query">query</a><span>, in § 3.2</span>
   <li><a href="#receiver">receiver</a><span>, in § 5.1</span>
   <li><a href="#receiver-contract">receiver contract</a><span>, in § 5.1</span>
   <li><a href="#scheduler">scheduler</a><span>, in § 4.2</span>
   <li><a href="#send">send</a><span>, in § 4.3</span>
   <li><a href="#sender">sender</a><span>, in § 4.3</span>
   <li><a href="#sender-adaptor">sender adaptor</a><span>, in § 4.21</span>
   <li><a href="#sender-algorithms">sender algorithms</a><span>, in § 4.4</span>
   <li><a href="#sender-consumer">sender consumer</a><span>, in § 4.22</span>
   <li><a href="#sender-factory">sender factory</a><span>, in § 4.20</span>
   <li><a href="#single-shot-sender">single-shot sender</a><span>, in § 4.7</span>
   <li><a href="#start">start</a><span>, in § 4.21</span>
   <li><a href="#strictly-lazy-submission">Strictly lazy submission</a><span>, in § 5.5</span>
  </ul>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-cwg2517">[CWG2517]
   <dd>Richard Smith. <a href="https://wg21.link/cwg2517"><cite>Useless restriction on use of parameter in constraint-expression</cite></a>. 10 June 2019. open. URL: <a href="https://wg21.link/cwg2517">https://wg21.link/cwg2517</a>
   <dt id="biblio-hpx">[HPX]
   <dd>Hartmut Kaiser; et al. <a href="https://doi.org/10.21105/joss.02352"><cite>HPX - The C++ Standard Library for Parallelism and Concurrency</cite></a>. URL: <a href="https://doi.org/10.21105/joss.02352">https://doi.org/10.21105/joss.02352</a>
   <dt id="biblio-n4885">[N4885]
   <dd>Thomas Köppe. <a href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. 17 March 2021. URL: <a href="https://wg21.link/n4885">https://wg21.link/n4885</a>
   <dt id="biblio-p0443r14">[P0443R14]
   <dd>Jared Hoberock, Michael Garland, Chris Kohlhoff, Chris Mysen, H. Carter Edwards, Gordon Brown, D. S. Hollman. <a href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>. 15 September 2020. URL: <a href="https://wg21.link/p0443r14">https://wg21.link/p0443r14</a>
   <dt id="biblio-p0981r0">[P0981R0]
   <dd>Richard Smith, Gor Nishanov. <a href="https://wg21.link/p0981r0"><cite>Halo: coroutine Heap Allocation eLision Optimization: the joint response</cite></a>. 18 March 2018. URL: <a href="https://wg21.link/p0981r0">https://wg21.link/p0981r0</a>
   <dt id="biblio-p1056r1">[P1056R1]
   <dd>Lewis Baker, Gor Nishanov. <a href="https://wg21.link/p1056r1"><cite>Add lazy coroutine (coroutine task) type</cite></a>. 7 October 2018. URL: <a href="https://wg21.link/p1056r1">https://wg21.link/p1056r1</a>
   <dt id="biblio-p1895r0">[P1895R0]
   <dd>Lewis Baker, Eric Niebler, Kirk Shoop. <a href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>. 8 October 2019. URL: <a href="https://wg21.link/p1895r0">https://wg21.link/p1895r0</a>
   <dt id="biblio-p1897r3">[P1897R3]
   <dd>Lee Howes. <a href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>. 16 May 2020. URL: <a href="https://wg21.link/p1897r3">https://wg21.link/p1897r3</a>
   <dt id="biblio-p2175r0">[P2175R0]
   <dd>Lewis Baker. <a href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>. 15 December 2020. URL: <a href="https://wg21.link/p2175r0">https://wg21.link/p2175r0</a>
   <dt id="biblio-p2280r2">[P2280r2]
   <dd>Barry Revzin. <a href="https://wg21.link/p2280r2"><cite>Using unknown references in constant expressions</cite></a>. 15 May 2021. URL: <a href="https://wg21.link/p2280r2">https://wg21.link/p2280r2</a>
  </dl>
  <aside class="dfn-panel" data-for="algorithm">
   <b><a href="#algorithm">#algorithm</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-algorithm">4.20. User-facing sender factories</a>
    <li><a href="#ref-for-algorithm①">4.21. User-facing sender adaptors</a>
    <li><a href="#ref-for-algorithm②">4.22. User-facing sender consumers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="send">
   <b><a href="#send">#send</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-send">4.5.1. execution::get_completion_scheduler</a>
    <li><a href="#ref-for-send①">4.9. Senders are joinable</a>
    <li><a href="#ref-for-send②">4.20.2. execution::just</a>
    <li><a href="#ref-for-send③">4.20.3. execution::transfer_just</a>
    <li><a href="#ref-for-send④">4.21.2. execution::then</a>
    <li><a href="#ref-for-send⑤">4.21.4. execution::let_*</a>
    <li><a href="#ref-for-send⑥">5.8. All senders are typed</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-algorithms">
   <b><a href="#sender-algorithms">#sender-algorithms</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-algorithms">4.3. Senders describe work</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="completion-schedulers">
   <b><a href="#completion-schedulers">#completion-schedulers</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-completion-schedulers">4.5.1. execution::get_completion_scheduler</a>
    <li><a href="#ref-for-completion-schedulers①">4.6. Execution context transitions are explicit</a>
    <li><a href="#ref-for-completion-schedulers②">4.9. Senders are joinable</a>
    <li><a href="#ref-for-completion-schedulers③">4.20.2. execution::just</a>
    <li><a href="#ref-for-completion-schedulers④">4.20.3. execution::transfer_just</a>
    <li><a href="#ref-for-completion-schedulers⑤">4.20.4. execution::just_error</a>
    <li><a href="#ref-for-completion-schedulers⑥">4.20.5. execution::just_stopped</a>
    <li><a href="#ref-for-completion-schedulers⑦">4.21.5. execution::on</a>
    <li><a href="#ref-for-completion-schedulers⑧">4.21.11. execution::when_all</a>
    <li><a href="#ref-for-completion-schedulers⑨">4.21.12. execution::transfer_when_all</a>
    <li><a href="#ref-for-completion-schedulers①⓪">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-factory">
   <b><a href="#sender-factory">#sender-factory</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-factory">4.4. Senders are composable through sender algorithms</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-adaptor">
   <b><a href="#sender-adaptor">#sender-adaptor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-adaptor">4.4. Senders are composable through sender algorithms</a>
    <li><a href="#ref-for-sender-adaptor①">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-consumer">
   <b><a href="#sender-consumer">#sender-consumer</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-consumer">4.4. Senders are composable through sender algorithms</a>
    <li><a href="#ref-for-sender-consumer①">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="receiver-contract">
   <b><a href="#receiver-contract">#receiver-contract</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-receiver-contract">5.3. execution::connect</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="connect">
   <b><a href="#connect">#connect</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-connect">4.21.13. execution::ensure_started</a>
   </ul>
  </aside>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script>