<!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>P0260R10: C++ Concurrent Queues</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;
			border-bottom: 3px solid transparent;
			margin-bottom: -3px;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom-color: #054572;
			border-bottom-color: var(--toclink-underline);
		}
		#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 44bea8ebb, updated Thu Sep 7 16:28:26 2023 -0700" name="generator">
  <link href="http://wg21.link/P0260R10" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="5f28ea0618efc0475b1d2b27a45cced83beeaba6" name="document-revision">
<style>/* Boilerplate: 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;
}

@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}
</style>
<style>/* Boilerplate: 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;
}

@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; }
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: style-issues */
a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: 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%;
}
.example > a.self-link,
.note > a.self-link,
.issue > a.self-link {
    /* These blocks are overflow:auto, so positioning outside
       doesn't work. */
    left: auto;
    right: 0;
}
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>/* Boilerplate: 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 */


@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">P0260R10<br>C++ Concurrent Queues</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="2024-06-26">2024-06-26</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P0260R10">http://wg21.link/P0260R10</a>
     <dt class="editor">Authors:
     <dd class="editor p-author h-card vcard"><span class="p-name fn">Lawrence Crowl</span>
     <dd class="editor p-author h-card vcard"><span class="p-name fn">Chris Mysen</span>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:dv@vollmann.ch">Detlef Vollmann</a>
     <dd class="editor p-author h-card vcard"><span class="p-name fn">Gor Nishanov</span>
     <dt>Audience:
     <dd>SG1, LEWG
     <dt>Project:
     <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
     <dt>Source:
     <dd><a href="https://gitlab.com/cppzs/papers/-/blob/main/source/P0260R9.bs">gitlab.com/cppzs/papers/-/blob/main/source/P0260R10.bs</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>Concurrent queues are a fundamental structuring tool for concurrent

        programs. We propose concurrent queue concepts and a concrete
        implementation.</p>
  </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="#Acknowledgments"><span class="secno">1</span> <span class="content">Acknowledgments</span></a>
    <li>
     <a href="#Revision"><span class="secno">2</span> <span class="content">Revision History</span></a>
     <ol class="toc">
      <li>
       <a href="#DiscussionPoints"><span class="secno">2.1</span> <span class="content">Discussion Points For This Revision</span></a>
       <ol class="toc">
        <li><a href="#DiscussionPointsSg1"><span class="secno">2.1.1</span> <span class="content">Discussion Points For SG1</span></a>
        <li><a href="#DiscussionPointsLewg"><span class="secno">2.1.2</span> <span class="content">Discussion Points For LEWG</span></a>
       </ol>
     </ol>
    <li><a href="#Introduction"><span class="secno">3</span> <span class="content">Introduction</span></a>
    <li>
     <a href="#PriorArt"><span class="secno">4</span> <span class="content">Existing Practice</span></a>
     <ol class="toc">
      <li><a href="#PriorArtConcept"><span class="secno">4.1</span> <span class="content">Concept of a Bounded Queue</span></a>
      <li>
       <a href="#PriorArtCpp"><span class="secno">4.2</span> <span class="content">Bounded Queues with C++ Interface</span></a>
       <ol class="toc">
        <li><a href="#QLiterature"><span class="secno">4.2.1</span> <span class="content">Literature</span></a>
        <li><a href="#QBoost"><span class="secno">4.2.2</span> <span class="content">Boost</span></a>
        <li><a href="#QTBB"><span class="secno">4.2.3</span> <span class="content">TBB</span></a>
       </ol>
     </ol>
    <li>
     <a href="#Conceptual"><span class="secno">5</span> <span class="content">Conceptual Interface</span></a>
     <ol class="toc">
      <li><a href="#error_class"><span class="secno">5.1</span> <span class="content">Error Class</span></a>
      <li><a href="#basic_operations"><span class="secno">5.2</span> <span class="content">Basic Operations</span></a>
      <li><a href="#async"><span class="secno">5.3</span> <span class="content">Asynchronous Operations</span></a>
      <li><a href="#non_waiting"><span class="secno">5.4</span> <span class="content">Non-Waiting Operations</span></a>
      <li><a href="#closed_queues"><span class="secno">5.5</span> <span class="content">Closed Queues</span></a>
      <li><a href="#element_requirements"><span class="secno">5.6</span> <span class="content">Element Type Requirements</span></a>
      <li><a href="#exception_handling"><span class="secno">5.7</span> <span class="content">Exception Handling</span></a>
     </ol>
    <li><a href="#Concrete"><span class="secno">6</span> <span class="content">Concrete Queues</span></a>
    <li>
     <a href="#wording"><span class="secno">7</span> <span class="content">Proposed Wording</span></a>
     <ol class="toc">
      <li>
       <a href="#q-wording"><span class="secno">7.1</span> <span class="content">Concurrent Queues</span></a>
       <ol class="toc">
        <li><a href="#q-general"><span class="secno">7.1.1</span> <span class="content">General</span></a>
        <li><a href="#q-synopsis"><span class="secno">7.1.2</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>experimental</c-><c- o>/</c-><c- n>conqueue</c-><c- o>></c-></code> synopsis</span></a>
        <li><a href="#error-reporting"><span class="secno">7.1.3</span> <span class="content">Error reporting</span></a>
        <li><a href="#conqueue-error"><span class="secno">7.1.4</span> <span class="content">Class <code class="highlight"><c- n>conqueue_error</c-></code></span></a>
        <li><a href="#wording-base-concept"><span class="secno">7.1.5</span> <span class="content">Basic Concurrent Queue Concept</span></a>
        <li><a href="#wording-concurrent-concept"><span class="secno">7.1.6</span> <span class="content">Concurrent Queue Concept</span></a>
        <li><a href="#wording-async-concept"><span class="secno">7.1.7</span> <span class="content">Asynchronous Queue Concept</span></a>
        <li>
         <a href="#wording-bqueue"><span class="secno">7.1.8</span> <span class="content">Class template <code class="highlight"><c- n>bounded_queue</c-></code></span></a>
         <ol class="toc">
          <li><a href="#bq-general"><span class="secno">7.1.8.1</span> <span class="content">General</span></a>
          <li><a href="#bq-ctor"><span class="secno">7.1.8.2</span> <span class="content">Constructor</span></a>
          <li><a href="#bq-modifiers"><span class="secno">7.1.8.3</span> <span class="content">Modifiers</span></a>
         </ol>
       </ol>
     </ol>
    <li><a href="#RevisionOld"><span class="secno">8</span> <span class="content">Old Revision History</span></a>
    <li><a href="#Implementation"><span class="secno">9</span> <span class="content">Implementation</span></a>
    <li>
     <a href="#Historic"><span class="secno">10</span> <span class="content">Historic Contents</span></a>
     <ol class="toc">
      <li>
       <a href="#Abandoned"><span class="secno">10.1</span> <span class="content">Abandoned Interfaces</span></a>
       <ol class="toc">
        <li><a href="#reopen"><span class="secno">10.1.1</span> <span class="content">Re-opening a Queue</span></a>
        <li><a href="#non_block"><span class="secno">10.1.2</span> <span class="content">Non-Blocking Operations</span></a>
        <li><a href="#push_front"><span class="secno">10.1.3</span> <span class="content">Push Front Operations</span></a>
        <li><a href="#queue_names"><span class="secno">10.1.4</span> <span class="content">Queue Names</span></a>
        <li><a href="#lock_free_buffer_queue"><span class="secno">10.1.5</span> <span class="content">Lock-Free Buffer Queue</span></a>
        <li><a href="#storage_iterators"><span class="secno">10.1.6</span> <span class="content">Storage Iterators</span></a>
        <li><a href="#empty_full"><span class="secno">10.1.7</span> <span class="content">Empty and Full Queues</span></a>
        <li><a href="#queue_order"><span class="secno">10.1.8</span> <span class="content">Queue Ordering</span></a>
        <li><a href="#lock_free"><span class="secno">10.1.9</span> <span class="content">Lock-Free Implementations</span></a>
       </ol>
      <li>
       <a href="#Tools"><span class="secno">10.2</span> <span class="content">Abandoned Additional Conceptual Tools</span></a>
       <ol class="toc">
        <li><a href="#front_back"><span class="secno">10.2.1</span> <span class="content">Fronts and Backs</span></a>
        <li><a href="#streaming_iterators"><span class="secno">10.2.2</span> <span class="content">Streaming Iterators</span></a>
        <li><a href="#Binary"><span class="secno">10.2.3</span> <span class="content">Binary Interfaces</span></a>
        <li><a href="#Managed"><span class="secno">10.2.4</span> <span class="content">Managed Indirection</span></a>
       </ol>
      <li><a href="#tryPushFailMove"><span class="secno">10.3</span> <span class="content"><code class="highlight"><c- n>try_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>)</c-></code></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="Acknowledgments"><span class="secno">1. </span><span class="content">Acknowledgments</span><a class="self-link" href="#Acknowledgments"></a></h2>
   <p>Thanks to David Goldblatt for his help with the wording!</p>
   <h2 class="heading settled" data-level="2" id="Revision"><span class="secno">2. </span><span class="content">Revision History</span><a class="self-link" href="#Revision"></a></h2>
   <p>This paper revises P0260R9 - 2024-05-19 as follows.</p>
   <ul>
    <li data-md>
     <p>Implement feedback from SG1 in St. Louis:</p>
    <li data-md>
     <p>Split concept into three</p>
    <li data-md>
     <p>Require <code class="highlight"><c- n>try_</c-><c- o>*</c-></code> to be lockfree (w/ error code <code class="highlight"><c- n>busy</c-></code>)</p>
    <li data-md>
     <p>Drop <code class="highlight"><c- n>is_always_lock_free</c-></code></p>
    <li data-md>
     <p>Drop <code class="highlight"><c- n>capacity</c-><c- p>()</c-></code></p>
    <li data-md>
     <p>Removed discussion points forSG1</p>
    <li data-md>
     <p>Removed TS ship vehicle</p>
    <li data-md>
     <p>General cleanup in the design part</p>
   </ul>
   <p>P0260R9 revises P0260R8 - 2024-03-08 as follows.</p>
   <ul>
    <li data-md>
     <p>Added more wording</p>
    <li data-md>
     <p>Fixed <code class="highlight"><c- n>capacity</c-></code></p>
    <li data-md>
     <p>Changed push/pop wording to use "strongly happens before"</p>
    <li data-md>
     <p>Added discussion points</p>
    <li data-md>
     <p>Removed paragraph about ctors/dtors returning on same thread</p>
    <li data-md>
     <p><code class="highlight"><c- n>try_</c-><c- o>*</c-></code> now never blocks (even for contention on
internal synchronization)</p>
    <li data-md>
     <p>Wording for spurious failures of <code class="highlight"><c- n>try_</c-><c- o>*</c-></code></p>
    <li data-md>
     <p>The constructors for <code class="highlight"><c- n>bounded_queue</c-></code> that pre-fill the
queue have been removed</p>
    <li data-md>
     <p>Reference to P3282 added</p>
    <li data-md>
     <p>Moved discussion about <code class="highlight"><c- n>try_push</c-><c- p>(</c-><c- n>T</c-> <c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-> <c- o>&amp;</c-><c- p>)</c-></code> to historic contents.</p>
   </ul>
   <p>P0260R8 revises P0260R7 - 2023-06-15 as follows.</p>
   <ul>
    <li data-md>
     <p>Restructured document</p>
    <li data-md>
     <p>Fix typos</p>
    <li data-md>
     <p>Implement LEWG feedback to derive conqueue_errc from system_error</p>
    <li data-md>
     <p>Implement LEWG feedback to add range constructor and go back to
InputIterator</p>
    <li data-md>
     <p>size_t capacity() added</p>
    <li data-md>
     <p>Added TBB concurrent_bounded_queue as existing practice</p>
    <li data-md>
     <p>Moved discussion about pop() interface to separate paper</p>
    <li data-md>
     <p>reintegrated P1958 <code class="highlight"><c- n>buffer_queue</c-></code></p>
    <li data-md>
     <p>Renamed <code class="highlight"><c- n>buffer_queue</c-></code> to <code class="highlight"><c- n>bounded_queue</c-></code></p>
    <li data-md>
     <p>Added proposed wording (incomplete)</p>
    <li data-md>
     <p>Updated TS questions</p>
   </ul>
   <p>Older revision history was moved to <a href="#RevisionOld">after the proposed wording</a>.</p>
   <h3 class="heading settled" data-level="2.1" id="DiscussionPoints"><span class="secno">2.1. </span><span class="content">Discussion Points For This Revision</span><a class="self-link" href="#DiscussionPoints"></a></h3>
   <h4 class="heading settled" data-level="2.1.1" id="DiscussionPointsSg1"><span class="secno">2.1.1. </span><span class="content">Discussion Points For SG1</span><a class="self-link" href="#DiscussionPointsSg1"></a></h4>
   <h4 class="heading settled" data-level="2.1.2" id="DiscussionPointsLewg"><span class="secno">2.1.2. </span><span class="content">Discussion Points For LEWG</span><a class="self-link" href="#DiscussionPointsLewg"></a></h4>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>pop</c-><c- p>()</c-></code> return: <code class="highlight"><c- n>optional</c-></code> or <code class="highlight"><c- n>expected</c-></code>?
  Other operations with <code class="highlight"><c- n>error_code</c-></code>: return <code class="highlight"><c- n>expected</c-></code>?
  This is <a data-link-type="biblio" href="https://wg21.link/P2921"><cite>Exploring std::expected based API alternatives for buffer_queue (P2921)</cite></a>.</p>
    <li data-md>
     <p>Are value initializing constructors required?</p>
    <li data-md>
     <p>A concurrent queue is not a container.
  Which of the requirements in <code class="highlight"><c- p>[</c-><c- n>container</c-><c- p>.</c-><c- n>reqmts</c-><c- p>]</c-></code> should be met anyways
  (<code class="highlight"><c- n>value_type</c-></code>, <code class="highlight"><c- n>reference</c-></code>, <code class="highlight"><c- n>get_allocator</c-><c- p>()</c-></code>, ...)?</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_</c-><c- o>*</c-></code>: Is closed condition a stop condition or a special return
  or an error?</p>
   </ul>
   <h2 class="heading settled" data-level="3" id="Introduction"><span class="secno">3. </span><span class="content">Introduction</span><a class="self-link" href="#Introduction"></a></h2>
   <p>Queues provide a mechanism for communicating data between components of
a system.</p>
   <p>The existing <code class="highlight"><c- n>deque</c-></code> in the standard library is an inherently sequential
data structure. Its reference-returning element access operations cannot
synchronize access to those elements with other queue operations. So,
concurrent pushes and pops on queues require a different interface to
the queue structure.</p>
   <p>Moreover, concurrency adds a new dimension for performance and
semantics. Different queue implementation must trade off uncontended
operation cost, contended operation cost, and element order guarantees.
Some of these trade-offs will necessarily result in semantics weaker
than a serial queue.</p>
   <p>Concurrent queues come in a several different flavours, e.g.</p>
   <ul>
    <li data-md>
     <p>bounded vs. unbounded</p>
    <li data-md>
     <p>blocking vs. overwriting</p>
    <li data-md>
     <p>single-ended vs. multi-ended</p>
    <li data-md>
     <p>strict FIFO ordering vs. priority based ordering</p>
   </ul>
   <p>The syntactic concepts proposed here should be valid for all of these
flavours, while the concrete semantics might differ.</p>
   <h2 class="heading settled" data-level="4" id="PriorArt"><span class="secno">4. </span><span class="content">Existing Practice</span><a class="self-link" href="#PriorArt"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="PriorArtConcept"><span class="secno">4.1. </span><span class="content">Concept of a Bounded Queue</span><a class="self-link" href="#PriorArtConcept"></a></h3>
   <p>The basic concept of a bounded queue with potentially blocking push and
pop operations is very old and widely used. It’s generally provided as
an operating system level facility, like other concurrency primitives.</p>
   <p>POSIX 2001 has <code class="highlight"><c- n>mq</c-></code> message queues (with priorities and timeout).</p>
   <p>FreeRTOS, Mbed, vxWorks provide bounded queues.</p>
   <h3 class="heading settled" data-level="4.2" id="PriorArtCpp"><span class="secno">4.2. </span><span class="content">Bounded Queues with C++ Interface</span><a class="self-link" href="#PriorArtCpp"></a></h3>
   <h4 class="heading settled" data-level="4.2.1" id="QLiterature"><span class="secno">4.2.1. </span><span class="content">Literature</span><a class="self-link" href="#QLiterature"></a></h4>
   <p>The first concurrent queue I’ve seen was in <a data-biblio-display="index" data-link-type="biblio" href="#biblio-hughes97" title="Object-Oriented Multithreading Using C++">[Hughes97]</a>.
It was full of bugs and as such shows what will go wrong if
C++ doesn’t provide a standard queue.
It’s unbounded.</p>
   <p>Anthony Williams provided a queue in <a data-link-type="biblio" href="#biblio-williams17"><cite>C++ Concurrency in Action</cite></a>.
It’s unbounded.</p>
   <h4 class="heading settled" data-level="4.2.2" id="QBoost"><span class="secno">4.2.2. </span><span class="content">Boost</span><a class="self-link" href="#QBoost"></a></h4>
   <p>Boost has a number of queues, as official library and as example uses
of synchronization primitives.</p>
   <p><a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/interprocess/message_queue_t.html"><cite>Boost Message Queue</cite></a> only transfers bytes, not objects.  It’s bounded.</p>
   <p><a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/queue.html"><cite>Boost Lock-Free Queue</cite></a> and <a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/spsc_queue.html"><cite>Boost Lock-Free SPSC Queue</cite></a> have only non-blocking operations. <a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/queue.html"><cite>Boost Lock-Free Queue</cite></a> is bounded or unbounded, <a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/spsc_queue.html"><cite>Boost Lock-Free SPSC Queue</cite></a> is bounded.</p>
   <p><a data-link-type="biblio" href="https://www.boost.org/doc/libs/1_85_0/doc/html/thread/sds.html"><cite>Boost Synchronized Queue</cite></a> is an implementation of an early version of this proposal.</p>
   <h4 class="heading settled" data-level="4.2.3" id="QTBB"><span class="secno">4.2.3. </span><span class="content">TBB</span><a class="self-link" href="#QTBB"></a></h4>
   <p>TBB has <code class="highlight"><c- n>concurrent_bounded_queue</c-></code> (<a data-link-type="biblio" href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_bounded_queue_cls.html"><cite>TBB Bounded Queue</cite></a>) and an unbounded version <code class="highlight"><c- n>concurrent_queue</c-></code> <a data-link-type="biblio" href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_queue_cls.html"><cite>TBB Unbounded Queue</cite></a>.</p>
   <h2 class="heading settled" data-level="5" id="Conceptual"><span class="secno">5. </span><span class="content">Conceptual Interface</span><a class="self-link" href="#Conceptual"></a></h2>
   <p>We provide basic queue operations, and then extend those operations to
cover other important use cases.</p>
   <p>Due to performance issues, the conceptual interface is split
into three separate interfaces.
The <code class="highlight"><c- n>basic_concurrent_queue</c-></code> concept provides the interface <code class="highlight"><c- n>push</c-></code> and <code class="highlight"><c- n>pop</c-></code> and closing the queue.
The <code class="highlight"><c- n>concurrent_queue</c-></code> concept is based on <code class="highlight"><c- n>basic_concurrent_queue</c-></code> and provides the additional interface <code class="highlight"><c- n>try_push</c-></code> and <code class="highlight"><c- n>try_pop</c-></code>.
The <code class="highlight"><c- n>async_concurrent_queue</c-></code> concept is also based on <code class="highlight"><c- n>basic_concurrent_queue</c-></code> provides the additional interface <code class="highlight"><c- n>async_push</c-></code> and <code class="highlight"><c- n>async_pop</c-></code>.</p>
   <p>The concrete queue <code class="highlight"><c- n>bounded_queue</c-></code> models all these concepts.</p>
   <h3 class="heading settled" data-level="5.1" id="error_class"><span class="secno">5.1. </span><span class="content">Error Class</span><a class="self-link" href="#error_class"></a></h3>
   <p>By analogy with how <code class="highlight"><c- n>future</c-></code> defines their errors, we introduce <code class="highlight"><c- n>conqueue_errc</c-></code> enum and <code class="highlight"><c- n>conqueue_error</c-></code>:</p>
<pre class="language-c++ highlight"><c- k>enum</c-> <c- n>class</c-> <c- n>conqueue_errc</c-> <c- p>{</c-> <c- n>empty</c-><c- p>,</c-> <c- n>full</c-><c- p>,</c-> <c- n>closed</c-><c- p>,</c-> <c- n>busy</c-> <c- p>};</c->

<c- k>const</c-> <c- n>error_category</c-><c- o>&amp;</c-> <c- nf>conqueue_category</c-><c- p>()</c-> <c- n>noexcept</c-><c- p>;</c->

<c- n>class</c-> <c- n>conqueue_error</c-> <c- o>:</c-> <c- n>public</c-> <c- n>system_error</c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="5.2" id="basic_operations"><span class="secno">5.2. </span><span class="content">Basic Operations</span><a class="self-link" href="#basic_operations"></a></h3>
   <p>The essential solution to the problem of concurrent queuing is to shift
to value-based operations, rather than reference-based operations.</p>
   <p>The basic operations are:</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>queue::push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>);</c->
<c- b>void</c-> <c- nf>queue::push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>);</c->
<c- b>bool</c-> <c- nf>queue::push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
<c- b>bool</c-> <c- nf>queue::push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
</pre>
   <p>Pushes <code class="highlight"><c- n>x</c-></code> onto the queue via copy or move construction (and possibly blocks).
The first
version throws <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code> if the
queue is closed. The second version returns <code class="highlight">true</code> on success, and <code class="highlight">false</code> and sets <code class="highlight"><c- n>ec</c-></code> to <code class="highlight"><c- n>error_code</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code> if the
queue is closed.</p>
<pre class="language-c++ highlight"><c- n>T</c-> <c- nf>queue::pop</c-><c- p>();</c->
<c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>queue</c-><c- o>::</c-><c- n>pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
</pre>
   <p>Pops a value from the queue via move construction into the return value.
The first version throws <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code> if
the queue is empty and closed; the second version, if the queue is empty
and closed, returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>nullopt</c-></code> and sets <code class="highlight"><c- n>ec</c-></code> to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code>. If queue is empty and open,
the operation blocks until an element is available.</p>
   <p>The exploration of different version of error reporting was moved to a
separate paper <a data-biblio-display="direct" data-link-type="biblio" href="https://wg21.link/p2921r0" title="Exploring std::expected based API alternatives for buffer_queue">[P2921R0]</a>.</p>
   <h3 class="heading settled" data-level="5.3" id="async"><span class="secno">5.3. </span><span class="content">Asynchronous Operations</span><a class="self-link" href="#async"></a></h3>
<pre class="language-c++ highlight"><c- n>sender</c-> <c- k>auto</c-> <c- n>queue</c-><c- o>::</c-><c- n>async_push</c-><c- p>(</c-><c- n>T</c-> <c- n>x</c-><c- p>);</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>queue</c-><c- o>::</c-><c- n>async_pop</c-><c- p>();</c->
</pre>
   <p>These operations return a sender that will push or pop the element.
Senders must support cancellation and if the receiver is currently
waiting on a push or pop operation and no longer interested in
performing the operation, it should be removed from any waiting
queues, if any, and be completed with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>.</p>
   <h3 class="heading settled" data-level="5.4" id="non_waiting"><span class="secno">5.4. </span><span class="content">Non-Waiting Operations</span><a class="self-link" href="#non_waiting"></a></h3>
   <p>Waiting on a full or empty queue can take a while, which has an
opportunity cost. Avoiding that wait enables algorithms to avoid queuing
speculative work when a queue is full, to do other work rather than wait
for a push on a full queue, and to do other work rather than wait for a
pop on an empty queue.</p>
<pre class="language-c++ highlight"><c- b>bool</c-> <c- nf>queue::try_push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
<c- b>bool</c-> <c- nf>queue::try_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
</pre>
   <p>If the queue is full or closed, returns <code class="highlight">false</code> and sets the
respective status in the <code class="highlight"><c- n>ec</c-></code>. Otherwise, push the value onto the
queue via copy or move construction and returns <code class="highlight">true</code>.</p>
<pre class="language-c++ highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>queue</c-><c- o>::</c-><c- n>try_pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
</pre>
   <p>If the queue is empty, returns <code class="highlight"><c- n>nullopt</c-></code> and set ec to <code class="highlight"><c- n>conqueue_errc</c-><c- o>::</c-><c- n>empty</c-></code>. Otherwise, pop the element from the queue
via move construction into the optional. Return <code class="highlight">true</code> and set <code class="highlight"><c- n>ec</c-></code> to <code class="highlight"><c- n>conqueue_errc</c-><c- o>::</c-><c- n>success</c-></code>.</p>
   <p>These operations will never block.
If they would have to wait for internal synchronization,
they return false and set <code class="highlight"><c- n>ec</c-></code> to <code class="highlight"><c- n>conqueue_errc</c-><c- o>::</c-><c- n>busy</c-></code>.</p>
   <h3 class="heading settled" data-level="5.5" id="closed_queues"><span class="secno">5.5. </span><span class="content">Closed Queues</span><a class="self-link" href="#closed_queues"></a></h3>
   <p>Threads using a queue for communication need some mechanism to signal
when the queue is no longer needed. The usual approach is add an
additional out-of-band signal. However, this approach suffers from the
flaw that threads waiting on either full or empty queues need to be
woken up when the queue is no longer needed. To do that, you need access
to the condition variables used for full/empty blocking, which
considerably increases the complexity and fragility of the interface. It
also leads to performance implications with additional mutexes or
atomics. Rather than require an out-of-band signal, we chose to directly
support such a signal in the queue itself, which considerably simplifies
coding.</p>
   <p>To achieve this signal, a thread may <code class="highlight"><c- n>close</c-></code> a queue. Once closed,
no new elements may be pushed onto the queue. Push operations on a
closed queue will either return <code class="highlight"><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-></code> (when they have <code class="highlight"><c- n>ec</c-></code> parameter) or throw <code class="highlight"><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code> (when they do not). Elements
already on the queue may be popped off. When a queue is empty and
closed, pop operations will either set <code class="highlight"><c- n>ec</c-></code> to <code class="highlight"><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-></code> (when they have a <code class="highlight"><c- n>ec</c-></code> parameter) or
throw <code class="highlight"><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code> otherwise.</p>
   <p>The additional operations are as follows:</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>queue::close</c-><c- p>()</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <p>Close the queue.</p>
<pre class="language-c++ highlight"><c- b>bool</c-> <c- nf>queue::is_closed</c-><c- p>()</c-> <c- k>const</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <p>Return true iff the queue is closed.</p>
   <h3 class="heading settled" data-level="5.6" id="element_requirements"><span class="secno">5.6. </span><span class="content">Element Type Requirements</span><a class="self-link" href="#element_requirements"></a></h3>
   <p>The above operations require element types with copy/move constructors,
and destructor. These operations may be trivial. The copy/move
constructors operators may throw, but must leave the objects in a valid
state for subsequent operations.</p>
   <h3 class="heading settled" data-level="5.7" id="exception_handling"><span class="secno">5.7. </span><span class="content">Exception Handling</span><a class="self-link" href="#exception_handling"></a></h3>
   <p><code class="highlight"><c- n>push</c-><c- p>()</c-></code> and <code class="highlight"><c- n>pop</c-><c- p>()</c-></code> may throw an exceptions of type <code class="highlight"><c- n>conqueue_error</c-></code> that’s derived from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>system_error</c-></code> and will contain a <code class="highlight"><c- n>conqueue_errc</c-></code>.</p>
   <p>Concurrent queues cannot completely hide the effect of exceptions thrown
by the element type, in part because changes cannot be transparently
undone when other threads are observing the queue.</p>
   <p>Queues may rethrow exceptions from storage allocation, mutexes, or
condition variables.</p>
   <p>If the <a href="#element_requirements">element type operations required</a> do not
throw exceptions, then only the exceptions above are rethrown.</p>
   <p>When an element copy/move may throw, some queue operations have
additional behavior.</p>
   <ul>
    <li data-md>
     <p>A push operation shall rethrow and the state of the queue is
unaffected.</p>
    <li data-md>
     <p>A pop operation shall rethrow and the element is popped from the
queue. The value popped is effectively lost. (Doing otherwise would
likely clog the queue with a bad element.)</p>
   </ul>
   <h2 class="heading settled" data-level="6" id="Concrete"><span class="secno">6. </span><span class="content">Concrete Queues</span><a class="self-link" href="#Concrete"></a></h2>
   <p>In addition to the concepts, the standard needs at least one concrete
queue.
This paper proposes a fixed-size <code class="highlight"><c- n>bounded_queue</c-></code>.
It meets both concepts for queues.
The constructor takes a parameter specifying the maximum number of elements
in the queue and an optional allocator.</p>
   <p><code class="highlight"><c- n>bounded_queue</c-></code> is only allowed to allocate in its constructor. <a data-link-type="biblio" href="https://wg21.link/P3282"><cite>Static Storage for C++ Concurrent bounded_queue (P3282)</cite></a> proposes to add a constructor where the queue doesn’t own
the storage.</p>
   <h2 class="heading settled" data-level="7" id="wording"><span class="secno">7. </span><span class="content">Proposed Wording</span><a class="self-link" href="#wording"></a></h2>
   <p>Add a new subclause to clause <strong>[thread]</strong> with the following contents.</p>
   <h3 class="heading settled" data-level="7.1" id="q-wording"><span class="secno">7.1. </span><span class="content">Concurrent Queues</span><a class="self-link" href="#q-wording"></a></h3>
   <h4 class="heading settled" data-level="7.1.1" id="q-general"><span class="secno">7.1.1. </span><span class="content">General</span><a class="self-link" href="#q-general"></a></h4>
   <p>Concurrent queues provide a mechanism to transfer objects from one point
in a program to another without producing data races.</p>
   <h4 class="heading settled" data-level="7.1.2" id="q-synopsis"><span class="secno">7.1.2. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>experimental</c-><c- o>/</c-><c- n>conqueue</c-><c- o>></c-></code> synopsis</span><a class="self-link" href="#q-synopsis"></a></h4>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>experimental</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>Q</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>basic_concurrent_queue</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
    <c- k>concept</c-> <c- nc>concurrent_queue</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
    <c- k>concept</c-> <c- nc>async_concurrent_queue</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

    <c- k>enum</c-> <c- k>class</c-> <c- nc>conqueue_errc</c-> <c- p>{</c->
      <c- n>empty</c-> <c- o>=</c-> <i><c- n>implementation</c-><c- o>-</c-><c- n>defined</c-></i><c- p>,</c->
      <c- n>full</c-> <c- o>=</c-> <i><c- n>implementation</c-><c- o>-</c-><c- n>defined</c-></i><c- p>,</c->
      <c- n>closed</c-> <c- o>=</c-> <i><c- n>implementation</c-><c- o>-</c-><c- n>defined</c-></i><c- p>,</c->
      <c- n>busy</c-> <c- o>=</c-> <i><c- n>implementation</c-><c- o>-</c-><c- n>defined</c-></i>
    <c- p>};</c->

    <c- k>template</c-><c- o>&lt;></c-> <c- k>struct</c-> <c- nc>is_error_code_enum</c-><conqueue_errc> <c- o>:</c-> <c- k>public</c-> <c- n>true_type</c-> <c- p>{</c-> <c- p>};</c->
    <c- k>const</c-> <c- n>error_category</c-><c- o>&amp;</c-> <c- nf>conqueue_category</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>error_code</c-> <c- nf>make_error_code</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>error_condition</c-> <c- nf>make_error_condition</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- k>class</c-> <c- nc>conqueue_error</c-><c- p>;</c->

    <c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Allocator</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
    <c- k>class</c-> <c- nc>bounded_queue</c-><c- p>;</c->
<c- p>}</c->
</conqueue_errc></pre>
   <h4 class="heading settled" data-level="7.1.3" id="error-reporting"><span class="secno">7.1.3. </span><span class="content">Error reporting</span><a class="self-link" href="#error-reporting"></a></h4>
<pre class="language-c++ highlight"><c- k>const</c-> <c- n>error_category</c-><c- o>&amp;</c-> <c- nf>conqueue_category</c-><c- p>()</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Returns</em>: A reference to an object of a type derived from
class <code class="highlight"><c- n>error_category</c-></code>.</p>
    <li data-md>
     <p>The object’s <code class="highlight"><c- n>default_error_condition</c-></code> and <code class="highlight"><c- n>equivalent</c-></code> virtual functions shall behave as specified for the class <code class="highlight"><c- n>error_category</c-></code>.
The object’s <code class="highlight"><c- n>name</c-></code> virtual function shall return a pointer
to the string "conqueue".</p>
   </ol>
<pre class="language-c++ highlight"><c- n>error_code</c-> <c- nf>make_error_code</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>)</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Returns</em>: <code class="highlight"><c- n>error_code</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>),</c-> <c- n>conqueue_category</c-><c- p>())</c-></code>.</p>
   </ol>
<pre class="language-c++ highlight"><c- n>error_condition</c-> <c- nf>make_error_condition</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>)</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <ol start="4">
    <li data-md>
     <p><em>Returns</em>: <code class="highlight"><c- n>error_condition</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>),</c-> <c- n>conqueue_category</c-><c- p>())</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="7.1.4" id="conqueue-error"><span class="secno">7.1.4. </span><span class="content">Class <code class="highlight"><c- n>conqueue_error</c-></code></span><a class="self-link" href="#conqueue-error"></a></h4>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>experimental</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>conqueue_error</c-> <c- o>:</c-> <c- n>system_error</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>explicit</c-> <c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>);</c->

    <c- k>const</c-> <c- n>error_code</c-><c- o>&amp;</c-> <c- nf>code</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- k>const</c-> <c- b>char</c-> <c- o>*</c-> <c- nf>what</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>error_code</c-> <c- n>ec_</c-><c- p>;</c->          <i><c- c1>// exposition only</c-></i>
  <c- p>};</c->
<c- p>}</c->
</pre>
<pre class="language-c++ highlight"><c- n>explicit</c-> <c- nf>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-> <c- n>e</c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: Initializes <code class="highlight"><c- n>ec_</c-></code> with <code class="highlight"><c- n>make_error_code</c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code>.</p>
   </ol>
<pre class="language-c++ highlight"><c- k>const</c-> <c- n>error_code</c-><c- o>&amp;</c-> <c- nf>code</c-><c- p>()</c-> <c- k>const</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p><em>Returns</em>: <code class="highlight"><c- n>ec_</c-></code>.</p>
   </ol>
<pre class="language-c++ highlight"><c- k>const</c-> <c- b>char</c-> <c- o>*</c-> <c- nf>what</c-><c- p>()</c-> <c- k>const</c-> <c- n>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Returns</em>: An <code class="highlight"><c- n>NTBS</c-></code> incorporating <code class="highlight"><c- n>code</c-><c- p>().</c-><c- n>message</c-><c- p>()</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="7.1.5" id="wording-base-concept"><span class="secno">7.1.5. </span><span class="content">Basic Concurrent Queue Concept</span><a class="self-link" href="#wording-base-concept"></a></h4>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>basic_concurrent_queue</c-></code> concept defines the requirements
for a basic queue type.</p>
<pre class="highlight">  <c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>experimental</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>Q</c-><c- o>></c->
      <c- k>concept</c-> <c- nc>basic_concurrent_queue</c-> <c- o>=</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>same_as</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>Q</c-><c- o>::</c-><c- n>value_type</c-><c- o>></c-> <c- o>&amp;&amp;</c->
        <c- k>requires</c-> <c- p>(</c-><c- n>Q</c-> <c- n>q</c-><c- p>,</c-> <c- n>T</c-> <c- o>&amp;&amp;</c-><c- n>t</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-> <c- n>ec</c-><c- p>)</c-> <c- p>{</c->
          <c- n>q</c-><c- p>.</c-><c- n>is_closed</c-><c- p>()</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>bool</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>close</c-><c- p>()</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>push</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>))</c-> <c- o>-></c-> <c- b>void</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>push</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>),</c-> <c- n>ec</c-><c- p>)</c-> <c- o>-></c-> <c- b>bool</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>pop</c-><c- p>()</c-> <c- o>-></c-> <c- n>T</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>pop</c-><c- p>(</c-><c- n>ec</c-><c- p>)</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
        <c- p>};</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>In the following description, <code class="highlight"><c- n>Q</c-></code> denotes a type
conforming to the <code class="highlight"><c- n>basic_concurrent_queue</c-></code> concept, <code class="highlight"><c- n>q</c-></code> denotes an object of type <code class="highlight"><c- n>Q</c-></code>, <code class="highlight"><c- n>t</c-></code> denotes an object convertible to <code class="highlight"><c- n>Q</c-><c- o>::</c-><c- n>value_type</c-></code> and <code class="highlight"><c- n>ec</c-></code> denotes an object of type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>error_code</c-></code>.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>is_closed</c-><c- p>()</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Returns:</em> <code class="highlight">true</code> iff the queue is closed.</p>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>close</c-><c- p>()</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> Closes the queue.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>push</c-></code> is a <em>push operation</em> and <code class="highlight"><c- n>pop</c-></code> is a <em>pop operation</em>.</p>
    <li data-md>
     <p>Concepts that sunbsume <code class="highlight"><c- n>queue_base</c-></code> may have additional
push and pop operations.</p>
    <li data-md>
     <p>Successful push and pop operations will call a constructor of <code class="highlight"><c- n>T</c-></code>.
For the description of concrete queues, <em>pre-ctor</em> is the call of the constructor
and <em>post-ctor</em> is the return of the constructor.
Likewise successful pop operations will call the destructor of <code class="highlight"><c- n>T</c-></code> and we have <em>pre-dtor</em> and <em>post-dtor</em>.</p>
    <li data-md>
     <p>If an object is <em>deposited</em> into
a queue by a push operation it can be <em>extracted</em> from the queue
and returned by a pop operation.
The <em>post-ctor</em> of the push operation of the deposit <em>strongly happens before</em> the return of the pop operation.
A pop operation on a queue can only extract objects that were deposited
into the same queue and each object can only be extracted once.</p>
    <li data-md>
     <p>Concrete queues shall specify whether a push may block for
 space available in the queue (bounded queue) or whether
 a push may allocate new space (unbounded queue).</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>push</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> If the queue is not closed, <code class="highlight"><c- n>t</c-></code> is deposited into <code class="highlight"><c- n>q</c-></code>.</p>
      <li data-md>
       <p><em>Throws:</em> If the queue is closed throw <code class="highlight"><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code>.
 A concrete queue may throw additional exceptions.</p>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>push</c-><c- p>(</c-><c- n>t</c-><c- p>,</c-> <c- n>ec</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> If the queue is not closed, <code class="highlight"><c- n>t</c-></code> is deposited into <code class="highlight"><c- n>q</c-></code>.</p>
      <li data-md>
       <p><em>Returns:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight">true</code> if <code class="highlight"><c- n>t</c-></code> was deposited into <code class="highlight"><c- n>q</c-></code>; <code class="highlight">false</code> otherwise.</p>
       </ul>
      <li data-md>
       <p><em>Error conditions:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>closed</c-></code> if the queue is closed.</p>
       </ul>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>pop</c-><c- p>()</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> Blocks the current thread until there’s an object
 available in the queue or until the queue is closed.
 If the queue is closed, throw.
 Otherwise, if there is an object available in the queue,
 extract the object and return it.</p>
      <li data-md>
       <p><em>Returns:</em> the available object in the queue.</p>
      <li data-md>
       <p><em>Throws:</em> If the queue is closed throw <code class="highlight"><c- n>conqueue_error</c-><c- p>(</c-><c- n>conqueue_errc</c-><c- o>::</c-><c- n>closed</c-><c- p>)</c-></code>.
 A concrete queue may throw additional exceptions.</p>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>pop</c-><c- p>(</c-><c- n>ec</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> Blocks the current thread until there’s an object
 available in the queue or until the queue is closed.
 If there is an object available in the queue,
 extract the object and return it.</p>
      <li data-md>
       <p><em>Returns:</em> <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> if <code class="highlight"><c- n>t</c-></code> was the available object in the queue, <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>{}</c-></code> otherwise.</p>
      <li data-md>
       <p><em>Error conditions:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>closed</c-></code> if the queue is closed.</p>
       </ul>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="7.1.6" id="wording-concurrent-concept"><span class="secno">7.1.6. </span><span class="content">Concurrent Queue Concept</span><a class="self-link" href="#wording-concurrent-concept"></a></h4>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>concurrent_queue</c-></code> concept defines the requirements
for a concurrent queue type.</p>
<pre class="highlight">  <c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>experimental</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>Q</c-><c- o>></c->
      <c- k>concept</c-> <c- nc>concurrent_queue</c-> <c- o>=</c->
        <c- n>basic_concurrent_queue</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>Q</c-> <c- n>q</c-><c- p>,</c-> <c- n>T</c-> <c- o>&amp;&amp;</c-><c- n>t</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-> <c- n>ec</c-><c- p>)</c-> <c- p>{</c->
          <c- n>q</c-><c- p>.</c-><c- n>try_push</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>),</c-> <c- n>ec</c-><c- p>)</c-> <c- o>-></c-> <c- b>bool</c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>try_pop</c-><c- p>(</c-><c- n>ec</c-><c- p>)</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
        <c- p>};</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>In the following description, <code class="highlight"><c- n>Q</c-></code> denotes a type
conforming to the <code class="highlight"><c- n>concurrent_queue</c-></code> concept, <code class="highlight"><c- n>q</c-></code> denotes an object of type <code class="highlight"><c- n>Q</c-></code>, <code class="highlight"><c- n>t</c-></code> denotes an object convertible to <code class="highlight"><c- n>Q</c-><c- o>::</c-><c- n>value_type</c-></code> and <code class="highlight"><c- n>ec</c-></code> denotes an object of type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>error_code</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>try_push</c-></code> is a push operation and <code class="highlight"><c- n>try_pop</c-></code> is a pop operation.</p>
    <li data-md>
     <p>In classes modelling this concept <code class="highlight"><c- n>try_push</c-></code> may return <code class="highlight">false</code> even if the queue has space for the element.
 Similarly <code class="highlight"><c- n>try_pop</c-></code> may return <code class="highlight">false</code> even if the queue has an element
 to be extracted.
 [<em>Note:</em> This spurious failure is normally uncommon. -- end note]
 An implementation should ensure that <code class="highlight"><c- n>try_push</c-><c- p>()</c-></code> and <code class="highlight"><c- n>try_pop</c-><c- p>()</c-></code> do not consistently spuriously fail.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>try_push</c-><c- p>(</c-><c- n>t</c-><c- p>,</c-> <c- n>ec</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> If the queue is not closed,
 and space is available in the queue, <code class="highlight"><c- n>t</c-></code> is deposited into <code class="highlight"><c- n>q</c-></code>.
 The operation will not block.</p>
      <li data-md>
       <p><em>Returns:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight">true</code> if <code class="highlight"><c- n>t</c-></code> was deposited into <code class="highlight"><c- n>q</c-></code>; <code class="highlight">false</code> otherwise.</p>
       </ul>
      <li data-md>
       <p><em>Error conditions:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>closed</c-></code> if the queue is closed.</p>
        <li data-md>
         <p><code class="highlight"><c- n>full</c-></code> if the queue doesn’t have space.</p>
        <li data-md>
         <p><code class="highlight"><c- n>busy</c-></code> if the operation would block for internal synchronization.</p>
       </ul>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>try_pop</c-><c- p>(</c-><c- n>ec</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Effects:</em> If there’s an object available in the queue
 it will be extracted from the queue and returned.
 If the queue is closed an empty <code class="highlight"><c- n>optional</c-></code> is returned.
 The operation will not block.</p>
      <li data-md>
       <p><em>Returns:</em> <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> if <code class="highlight"><c- n>t</c-></code> was the available object in the queue, <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>{}</c-></code> otherwise.</p>
      <li data-md>
       <p><em>Error conditions:</em></p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>closed</c-></code> if the queue is closed.</p>
        <li data-md>
         <p><code class="highlight"><c- n>empty</c-></code> if the queue doesn’t have an element.</p>
        <li data-md>
         <p><code class="highlight"><c- n>busy</c-></code> if the operation would block for internal synchronization.</p>
       </ul>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="7.1.7" id="wording-async-concept"><span class="secno">7.1.7. </span><span class="content">Asynchronous Queue Concept</span><a class="self-link" href="#wording-async-concept"></a></h4>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>async_concurrent_queue</c-></code> concept defines the requirements
for an asynchronous queue type.</p>
<pre class="highlight">  <c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>experimental</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>Q</c-><c- o>></c->
      <c- k>concept</c-> <c- nc>async_concurrent_queue</c-> <c- o>=</c->
        <c- n>basic_concurrent_queue</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>Q</c-> <c- n>q</c-><c- p>,</c-> <c- n>T</c-> <c- o>&amp;&amp;</c-><c- n>t</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-> <c- n>ec</c-><c- p>)</c-> <c- p>{</c->
          <c- n>q</c-><c- p>.</c-><c- n>async_push</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>))</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- b>void</c-><c- o>></c-><c- p>;</c->
          <c- n>q</c-><c- p>.</c-><c- n>async_pop</c-><c- p>()</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_of</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
        <c- p>};</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>In the following description, <code class="highlight"><c- n>Q</c-></code> denotes a type
conforming to the <code class="highlight"><c- n>async_concurrent_queue</c-></code> concept, <code class="highlight"><c- n>q</c-></code> denotes an object of type <code class="highlight"><c- n>Q</c-></code> and <code class="highlight"><c- n>t</c-></code> denotes an object convertible to <code class="highlight"><c- n>Q</c-><c- o>::</c-><c- n>value_type</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_push</c-></code> is a push operation and <code class="highlight"><c- n>async_pop</c-></code> is a pop operations.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>async_push</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Returns:</em> A sender object <code class="highlight"><c- n>w</c-></code> that behaves as follows:</p>
       <ol>
        <li data-md>
         <p>When <code class="highlight"><c- n>w</c-></code> is connected with some receiver <code class="highlight"><c- n>r</c-></code>,
 it returns an operation state <code class="highlight"><c- n>op</c-></code> that behaves as follows:</p>
         <ol>
          <li data-md>
           <p>It waits until there’s space in the queue
 or until the queue is closed.</p>
          <li data-md>
           <p>If there’s space in the queue <code class="highlight"><c- n>t</c-></code> will be deposited
 into the queue and <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> will be called.</p>
          <li data-md>
           <p>If the queue is closed <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> will be called.</p>
         </ol>
       </ol>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>q</c-><c- p>.</c-><c- n>async_pop</c-><c- p>()</c-></code> has the following semantics:</p>
     <ol>
      <li data-md>
       <p><em>Returns:</em> A sender object <code class="highlight"><c- n>w</c-></code> that behaves as follows:</p>
       <ol>
        <li data-md>
         <p>When <code class="highlight"><c- n>w</c-></code> is connected with some receiver <code class="highlight"><c- n>r</c-></code>,
 it returns an operation state <code class="highlight"><c- n>op</c-></code> that behaves as follows:</p>
         <ol>
          <li data-md>
           <p>It waits until there’s an object available in the queue
 or until the queue is closed.</p>
          <li data-md>
           <p>If there’s an object <code class="highlight"><c- n>t</c-></code> available in the queue
 it will be extracted and <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>r</c-><c- p>,</c-> <c- n>t</c-><c- p>)</c-></code> will be called.</p>
          <li data-md>
           <p>If the queue is closed <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>r</c-><c- p>)</c-></code> will be called.</p>
         </ol>
       </ol>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="7.1.8" id="wording-bqueue"><span class="secno">7.1.8. </span><span class="content">Class template <code class="highlight"><c- n>bounded_queue</c-></code></span><a class="self-link" href="#wording-bqueue"></a></h4>
   <h5 class="heading settled" data-level="7.1.8.1" id="bq-general"><span class="secno">7.1.8.1. </span><span class="content">General</span><a class="self-link" href="#bq-general"></a></h5>
   <ol>
    <li data-md>
     <p>A <code class="highlight"><c- n>bounded_queue</c-></code> models <code class="highlight"><c- n>concurrent_queue</c-></code> and <code class="highlight"><c- n>async_concurrent_queue</c-></code> and can hold a fixed size of objects
which is given at construction time.</p>
    <li data-md>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- nc>T</c-><c- p>,</c->
  <c- k>class</c-> <c- nc>Allocator</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>class</c-> <c- nc>bounded_queue</c->
<c- p>{</c->
  <c- n>bounded_queue</c-><c- p>()</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
  <c- n>bounded_queue</c-><c- p>(</c-><c- k>const</c-> <c- n>bounded_queue</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
  <c- n>bounded_queue</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>bounded_queue</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->

<c- k>public</c-><c- o>:</c->
  <c- k>typedef</c-> <c- n>T</c-> <c- n>value_type</c-><c- p>;</c->

  <c- c1>// construct/destroy</c->
  <c- k>explicit</c-> <c- n>bounded_queue</c-><c- p>(</c-><c- b>size_t</c-> <c- n>max_elems</c-><c- p>,</c-> <c- k>const</c-> <c- n>Allocator</c-><c- o>&amp;</c-> <c- n>alloc</c-> <c- o>=</c-> <c- n>Allocator</c-><c- p>());</c->

  <c- o>~</c-><c- n>bounded_queue</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// observers</c->
  <c- b>bool</c-> <c- nf>is_closed</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// modifiers</c->
  <c- b>void</c-> <c- nf>close</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- b>void</c-> <c- nf>push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>);</c->
  <c- b>void</c-> <c- nf>push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>try_push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>try_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- n>sender</c-> <c- k>auto</c-> <c- n>async_push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>);</c->
  <c- n>sender</c-> <c- k>auto</c-> <c- n>async_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-><c- p>);</c->

  <c- n>T</c-> <c- nf>pop</c-><c- p>();</c->
  <c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>try_pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
  <c- n>sender</c-> <c- k>auto</c-> <c- n>async_pop</c-><c- p>();</c->
<c- p>};</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="7.1.8.2" id="bq-ctor"><span class="secno">7.1.8.2. </span><span class="content">Constructor</span><a class="self-link" href="#bq-ctor"></a></h5>
<pre class="language-c++ highlight"><c- n>explicit</c-> <c- nf>bounded_queue</c-><c- p>(</c-><c- b>size_t</c-> <c- n>max_elems</c-><c- p>,</c-> <c- k>const</c-> <c- n>Allocator</c-><c- o>&amp;</c-> <c- n>alloc</c-> <c- o>=</c-> <c- n>Allocator</c-><c- p>());</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Effects</em>: Constructs an object with no elements, but with storage for <code class="highlight"><c- n>max_elems</c-></code>.
The storage for the elements will be allocated using <code class="highlight"><c- n>alloc</c-></code>.</p>
    <li data-md>
     <p><em>Remarks</em>: The operations of <code class="highlight"><c- n>bounded_queue</c-></code> will not allocate any memory
outside the constructor.</p>
   </ol>
   <h5 class="heading settled" data-level="7.1.8.3" id="bq-modifiers"><span class="secno">7.1.8.3. </span><span class="content">Modifiers</span><a class="self-link" href="#bq-modifiers"></a></h5>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>);</c->
<c- b>void</c-> <c- nf>push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>);</c->
<c- b>bool</c-> <c- nf>push</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
<c- b>bool</c-> <c- nf>push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-> <c- n>ec</c-><c- p>);</c->
</pre>
   <ol start="5">
    <li data-md>
     <p><em>Effects</em>: Blocks the current thread until there’s space in the queue
 or until the queue is closed.</p>
    <li data-md>
     <p>Let <em>Push1</em> and <em>Push2</em> be push operations
and <em>Pop1</em> and <em>Pop2</em> be pop operations,
where <em>Pop1</em> returns the value of the parameter given to <em>Push1</em> and <em>Pop2</em> returns the value of the parameter given to <em>Push2</em>,
then there is a total order consistent with <code class="highlight"><c- n>memory_order</c-><c- o>::</c-><c- n>seq_cst</c-></code> of <em>pre-ctor</em>, <em>post-ctor</em>, <em>pre-dtor</em> and <em>post-dtor</em> of <em>Push1</em>, <em>Push2</em>, <em>Pop1</em> and <em>Pop2</em>, and moreover
if <em>post-ctor</em> of <em>Push1</em> is before <em>post-ctor</em> of <em>Push2</em> in the order,
then <em>pre-ctor</em> of <em>Pop1</em> strongly happens before <em>pre-ctor</em> of <em>Pop2</em>.</p>
    <li data-md>
     <p>[<em>Note:</em> This guarantees FIFO behaviour, but for
two concurrent pushes the constructors can not determine the
order in which the values are enqueued, and the constructors
can run concurrently as well. -- end note]</p>
    <li data-md>
     <p>[<em>Note:</em> This does not guarantee that constructors or destructors
may ever run concurrently.  An implementation may decide that
two pushes (or to pops) never run concurrently. -- end note]</p>
    <li data-md>
     <p>[<em>Note:</em> A constructor can deadlock if it tries a push or pop
on the same queue. -- end note]</p>
   </ol>
<pre class="language-c++ highlight"><c- n>T</c-> <c- nf>pop</c-><c- p>();</c->
<c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-><c- p>);</c->
<c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>try_pop</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- o>&amp;</c-><c- p>);</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>async_pop</c-><c- p>();</c->
</pre>
   <ol start="10">
    <li data-md>
     <p><em>Remarks:</em> The constructor of the returned object
and the destructor of the internal object
run on the same thread of execution.</p>
   </ol>
   <h2 class="heading settled" data-level="8" id="RevisionOld"><span class="secno">8. </span><span class="content">Old Revision History</span><a class="self-link" href="#RevisionOld"></a></h2>
   <p>P0260R6 revises P0260R5 - 2023-01-15 as follows.</p>
   <ul>
    <li data-md>
     <p>Fixing typos.</p>
    <li data-md>
     <p>Added a scope for the target TS.</p>
    <li data-md>
     <p>Added questions to be answered by a TS.</p>
    <li data-md>
     <p>Added asynchronous interface</p>
   </ul>
   <p>P0260R5 revises P0260R4 - 2020-01-12 as follows.</p>
   <ul>
    <li data-md>
     <p>Added more introductory material.</p>
    <li data-md>
     <p>Added response to feedback by LEWGI at Prague meeting 2020.</p>
    <li data-md>
     <p>Added section on existing practice.</p>
    <li data-md>
     <p>Replaced <code class="highlight"><c- n>value_pop</c-></code> with <code class="highlight"><c- n>pop</c-></code>.</p>
    <li data-md>
     <p>Replaced <code class="highlight"><c- n>is_lock_free</c-></code> with <code class="highlight"><c- n>is_always_lockfree</c-></code>.</p>
    <li data-md>
     <p>Removed <code class="highlight"><c- n>is_empty</c-></code> and <code class="highlight"><c- n>is_full</c-></code>.</p>
    <li data-md>
     <p>Added move-into parameter to <code class="highlight"><c- n>try_push</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;&amp;</c-><c- p>)</c-></code></p>
    <li data-md>
     <p>Added note that exception thrown by the queue operations themselves
are derived from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>exception</c-></code>.</p>
    <li data-md>
     <p>Added a note that the wording is partly invalid.</p>
    <li data-md>
     <p>Moved more contents into the "Abandoned" part to avoid confusion.</p>
   </ul>
   <p>P0260R4 revised P0260R3 - 2019-01-20 as follows.</p>
   <ul>
    <li data-md>
     <p>Remove the binding of <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code> to a value of zero.</p>
    <li data-md>
     <p>Correct stale use of the <code class="highlight"><c- n>Queue</c-></code> template parameter in <code class="highlight"><c- n>shared_queue_front</c-></code> to <code class="highlight"><c- n>Value</c-></code>.</p>
    <li data-md>
     <p>Change the return type of <code class="highlight"><c- n>share_queue_ends</c-></code> from a <code class="highlight"><c- n>pair</c-></code> to a
custom struct.</p>
    <li data-md>
     <p>Move the concrete queue proposal to a separate paper, <a data-biblio-display="direct" data-link-type="biblio" href="https://wg21.link/P1958" title="C++ Concurrent Buffer Queue (P1958)">[P1958]</a>.</p>
   </ul>
   <p>P0260R3 revised P0260R2 - 2017-10-15 as follows.</p>
   <ul>
    <li data-md>
     <p>Convert <code class="highlight"><c- n>queue_wrapper</c-></code> to a <code class="highlight"><c- n>function</c-></code>-like interface. This
conversion removes the <code class="highlight"><c- n>queue_base</c-></code> class. Thanks to Zach Lane for
the approach.</p>
    <li data-md>
     <p>Removed the requirement that element types have a default
constructor. This removal implies that statically sized buffers
cannot use an array implmentation and must grow a vector
implementation to the maximum size.</p>
    <li data-md>
     <p>Added a discussion of checking for output iterator end in the
wording.</p>
    <li data-md>
     <p>Fill in synopsis section.</p>
    <li data-md>
     <p>Remove stale discussion of <code class="highlight"><c- n>queue_owner</c-></code>.</p>
    <li data-md>
     <p>Move all abandoned interface discussion to a new section.</p>
    <li data-md>
     <p>Update paper header to current practice.</p>
   </ul>
   <p>P0260R2 revised P0260R1 - 2017-02-05 as follows.</p>
   <ul>
    <li data-md>
     <p>Emphasize that non-blocking operations were removed from the
proposed changes.</p>
    <li data-md>
     <p>Correct syntax typos for noexcept and template alias.</p>
    <li data-md>
     <p>Remove <code class="highlight"><c- k>static</c-></code> from <code class="highlight"><c- n>is_lock_free</c-></code> for <code class="highlight"><c- n>generic_queue_back</c-></code> and <code class="highlight"><c- n>generic_queue_front</c-></code>.</p>
   </ul>
   <p>P0260R1 revised P0260R0 - 2016-02-14 as follows.</p>
   <ul>
    <li data-md>
     <p>Remove pure virtuals from <code class="highlight"><c- n>queue_wrapper</c-></code>.</p>
    <li data-md>
     <p>Correct <code class="highlight"><c- n>queue</c-><c- o>::</c-><c- n>pop</c-></code> to <code class="highlight"><c- n>value_pop</c-></code>.</p>
    <li data-md>
     <p>Remove nonblocking operations.</p>
    <li data-md>
     <p>Remove non-locking buffer queue concrete class.</p>
    <li data-md>
     <p>Tighten up push/pop wording on closed queues.</p>
    <li data-md>
     <p>Tighten up push/pop wording on synchronization.</p>
    <li data-md>
     <p>Add note about possible non-FIFO behavior.</p>
    <li data-md>
     <p>Define <code class="highlight"><c- n>buffer_queue</c-></code> to be FIFO.</p>
    <li data-md>
     <p>Make wording consistent across attributes.</p>
    <li data-md>
     <p>Add a restriction on element special methods using the queue.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>is_lock_free</c-><c- p>()</c-></code> for only non-waiting functions.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>is_lock_free</c-><c- p>()</c-></code> static for non-indirect classes.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>is_lock_free</c-><c- p>()</c-> <c- k>noexcept</c-></code>.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>has_queue</c-><c- p>()</c-> <c- k>noexcept</c-></code>.</p>
    <li data-md>
     <p>Make destructors <code class="highlight"><c- k>noexcept</c-></code>.</p>
    <li data-md>
     <p>Replace "throws nothing" with <code class="highlight"><c- k>noexcept</c-></code>.</p>
    <li data-md>
     <p>Make the remarks about the usefulness of <code class="highlight"><c- n>is_empty</c-><c- p>()</c-></code> and <code class="highlight"><c- n>is_full</c-></code> into notes.</p>
    <li data-md>
     <p>Make the non-static member functions <code class="highlight"><c- n>is_</c-><c- p>...</c-></code> and <code class="highlight"><c- n>has_</c-><c- p>...</c-></code> functions <code class="highlight"><c- k>const</c-></code>.</p>
   </ul>
   <p>P0260R0 revised N3533 - 2013-03-12 as follows.</p>
   <ul>
    <li data-md>
     <p>Update links to source code.</p>
    <li data-md>
     <p>Add wording.</p>
    <li data-md>
     <p>Leave the name facility out of the wording.</p>
    <li data-md>
     <p>Leave the push-front facility out of the wording.</p>
    <li data-md>
     <p>Leave the reopen facility out of the wording.</p>
    <li data-md>
     <p>Leave the storage iterator facility out of the wording.</p>
   </ul>
   <p>N3532 revised N3434 = 12-0043 - 2012-01-14 as follows.</p>
   <ul>
    <li data-md>
     <p>Add more exposition.</p>
    <li data-md>
     <p>Provide separate non-blocking operations.</p>
    <li data-md>
     <p>Add a section on the lock-free queues.</p>
    <li data-md>
     <p>Argue against push-back operations.</p>
    <li data-md>
     <p>Add a cautionary note on the usefulness of <code class="highlight"><c- n>is_closed</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p>Expand the cautionary note on the usefulness of <code class="highlight"><c- n>is_empty</c-><c- p>()</c-></code>. Add <code class="highlight"><c- n>is_full</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p>Add a subsection on element type requirements.</p>
    <li data-md>
     <p>Add a subsection on exception handling.</p>
    <li data-md>
     <p>Clarify ordering constraints on the interface.</p>
    <li data-md>
     <p>Add a subsection on a lock-free concrete queue.</p>
    <li data-md>
     <p>Add a section on content iterators, distinct from the existing
streaming iterators section.</p>
    <li data-md>
     <p>Swap front and back names, as requested.</p>
    <li data-md>
     <p>General expository cleanup.</p>
    <li data-md>
     <p>Add an "Revision History" section.</p>
   </ul>
   <p>N3434 revised N3353 = 12-0043 - 2012-01-14 as follows.</p>
   <ul>
    <li data-md>
     <p>Change the inheritance-based interface to a pure conceptual
interface.</p>
    <li data-md>
     <p>Put <code class="highlight"><c- n>try_</c-><c- p>...</c-></code> operations into a separate subsection.</p>
    <li data-md>
     <p>Add a subsection on non-blocking operations.</p>
    <li data-md>
     <p>Add a subsection on push-back operations.</p>
    <li data-md>
     <p>Add a subsection on queue ordering.</p>
    <li data-md>
     <p>Merge the "Binary Interface" and "Managed Indirection" sections
into a new "Conceptual Tools" section. Expand on the topics and
their rationale.</p>
    <li data-md>
     <p>Add a subsection to "Conceptual Tools" that provides for type
erasure.</p>
    <li data-md>
     <p>Remove the "Synopsis" section.</p>
    <li data-md>
     <p>Add an "Implementation" section.</p>
   </ul>
   <h2 class="heading settled" data-level="9" id="Implementation"><span class="secno">9. </span><span class="content">Implementation</span><a class="self-link" href="#Implementation"></a></h2>
   <p>An implementation is available at <a href="https://github.com/GorNishanov/conqueue">github.com/GorNishanov/conqueue</a>.</p>
   <p>A free, open-source implementation of an earlier version of these
interfaces is avaliable at the Google Concurrency Library project at <a href="https://github.com/alasdairmackintosh/google-concurrency-library">github.com/alasdairmackintosh/google-concurrency-library</a>.
The original <code class="highlight"><c- n>buffer_queue</c-></code> is in <a href="https://github.com/alasdairmackintosh/google-concurrency-library/blob/master/include/buffer_queue.h">..../blob/master/include/buffer_queue.h</a>.
The concrete <code class="highlight"><c- n>lock_free_buffer_queue</c-></code> is in <a href="https://github.com/alasdairmackintosh/google-concurrency-library/blob/master/include/lock_free_buffer_queue.h">..../blob/master/include/lock_free_buffer_queue.h</a>.
The corresponding implementation of the conceptual tools is in <a href="https://github.com/alasdairmackintosh/google-concurrency-library/blob/master/include/queue_base.h">..../blob/master/include/queue_base.h</a>.</p>
   <h2 class="heading settled" data-level="10" id="Historic"><span class="secno">10. </span><span class="content">Historic Contents</span><a class="self-link" href="#Historic"></a></h2>
   <p><strong>The Contents in this section is for historic reference only.</strong></p>
   <h3 class="heading settled" data-level="10.1" id="Abandoned"><span class="secno">10.1. </span><span class="content">Abandoned Interfaces</span><a class="self-link" href="#Abandoned"></a></h3>
   <h4 class="heading settled" data-level="10.1.1" id="reopen"><span class="secno">10.1.1. </span><span class="content">Re-opening a Queue</span><a class="self-link" href="#reopen"></a></h4>
   <p>There are use cases for opening a queue that is closed. While we are not
aware of an implementation in which the ability to reopen a queue would
be a hardship, we also imagine that such an implementation could exist.
Open should generally only be called if the queue is closed and empty,
providing a clean synchronization point, though it is possible to call
open on a non-empty queue. An open operation following a close operation
is guaranteed to be visible after the close operation and the queue is
guaranteed to be open upon completion of the open call. (But of course,
another close call could occur immediately thereafter.)</p>
   <p><code class="highlight"><c- b>void</c-> <c- nf>queue::open</c-><c- p>();</c-></code></p>
   <dl>
    <dt data-md>Open the queue.
   </dl>
   <p>Note that when <code class="highlight"><c- n>is_closed</c-><c- p>()</c-></code> returns false, there is no assurance that
any subsequent operation finds the queue closed because some other
thread may close it concurrently.</p>
   <p>If an open operation is not available, there is an assurance that once
closed, a queue stays closed. So, unless the programmer takes care to
ensure that all other threads will not close the queue, only a return
value of true has any meaning.</p>
   <p>Given these concerns with reopening queues, we do not propose wording to
reopen a queue.</p>
   <h4 class="heading settled" data-level="10.1.2" id="non_block"><span class="secno">10.1.2. </span><span class="content">Non-Blocking Operations</span><a class="self-link" href="#non_block"></a></h4>
   <p>For cases when blocking for mutual exclusion is undesirable, one can
consider non-blocking operations. The interface is the same as the try
operations but is allowed to also return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>busy</c-></code> in case
the operation is unable to complete without blocking.</p>
   <p><code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::nonblocking_push</c-><c- p>(</c-><c- k>const</c-> <c- n>Element</c-><c- o>&amp;</c-><c- p>);</c-></code>\ <code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::nonblocking_push</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;&amp;</c-><c- p>);</c-></code></p>
   <dl>
    <dt data-md>If the operation would block, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>busy</c-></code>.
Otherwise, if the queue is full, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>full</c-></code>.
Otherwise, push the <code class="highlight"><c- n>Element</c-></code> onto the queue. Return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code>.
   </dl>
   <p><code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::nonblocking_pop</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;</c-><c- p>);</c-></code></p>
   <dl>
    <dt data-md>If the operation would block, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>busy</c-></code>.
Otherwise, if the queue is empty, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>empty</c-></code>.
Otherwise, pop the <code class="highlight"><c- n>Element</c-></code> from the queue. The element will be
moved out of the queue in preference to being copied. Return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code>.
   </dl>
   <p>These operations will neither wait nor block. However, they may do
nothing.</p>
   <p>The non-blocking operations highlight a terminology problem. In terms of
synchronization effects, <code class="highlight"><c- n>nonwaiting_push</c-></code> on queues is equivalent to <code class="highlight"><c- n>try_lock</c-></code> on mutexes. And so one could conclude that the existing <code class="highlight"><c- n>try_push</c-></code> should be renamed <code class="highlight"><c- n>nonwaiting_push</c-></code> and <code class="highlight"><c- n>nonblocking_push</c-></code> should be renamed <code class="highlight"><c- n>try_push</c-></code>. However, at least Thread Building Blocks
uses the existing terminology. Perhaps better is to not use <code class="highlight"><c- n>try_push</c-></code> and instead use <code class="highlight"><c- n>nonwaiting_push</c-></code> and <code class="highlight"><c- n>nonblocking_push</c-></code>.</p>
   <p>**In November 2016, the Concurrency Study Group chose to defer
non-blocking operations. Hence, the proposed wording does not include
these functions. In addition, as these functions were the only ones that
returned <code class="highlight"><c- n>busy</c-></code>, that enumeration is also not included.**</p>
   <h4 class="heading settled" data-level="10.1.3" id="push_front"><span class="secno">10.1.3. </span><span class="content">Push Front Operations</span><a class="self-link" href="#push_front"></a></h4>
   <p>Occasionally, one may wish to return a popped item to the queue. We can
provide for this with <code class="highlight"><c- n>push_front</c-></code> operations.</p>
   <p><code class="highlight"><c- b>void</c-> <c- nf>queue::push_front</c-><c- p>(</c-><c- k>const</c-> <c- n>Element</c-><c- o>&amp;</c-><c- p>);</c-></code>\ <code class="highlight"><c- b>void</c-> <c- nf>queue::push_front</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;&amp;</c-><c- p>);</c-></code></p>
   <dl>
    <dt data-md>Push the <code class="highlight"><c- n>Element</c-></code> onto the back of the queue, i.e. in at the end of
the queue that is normally popped. Return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code>.
   </dl>
   <p><code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::try_push_front</c-><c- p>(</c-><c- k>const</c-> <c- n>Element</c-><c- o>&amp;</c-><c- p>);</c-></code>\ <code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::try_push_front</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;&amp;</c-><c- p>);</c-></code></p>
   <dl>
    <dt data-md>If the queue was full, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>full</c-></code>. Otherwise,
push the <code class="highlight"><c- n>Element</c-></code> onto the front of the queue, i.e. in at the end
of the queue that is normally popped. Return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code>.
   </dl>
   <p><code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::nonblocking_push_front</c-><c- p>(</c-><c- k>const</c-> <c- n>Element</c-><c- o>&amp;</c-><c- p>);</c-></code>\ <code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::nonblocking_push_front</c-><c- p>(</c-><c- n>Element</c-><c- o>&amp;&amp;</c-><c- p>);</c-></code></p>
   <dl>
    <dt data-md>If the operation would block, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>busy</c-></code>.
Otherwise, if the queue is full, return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>full</c-></code>.
Otherwise, push the <code class="highlight"><c- n>Element</c-></code> onto the front queue. i.e. in at the
end of the queue that is normally popped. Return <code class="highlight"><c- n>queue_op_status</c-><c- o>::</c-><c- n>success</c-></code>.
   </dl>
   <p>This feature was requested at the Spring 2012 meeting. However, we do
not think the feature works.</p>
   <ul>
    <li data-md>
     <p>The name <code class="highlight"><c- n>push_front</c-></code> is inconsistent with existing \"push back\"
nomenclature.</p>
    <li data-md>
     <p>The effects of <code class="highlight"><c- n>push_front</c-></code> are only distinguishable from a regular
push when there is a strong ordering of elements. Highly concurrent
queues will likely have no strong ordering.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>push_front</c-></code> call may fail due to full queues, closed queues,
etc. In which case the operation will suffer contention, and may
succeed only after interposing push and pop operations. The
consequence is that the original push order is not preserved in the
final pop order. So, <code class="highlight"><c- n>push_front</c-></code> cannot be directly used as an
\'undo\'.</p>
    <li data-md>
     <p>The operation implies an ability to reverse internal changes at the
front of the queue. This ability implies a loss efficiency in some
implementations.</p>
   </ul>
   <p>In short, we do not think that in a concurrent environment <code class="highlight"><c- n>push_front</c-></code> provides sufficient semantic value to justify its cost. Consequently,
the proposed wording does not provide this feature.</p>
   <h4 class="heading settled" data-level="10.1.4" id="queue_names"><span class="secno">10.1.4. </span><span class="content">Queue Names</span><a class="self-link" href="#queue_names"></a></h4>
   <p>It is sometimes desirable for queues to be able to identify themselves.
This feature is particularly helpful for run-time diagnotics,
particularly when \'ends\' become dynamically passed around between
threads. See <a href="#Managed">Managed Indirection</a>.</p>
   <p><code class="highlight"><c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- nf>queue::name</c-><c- p>();</c-></code></p>
   <dl>
    <dt data-md>Return the name string provided as a parameter to queue
construction.
   </dl>
   <p>There is some debate on this facility, but we see no way to effectively
replicate the facility. However, in recognition of that debate, the
wording does not provide the name facility.</p>
   <h4 class="heading settled" data-level="10.1.5" id="lock_free_buffer_queue"><span class="secno">10.1.5. </span><span class="content">Lock-Free Buffer Queue</span><a class="self-link" href="#lock_free_buffer_queue"></a></h4>
   <p>We provide a concrete concurrent queue in the form of a fixed-size <code class="highlight"><c- n>lock_free_buffer_queue</c-></code>. It meets the <code class="highlight"><c- n>NonWaitingConcurrentQueue</c-></code> concept. The queue is still under development, so details may change.</p>
   <p><strong>In November 2016, the Concurrency Study Group chose to defer lock-free
queues. Hence, the proposed wording does not include a concrete
lock-free queue.</strong></p>
   <h4 class="heading settled" data-level="10.1.6" id="storage_iterators"><span class="secno">10.1.6. </span><span class="content">Storage Iterators</span><a class="self-link" href="#storage_iterators"></a></h4>
   <p>In addition to iterators that stream data into and out of a queue, we
could provide an iterator over the storage contents of a queue. Such and
iterator, even when implementable, would mostly likely be valid only
when the queue is otherwise quiecent. We believe such an iterator would
be most useful for debugging, which may well require knowledge of the
concrete class. Therefore, we do not propose wording for this feature.</p>
   <h4 class="heading settled" data-level="10.1.7" id="empty_full"><span class="secno">10.1.7. </span><span class="content">Empty and Full Queues</span><a class="self-link" href="#empty_full"></a></h4>
   <p>It is sometimes desirable to know if a queue is empty.</p>
   <p><code class="highlight"><c- b>bool</c-> <c- nf>queue::is_empty</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c-></code></p>
   <dl>
    <dt data-md>Return true iff the queue is empty.
   </dl>
   <p>This operation is useful only during intervals when the queue is known
to not be subject to pushes and pops from other threads. Its primary use
case is assertions on the state of the queue at the end if its lifetime,
or when the system is in quiescent state (where there no outstanding
pushes).</p>
   <p>We can imagine occasional use for knowing when a queue is full, for
instance in system performance polling. The motivation is significantly
weaker though.</p>
   <p><code class="highlight"><c- b>bool</c-> <c- nf>queue::is_full</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c-></code></p>
   <dl>
    <dt data-md>Return true iff the queue is full.
   </dl>
   <p>Not all queues will have a full state, and these would always return
false.</p>
   <h4 class="heading settled" data-level="10.1.8" id="queue_order"><span class="secno">10.1.8. </span><span class="content">Queue Ordering</span><a class="self-link" href="#queue_order"></a></h4>
   <p>The conceptual queue interface makes minimal guarantees.</p>
   <ul>
    <li data-md>
     <p>The queue is not empty if there is an element that has been pushed
but not popped.</p>
    <li data-md>
     <p>A push operation <em>synchronizes with</em> the pop operation that obtains
that element.</p>
    <li data-md>
     <p>A close operation <em>synchronizes with</em> an operation that observes
that the queue is closed.</p>
    <li data-md>
     <p>There is a sequentially consistent order of operations.</p>
   </ul>
   <p>In particular, the conceptual interface does not guarantee that the
sequentially consistent order of element pushes matches the sequentially
consistent order of pops. Concrete queues could specify more specific
ordering guarantees.</p>
   <h4 class="heading settled" data-level="10.1.9" id="lock_free"><span class="secno">10.1.9. </span><span class="content">Lock-Free Implementations</span><a class="self-link" href="#lock_free"></a></h4>
   <p>Lock-free queues will have some trouble waiting for the queue to be
non-empty or non-full. Therefore, we propose two closely-related
concepts. A full concurrent queue concept as described above, and a
non-waiting concurrent queue concept that has all the operations except <code class="highlight"><c- n>push</c-></code>, <code class="highlight"><c- n>wait_push</c-></code>, <code class="highlight"><c- n>value_pop</c-></code> and <code class="highlight"><c- n>wait_pop</c-></code>. That is, it has only
non-waiting operations (presumably emulated with busy wait) and
non-blocking operations, but no waiting operations. We propose naming
these <code class="highlight"><c- n>WaitingConcurrentQueue</c-></code> and <code class="highlight"><c- n>NonWaitingConcurrentQueue</c-></code>,
respectively.</p>
   <p class="note" role="note"><span class="marker">Note:</span> Adopting this conceptual split requires splitting some of the
facilities defined later.</p>
   <p>For generic code it\'s sometimes important to know if a concurrent queue
has a lock free implementation.</p>
   <p><code class="highlight"><c- k>constexpr</c-> <c- k>static</c-> <c- b>bool</c-> <c- nf>queue::is_always_lock_free</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></code></p>
   <dl>
    <dt data-md>Return true iff the has a lock-free implementation of the
non-waiting operations.
   </dl>
   <h3 class="heading settled" data-level="10.2" id="Tools"><span class="secno">10.2. </span><span class="content">Abandoned Additional Conceptual Tools</span><a class="self-link" href="#Tools"></a></h3>
   <p>There are a number of tools that support use of the conceptual
interface. These tools are not part of the queue interface, but provide
restricted views or adapters on top of the queue useful in implementing
concurrent algorithms.</p>
   <h4 class="heading settled" data-level="10.2.1" id="front_back"><span class="secno">10.2.1. </span><span class="content">Fronts and Backs</span><a class="self-link" href="#front_back"></a></h4>
   <p>Restricting an interface to one side of a queue is a valuable code
structuring tool. This restriction is accomplished with the classes <code class="highlight"><c- n>generic_queue_front</c-></code> and <code class="highlight"><c- n>generic_queue_back</c-></code> parameterized on the
concrete queue implementation. These act as pointers with access to only
the front or the back of a queue. The front of the queue is where
elements are popped. The back of the queue is where elements are pushed.</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>send</c-><c- p>(</c-> <c- b>int</c-> <c- n>number</c-><c- p>,</c-> <c- n>generic_queue_back</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-> <c- n>arv</c-> <c- p>);</c->
</pre>
   <p>These fronts and backs are also able to provide <code class="highlight"><c- n>begin</c-></code> and <code class="highlight"><c- n>end</c-></code> operations that unambiguously stream data into or out of a queue.</p>
   <h4 class="heading settled" data-level="10.2.2" id="streaming_iterators"><span class="secno">10.2.2. </span><span class="content">Streaming Iterators</span><a class="self-link" href="#streaming_iterators"></a></h4>
   <p>In order to enable the use of existing algorithms streaming through
concurrent queues, they need to support iterators. Output iterators will
push to a queue and input iterators will pop from a queue. Stronger
forms of iterators are in general not possible with concurrent queues.</p>
   <p>Iterators implicitly require waiting for the advance, so iterators are
only supportable with the <code class="highlight"><c- n>WaitingConcurrentQueue</c-></code> concept.</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>iterate</c-><c- p>(</c->
    <c- n>generic_queue_back</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>>::</c-><c- n>iterator</c-> <c- n>bitr</c-><c- p>,</c->
    <c- n>generic_queue_back</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>>::</c-><c- n>iterator</c-> <c- n>bend</c-><c- p>,</c->
    <c- n>generic_queue_front</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>>::</c-><c- n>iterator</c-> <c- n>fitr</c-><c- p>,</c->
    <c- n>generic_queue_front</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>>::</c-><c- n>iterator</c-> <c- n>fend</c-><c- p>,</c->
    <c- b>int</c-> <c- p>(</c-><c- o>*</c-><c- n>compute</c-><c- p>)(</c-> <c- b>int</c-> <c- p>)</c-> <c- p>)</c->
<c- p>{</c->
    <c- k>while</c-> <c- p>(</c-> <c- n>fitr</c-> <c- o>!=</c-> <c- n>fend</c-> <c- o>&amp;&amp;</c-> <c- n>bitr</c-> <c- o>!=</c-> <c- n>bend</c-> <c- p>)</c->
        <c- o>*</c-><c- n>bitr</c-><c- o>++</c-> <c- o>=</c-> <c- n>compute</c-><c- p>(</c-><c- o>*</c-><c- n>fitr</c-><c- o>++</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>Note that contrary to existing iterator algorithms, we check both
iterators for reaching their end, as either may be closed at any time.</p>
   <p>Note that with suitable renaming, the existing standard front insert and
back insert iterators could work as is. However, there is nothing like a
pop iterator adapter.</p>
   <h4 class="heading settled" data-level="10.2.3" id="Binary"><span class="secno">10.2.3. </span><span class="content">Binary Interfaces</span><a class="self-link" href="#Binary"></a></h4>
   <p>The standard library is template based, but it is often desirable to
have a binary interface that shields client from the concrete
implementations. For example, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>function</c-></code> is a binary interface to
callable object (of a given signature). We achieve this capability in
queues with type erasure.</p>
   <p>We provide a <code class="highlight"><c- n>queue_base</c-></code> class template parameterized by the value
type. Its operations are virtual. This class provides the essential
independence from the queue representation.</p>
   <p>We also provide <code class="highlight"><c- n>queue_front</c-></code> and <code class="highlight"><c- n>queue_back</c-></code> class templates
parameterized by the value types. These are essentially <code class="highlight"><c- n>generic_queue_front</c-><c- o>&lt;</c-><c- n>queue_base</c-><c- o>&lt;</c-><c- n>Value</c-><c- o>>></c-></code> and <code class="highlight"><c- n>generic_queue_front</c-><c- o>&lt;</c-><c- n>queue_base</c-><c- o>&lt;</c-><c- n>Value</c-><c- o>>></c-></code>, respectively.</p>
   <p>To obtain a pointer to <code class="highlight"><c- n>queue_base</c-></code> from an non-virtual concurrent
queue, construct an instance the <code class="highlight"><c- n>queue_wrapper</c-></code> class template, which
is parameterized on the queue and derived from <code class="highlight"><c- n>queue_base</c-></code>. Upcasting a
pointer to the <code class="highlight"><c- n>queue_wrapper</c-></code> instance to a <code class="highlight"><c- n>queue_base</c-></code> instance thus
erases the concrete queue type.</p>
<pre class="language-c++ highlight"><c- k>extern</c-> <c- b>void</c-> <c- nf>seq_fill</c-><c- p>(</c-> <c- b>int</c-> <c- n>count</c-><c- p>,</c-> <c- n>queue_back</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>b</c-> <c- p>);</c->

<c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>body</c-><c- p>(</c-> <c- mi>10</c-> <c- d>/*elements*/</c-><c- p>,</c-> <c- d>/*named*/</c-> <c- s>"body"</c-> <c- p>);</c->
<c- n>queue_wrapper</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-> <c- n>wrap</c-><c- p>(</c-> <c- n>body</c-> <c- p>);</c->
<c- n>seq_fill</c-><c- p>(</c-> <c- mi>10</c-><c- p>,</c-> <c- n>wrap</c-><c- p>.</c-><c- n>back</c-><c- p>()</c-> <c- p>);</c->
</pre>
   <h4 class="heading settled" data-level="10.2.4" id="Managed"><span class="secno">10.2.4. </span><span class="content">Managed Indirection</span><a class="self-link" href="#Managed"></a></h4>
   <p>Long running servers may have the need to reconfigure the relationship
between queues and threads. The ability to pass \'ends\' of queues
between threads with automatic memory management eases programming.</p>
   <p>To this end, we provide <code class="highlight"><c- n>shared_queue_front</c-></code> and <code class="highlight"><c- n>shared_queue_back</c-></code> template classes. These act as reference-counted versions of the <code class="highlight"><c- n>queue_front</c-></code> and <code class="highlight"><c- n>queue_back</c-></code> template classes.</p>
   <p>The <code class="highlight"><c- n>share_queue_ends</c-><c- p>(</c-><c- n>Args</c-> <c- p>...</c-> <c- n>args</c-><c- p>)</c-></code> template function will provide a
pair of <code class="highlight"><c- n>shared_queue_front</c-></code> and <code class="highlight"><c- n>shared_queue_back</c-></code> to a dynamically
allocated <code class="highlight"><c- n>queue_object</c-></code> instance containing an instance of the
specified implementation queue. When the last of these fronts and backs
are deleted, the queue itself will be deleted. Also, when the last of
the fronts or the last of the backs is deleted, the queue will be
closed.</p>
<pre class="language-c++ highlight"><c- k>auto</c-> <c- n>x</c-> <c- o>=</c-> <c- n>share_queue_ends</c-><c- o>&lt;</c-><c- n>buffer_queue</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-><c- p>(</c-> <c- mi>10</c-><c- p>,</c-> <c- s>"shared"</c-> <c- p>);</c->
<c- n>shared_queue_back</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>b</c-><c- p>(</c-><c- n>x</c-><c- p>.</c-><c- n>back</c-><c- p>);</c->
<c- n>shared_queue_front</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>f</c-><c- p>(</c-><c- n>x</c-><c- p>.</c-><c- n>front</c-><c- p>);</c->
<c- n>f</c-><c- p>.</c-><c- n>push</c-><c- p>(</c-><c- mi>3</c-><c- p>);</c->
<c- n>assert</c-><c- p>(</c-><c- mi>3</c-> <c- o>==</c-> <c- n>b</c-><c- p>.</c-><c- n>value_pop</c-><c- p>());</c->
</pre>
   <h3 class="heading settled" data-level="10.3" id="tryPushFailMove"><span class="secno">10.3. </span><span class="content"><code class="highlight"><c- n>try_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>)</c-></code></span><a class="self-link" href="#tryPushFailMove"></a></h3>
   <p><strong>REVISITED in Varna</strong></p>
   <p>The following version was introduced in response to LEWG-I concerns
about loosing the element if an rvalue cannot be stored in the
queue.</p>
   <p><code class="highlight"><c- n>queue_op_status</c-> <c- nf>queue::try_push</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>);</c-></code></p>
   <p>However, SG1 reaffirmed the APIs above with the following rationale:</p>
   <p>It seems that it is possible not to loose the element in both versions:</p>
<pre class="language-c++ highlight"><c- n>T</c-> <c- n>x</c-> <c- o>=</c-> <c- n>get_something</c-><c- p>();</c->
<c- k>if</c-> <c- p>(</c-><c- n>q</c-><c- p>.</c-><c- n>try_push</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>x</c-><c- p>)))</c-> <c- p>...</c->
</pre>
   <p>With two parameter version:</p>
<pre class="language-c++ highlight"><c- n>T</c-> <c- n>x</c-><c- p>;</c->
<c- k>if</c-> <c- p>(</c-><c- n>q</c-><c- p>.</c-><c- n>try_push</c-><c- p>(</c-><c- n>get_something</c-><c- p>(),</c-> <c- n>x</c-><c- p>))</c-> <c- p>...</c->
</pre>
   <p>Ergonomically they are roughly identical. API is slightly simpler
with one argument version, therefore, we reverted to original one
argument version.</p>
  </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="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-boostlfq">[BoostLFQ]
   <dd><a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/queue.html"><cite>Boost Lock-Free Queue</cite></a>. URL: <a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/queue.html">https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/queue.html</a>
   <dt id="biblio-boostlfspscq">[BoostLFSPSCQ]
   <dd><a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/spsc_queue.html"><cite>Boost Lock-Free SPSC Queue</cite></a>. URL: <a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/spsc_queue.html">https://www.boost.org/doc/libs/1_85_0/doc/html/boost/lockfree/spsc_queue.html</a>
   <dt id="biblio-boostmq">[BoostMQ]
   <dd><a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/interprocess/message_queue_t.html"><cite>Boost Message Queue</cite></a>. URL: <a href="https://www.boost.org/doc/libs/1_85_0/doc/html/boost/interprocess/message_queue_t.html">https://www.boost.org/doc/libs/1_85_0/doc/html/boost/interprocess/message_queue_t.html</a>
   <dt id="biblio-boostsq">[BoostSQ]
   <dd><a href="https://www.boost.org/doc/libs/1_85_0/doc/html/thread/sds.html"><cite>Boost Synchronized Queue</cite></a>. URL: <a href="https://www.boost.org/doc/libs/1_85_0/doc/html/thread/sds.html">https://www.boost.org/doc/libs/1_85_0/doc/html/thread/sds.html</a>
   <dt id="biblio-hughes97">[Hughes97]
   <dd>Cameron Hughes; Tracey Hughes. <cite>Object-Oriented Multithreading Using C++</cite>. 
   <dt id="biblio-p1958">[P1958]
   <dd><a href="https://wg21.link/P1958"><cite>C++ Concurrent Buffer Queue (P1958)</cite></a>. URL: <a href="https://wg21.link/P1958">https://wg21.link/P1958</a>
   <dt id="biblio-p2921">[P2921]
   <dd><a href="https://wg21.link/P2921"><cite>Exploring std::expected based API alternatives for buffer_queue (P2921)</cite></a>. URL: <a href="https://wg21.link/P2921">https://wg21.link/P2921</a>
   <dt id="biblio-p2921r0">[P2921R0]
   <dd>Gor Nishanov, Detlef Vollmann. <a href="https://wg21.link/p2921r0"><cite>Exploring std::expected based API alternatives for buffer_queue</cite></a>. 5 July 2023. URL: <a href="https://wg21.link/p2921r0">https://wg21.link/p2921r0</a>
   <dt id="biblio-p3282">[P3282]
   <dd><a href="https://wg21.link/P3282"><cite>Static Storage for C++ Concurrent bounded_queue (P3282)</cite></a>. URL: <a href="https://wg21.link/P3282">https://wg21.link/P3282</a>
   <dt id="biblio-tbbqb">[TBBQB]
   <dd><a href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_bounded_queue_cls.html"><cite>TBB Bounded Queue</cite></a>. URL: <a href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_bounded_queue_cls.html">https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_bounded_queue_cls.html</a>
   <dt id="biblio-tbbqub">[TBBQUB]
   <dd><a href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_queue_cls.html"><cite>TBB Unbounded Queue</cite></a>. URL: <a href="https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_queue_cls.html">https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_queue_cls.html</a>
   <dt id="biblio-williams17">[Williams17]
   <dd>Anthony Williams. <cite>C++ Concurrency in Action</cite>. 
  </dl>