<!DOCTYPE html>

<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="mobile-web-app-capable" content="yes">
    <title>
        Improving C++ concurrency features
    </title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css" integrity="sha256-QiWfLIsCT02Sdwkogf6YMiQlj4NE84MKkzEMkZnMGdg=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css" integrity="sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
    <style>
        @import url(https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i|Source+Code+Pro:300,400,500|Source+Sans+Pro:300,300i,400,400i,600,600i|Source+Serif+Pro&subset=latin-ext);.hljs{background:#fff;color:#333;display:block;overflow-x:auto;padding:.5em}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-string,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#a71d5d}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#0086b3}.hljs-built_in,.hljs-builtin-name{color:#005cc5}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#795da3}.hljs-addition{background-color:#eaffea;color:#55a532}.hljs-deletion{background-color:#ffecec;color:#bd2c00}.hljs-link{text-decoration:underline}.markdown-body{word-wrap:break-word;font-size:16px;line-height:1.5}.markdown-body:after,.markdown-body:before{content:"";display:table}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#c00}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-bottom:16px;margin-top:0}.markdown-body hr{background-color:#e7e7e7;border:0;height:.25em;margin:24px 0;padding:0}.markdown-body blockquote{border-left:.25em solid #ddd;color:#777;font-size:16px;padding:0 1em}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{background-color:#fcfcfc;border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb;color:#555;display:inline-block;font-size:11px;line-height:10px;padding:3px 5px;vertical-align:middle}.markdown-body .loweralpha{list-style-type:lower-alpha}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{font-weight:600;line-height:1.25;margin-bottom:16px;margin-top:24px}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#000;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 code,.markdown-body h1 tt,.markdown-body h2 code,.markdown-body h2 tt,.markdown-body h3 code,.markdown-body h3 tt,.markdown-body h4 code,.markdown-body h4 tt,.markdown-body h5 code,.markdown-body h5 tt,.markdown-body h6 code,.markdown-body h6 tt{font-size:inherit}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{border-bottom:1px solid #eee;padding-bottom:.3em}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{color:#777;font-size:.85em}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{list-style-type:none;padding:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-bottom:0;margin-top:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{font-size:1em;font-style:italic;font-weight:700;margin-top:16px;padding:0}.markdown-body dl dd{margin-bottom:16px;padding:0 16px}.markdown-body table{display:block;overflow:auto;width:100%;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{border:1px solid #ddd;padding:6px 13px}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{background-color:#fff;box-sizing:initial;max-width:100%}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{background-color:initial;max-width:none;vertical-align:text-top}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{border:1px solid #ddd;display:block;float:left;margin:13px 0 0;overflow:hidden;padding:7px;width:auto}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}.markdown-body span.align-center{clear:both;display:block;overflow:hidden}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{clear:both;display:block;overflow:hidden}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{background-color:#0000000a;border-radius:3px;font-size:85%;margin:0;padding:.2em 0}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{content:"\00a0";letter-spacing:-.2em}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{background:#0000;border:0;font-size:100%;margin:0;padding:0;white-space:pre;word-break:normal}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{border-radius:3px;font-size:85%;line-height:1.45;overflow:auto}.markdown-body:not(.next-editor) pre{background-color:#f7f7f7;padding:16px}.markdown-body pre code,.markdown-body pre tt{word-wrap:normal;background-color:initial;border:0;display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0}.markdown-body pre code:after,.markdown-body pre code:before,.markdown-body pre tt:after,.markdown-body pre tt:before{content:normal}.markdown-body .csv-data td,.markdown-body .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{background:#fff;border:0;padding:10px 8px 9px;text-align:right}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{background:#f8f8f8;border-top:0;font-weight:700}.news .alert .markdown-body blockquote{border:0;padding:0 0 0 40px}.activity-tab .news .alert .commits,.activity-tab .news .markdown-body blockquote{padding-left:0}.task-list-item{list-style-type:none}.task-list-item label{font-weight:400}.task-list-item.enabled label{cursor:pointer}.task-list-item+.task-list-item{margin-top:3px}.task-list-item-checkbox{cursor:default!important;float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle}.markdown-body{max-width:758px;overflow:visible!important;padding-bottom:40px;padding-top:40px;position:relative}.markdown-body.next-editor{overflow-x:hidden!important}.markdown-body .emoji{vertical-align:top}.markdown-body pre{border:inherit!important}.markdown-body code{color:inherit!important}.markdown-body pre code .wrapper{display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}.markdown-body pre code .gutter{float:left;overflow:hidden;-webkit-user-select:none;user-select:none}.markdown-body pre code .gutter.linenumber{border-right:3px solid #6ce26c!important;box-sizing:initial;color:#afafaf!important;cursor:default;display:inline-block;min-width:20px;padding:0 8px 0 0;position:relative;text-align:right;z-index:4}.markdown-body pre code .gutter.linenumber>span:before{content:attr(data-linenumber)}.markdown-body pre code .code{float:left;margin:0 0 0 16px}.markdown-body .gist .line-numbers{border-bottom:none;border-left:none;border-top:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-collapse:inherit!important;border-spacing:0}.markdown-body code[data-gist-id]{background:none;padding:0}.markdown-body code[data-gist-id]:after,.markdown-body code[data-gist-id]:before{content:""}.markdown-body code[data-gist-id] .blob-num{border:unset}.markdown-body code[data-gist-id] table{margin-bottom:unset;overflow:unset}.markdown-body code[data-gist-id] table tr{background:unset}.markdown-body[dir=rtl] pre{direction:ltr}.markdown-body[dir=rtl] code{direction:ltr;unicode-bidi:embed}.markdown-body .alert{display:flex;flex-direction:column;gap:16px}.markdown-body .alert>*{margin:0}.markdown-body pre.abc,.markdown-body pre.flow-chart,.markdown-body pre.graphviz,.markdown-body pre.mermaid,.markdown-body pre.sequence-diagram,.markdown-body pre.vega{background-color:inherit;border-radius:0;overflow:visible;text-align:center;white-space:inherit}.markdown-body pre.abc>code,.markdown-body pre.flow-chart>code,.markdown-body pre.graphviz>code,.markdown-body pre.mermaid>code,.markdown-body pre.sequence-diagram>code,.markdown-body pre.vega>code{text-align:left}.markdown-body pre.abc>svg,.markdown-body pre.flow-chart>svg,.markdown-body pre.graphviz>svg,.markdown-body pre.mermaid>svg,.markdown-body pre.sequence-diagram>svg,.markdown-body pre.vega>svg{height:100%;max-width:100%}.markdown-body pre>code.wrap{word-wrap:break-word;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap}.markdown-body summary{display:list-item}.markdown-body summary:focus{outline:none}.markdown-body details summary{cursor:pointer}.markdown-body details:not([open])>:not(summary){display:none}.markdown-body figure{margin:1em 40px}.markdown-body .mark,.markdown-body mark{background-color:#fff1a7}.vimeo,.youtube{background-color:#000;background-position:50%;background-repeat:no-repeat;background-size:contain;cursor:pointer;display:table;overflow:hidden;text-align:center}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{object-fit:contain;width:100%;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{height:100%;left:0;position:absolute;top:0;width:100%}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{color:#fff;height:auto;left:50%;opacity:.3;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity .2s;width:auto;z-index:0}.vimeo:hover .icon,.youtube:hover .icon{opacity:.6;transition:opacity .2s}.slideshare .inner,.speakerdeck .inner{position:relative;width:100%}.slideshare .inner iframe,.speakerdeck .inner iframe{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.figma{display:table;padding-bottom:56.25%;position:relative;width:100%}.figma iframe{border:1px solid #eee;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.markmap-container{height:300px}.markmap-container>svg{height:100%;width:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{color:#777;margin:25px auto -25px;max-width:760px;position:relative;z-index:2}.toc .invisable-node{list-style-type:none}.ui-toc{bottom:20px;position:fixed;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{border-bottom-left-radius:0;border-top-left-radius:0;height:40px;padding:10px 4px}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{color:#fff;opacity:1;transition:opacity .2s}.ui-toc-label:focus{background-color:#ccc;color:#000;opacity:.3}.ui-toc-label:hover{background-color:#ccc;opacity:1;transition:opacity .2s}.ui-toc-dropdown{margin-bottom:20px;margin-top:20px;max-height:70vh;max-width:45vw;overflow:auto;padding-left:10px;padding-right:10px;text-align:inherit;width:25vw}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{letter-spacing:.0029em;padding-right:0}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{color:#767676;display:block;font-size:13px;font-weight:500;padding:4px 20px}.ui-toc-dropdown .nav>li:first-child:last-child>ul,.ui-toc-dropdown .toc.expand ul{display:block}.ui-toc-dropdown .nav>li>a:focus,.ui-toc-dropdown .nav>li>a:hover{background-color:initial;border-left:1px solid #000;color:#000;padding-left:19px;text-decoration:none}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{border-left:none;border-right:1px solid #000;padding-right:19px}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{background-color:initial;border-left:2px solid #000;color:#000;font-weight:700;padding-left:18px}.ui-toc-dropdown[dir=rtl] .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav>.active>a{border-left:none;border-right:2px solid #000;padding-right:18px}.ui-toc-dropdown .nav .nav{display:none;padding-bottom:10px}.ui-toc-dropdown .nav>.active>ul{display:block}.ui-toc-dropdown .nav .nav>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:30px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:40px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a{padding-right:40px}.ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover{padding-left:29px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:hover{padding-right:29px}.ui-toc-dropdown .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>a:hover{padding-left:39px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:hover{padding-right:39px}.ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a{font-weight:500;padding-left:28px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>a{padding-right:28px}.ui-toc-dropdown .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>a{font-weight:500;padding-left:38px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active>a{padding-right:38px}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang^=ja]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,ＭＳ Ｐゴシック,sans-serif}html[lang=zh-tw] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html[lang=zh-cn] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}html .ui-toc-dropdown[lang^=ja]{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,ＭＳ Ｐゴシック,sans-serif}html .ui-toc-dropdown[lang=zh-tw]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html .ui-toc-dropdown[lang=zh-cn]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}.ui-affix-toc{max-height:70vh;max-width:15vw;overflow:auto;position:fixed;top:0}.back-to-top,.expand-toggle,.go-to-bottom{color:#999;display:block;font-size:12px;font-weight:500;margin-left:10px;margin-top:10px;padding:4px 10px}.back-to-top:focus,.back-to-top:hover,.expand-toggle:focus,.expand-toggle:hover,.go-to-bottom:focus,.go-to-bottom:hover{color:#563d7c;text-decoration:none}.back-to-top,.go-to-bottom{margin-top:0}.ui-user-icon{background-position:50%;background-repeat:no-repeat;background-size:cover;border-radius:50%;display:block;height:20px;margin-bottom:2px;margin-right:5px;margin-top:2px;width:20px}.ui-user-icon.small{display:inline-block;height:18px;margin:0 0 .2em;vertical-align:middle;width:18px}.ui-infobar>small>span{line-height:22px}.ui-infobar>small .dropdown{display:inline-block}.ui-infobar>small .dropdown a:focus,.ui-infobar>small .dropdown a:hover{text-decoration:none}.ui-more-info{color:#888;cursor:pointer;vertical-align:middle}.ui-more-info .fa{font-size:16px}.ui-connectedGithub,.ui-published-note{color:#888}.ui-connectedGithub{line-height:23px;white-space:nowrap}.ui-connectedGithub a.file-path{color:#888;padding-left:22px;text-decoration:none}.ui-connectedGithub a.file-path:active,.ui-connectedGithub a.file-path:hover{color:#888;text-decoration:underline}.ui-connectedGithub .fa{font-size:20px}.ui-published-note .fa{font-size:20px;vertical-align:top}.unselectable{-webkit-user-select:none;-o-user-select:none;user-select:none}.selectable{-webkit-user-select:text;-o-user-select:text;user-select:text}.inline-spoiler-section{cursor:pointer}.inline-spoiler-section .spoiler-text{background-color:#333;border-radius:2px}.inline-spoiler-section .spoiler-text>*{opacity:0}.inline-spoiler-section .spoiler-img{filter:blur(10px)}.inline-spoiler-section.raw{background-color:#333;border-radius:2px}.inline-spoiler-section.raw>*{opacity:0}.inline-spoiler-section.unveil{cursor:auto}.inline-spoiler-section.unveil .spoiler-text{background-color:#3333331a}.inline-spoiler-section.unveil .spoiler-text>*{opacity:1}.inline-spoiler-section.unveil .spoiler-img{filter:none}@media print{blockquote,div,img,pre,table{page-break-inside:avoid!important}a[href]:after{font-size:12px!important}}.markdown-body.slides{color:#222;position:relative;z-index:1}.markdown-body.slides:before{background-color:currentColor;bottom:0;box-shadow:0 0 0 50vw;content:"";display:block;left:0;position:absolute;right:0;top:0;z-index:-1}.markdown-body.slides section[data-markdown]{background-color:#fff;margin-bottom:1.5em;position:relative;text-align:center}.markdown-body.slides section[data-markdown] code{text-align:left}.markdown-body.slides section[data-markdown]:before{content:"";display:block;padding-bottom:56.23%}.markdown-body.slides section[data-markdown]>div:first-child{left:1em;max-height:100%;overflow:hidden;position:absolute;right:1em;top:50%;transform:translateY(-50%)}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{border:3px solid #777;content:"";height:1.5em;position:absolute;right:1em;top:-1.5em}.site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,sans-serif}html[lang^=ja] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif}html[lang=zh-tw] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}body{font-smoothing:subpixel-antialiased!important;-webkit-font-smoothing:subpixel-antialiased!important;-moz-osx-font-smoothing:auto!important;-webkit-overflow-scrolling:touch;font-family:Source Sans Pro,Helvetica,Arial,sans-serif;letter-spacing:.025em}html[lang^=ja] body{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif}html[lang=zh-tw] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}abbr[data-original-title],abbr[title]{cursor:help}body.modal-open{overflow-y:auto;padding-right:0!important}svg{text-shadow:none}
    </style>
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    	<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js" integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
    	<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js" integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js" integrity="sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=" crossorigin="anonymous"></script>
    <![endif]-->
</head>

<body>
    <div id="doc" class="markdown-body container-fluid comment-enabled" data-hard-breaks="true"><p><strong><span>Document number:</span></strong><span> P2643R2.</span><br>
<strong><span>Date</span></strong><span>: 2024-01-11.</span><br>
<strong><span>Reply to</span></strong><span>: Gonzalo Brito Gadeschi &lt;gonzalob _at_ </span><a href="http://nvidia.com" target="_blank" rel="noopener"><span>nvidia.com</span></a><span>&gt;.</span><br>
<strong><span>Authors:</span></strong><span> Gonzalo Brito Gadeschi, Olivier Giroux, Thomas Rodgers.</span><br>
<strong><span>Audience:</span></strong><span> LEWG.</span></p><style>
ins {
    color:green; 
    background-color:yellow;
    text-decoration:underline;
}
del { 
    color:red;
    background-color:yellow;
    text-decoration:line-through;
}
bdi {
    color:black;
    background-color:lightblue;
    text-decoration:underline;
}
.markdown-body { 
    max-width: 900px; 
}
</style><h1 id="Improving-C-concurrency-features" data-id="Improving-C-concurrency-features"><a class="anchor hidden-xs" href="#Improving-C-concurrency-features" title="Improving-C-concurrency-features"><span class="octicon octicon-link"></span></a><span>Improving C++ concurrency features</span></h1><p><span class="toc"><ul>
<li><a href="#Improving-C-concurrency-features" title="Improving C++ concurrency features">Improving C++ concurrency features</a><ul>
<li><a href="#Revisions" title="Revisions">Revisions</a><ul>
<li><a href="#P2---pre-Tokyo-submitted" title="P2 - (pre-Tokyo submitted)">P2 - (pre-Tokyo submitted)</a></li>
<li><a href="#D2---post-Varna-draft" title="D2 - (post-Varna draft)">D2 - (post-Varna draft)</a></li>
<li><a href="#P1---Varna-submitted" title="P1 - (Varna submitted)">P1 - (Varna submitted)</a></li>
<li><a href="#D1---post-Kona-draft" title="D1 - (post-Kona draft)">D1 - (post-Kona draft)</a></li>
</ul>
</li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Design" title="Design">Design</a><ul>
<li><a href="#Return-last-observed-value-on-wait-success" title="Return last observed value on wait success">Return last observed value on wait success</a></li>
<li><a href="#Fallible-and-timed-waiting-APIs" title="Fallible and timed waiting APIs">Fallible and timed waiting APIs</a></li>
<li><a href="#Predicated-waiting-APIs" title="Predicated waiting APIs">Predicated waiting APIs</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a><ul>
<li><a href="#Return-last-observed-value-from-atomicwait" title="Return last observed value from atomic::wait">Return last observed value from atomic::wait</a></li>
<li><a href="#Fallible-and-timed-versions-of-wait-APIs" title="Fallible and timed versions of ::wait APIs">Fallible and timed versions of ::wait APIs</a></li>
<li><a href="#Fallible-timed-and-predicated-versions-of-wait-APIs" title="Fallible, timed, and predicated versions of ::wait APIs">Fallible, timed, and predicated versions of ::wait APIs</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</span></p><h2 id="Revisions" data-id="Revisions"><a class="anchor hidden-xs" href="#Revisions" title="Revisions"><span class="octicon octicon-link"></span></a><span>Revisions</span></h2><h3 id="P2---pre-Tokyo-submitted" data-id="P2---pre-Tokyo-submitted"><a class="anchor hidden-xs" href="#P2---pre-Tokyo-submitted" title="P2---pre-Tokyo-submitted"><span class="octicon octicon-link"></span></a><span>P2 - (pre-Tokyo submitted)</span></h3><ul>
<li><span>Update examples and explanation for Library Evolution audience (forwarded from SG1).</span></li>
<li><span>Rename </span><code>try_wait_for</code><span> and </span><code>try_wait_until</code><span> to </span><code>wait_for</code><span> and </span><code>wait_until</code><span> for consistency with </span><code>condition_variable</code><span>.</span></li>
<li><span>Update </span><code>wait_with_predicate</code><span> to use </span><code>condition_variable</code><span> semantics.</span></li>
<li><code>try_wait</code><span> is </span><code>const noexcept</code><span>, </span><code>wait_for</code><span>/</span><code>wait_until</code><span> are </span><code>const</code><span> but may throw exceptions.</span></li>
<li><span>Update list of atomic waiting operations.</span></li>
<li><span>Consistently remove </span><code>noexcept</code><span> from </span><code>wait_for</code><span>/</span><code>wait_until</code><span>-like APIs which can throw due to timeout. Kept </span><code>noexcept</code><span> on untimed </span><code>try_wait</code><span>-like APIs.</span></li>
<li><span>Add wording for </span><code>latch</code><span> APIs.</span></li>
<li><span>Update predicate wait APIs with </span><code>_with_predicate</code><span> suffix for consistency. TBD whether it can be removed.</span></li>
</ul><h3 id="D2---post-Varna-draft" data-id="D2---post-Varna-draft"><a class="anchor hidden-xs" href="#D2---post-Varna-draft" title="D2---post-Varna-draft"><span class="octicon octicon-link"></span></a><span>D2 - (post-Varna draft)</span></h3><ul>
<li><span>Modified the proposal to add a new API instead of modifying the return value of </span><code>wait</code><span> to avoid breaking the ABI.</span></li>
<li><span>Remove the new C-compatibility free functions except for </span><code>atomic_wait_value</code><span> and </span><code>atomic_flag_try_wait</code><span>.</span></li>
<li><span>Add wording for </span><code>wait_with_predicate</code><span>.</span></li>
</ul><h3 id="P1---Varna-submitted" data-id="P1---Varna-submitted"><a class="anchor hidden-xs" href="#P1---Varna-submitted" title="P1---Varna-submitted"><span class="octicon octicon-link"></span></a><span>P1 - (Varna submitted)</span></h3><ul>
<li><span>Removed timed waiting for freestanding, to reflect Kona guidance, and added discussion.</span></li>
<li><span>Removed pros/cons discussion of returning </span><code>optional&lt;T&gt;</code><span> vs </span><code>pair&lt;bool, T&gt;</code><span> vs </span><code>T</code><span>, reflecting Kona guidance.</span></li>
<li><span>Re-added fallible untimed </span><code>try_wait</code><span> with rationale, reflecting Kona guidance.</span></li>
</ul><h3 id="D1---post-Kona-draft" data-id="D1---post-Kona-draft"><a class="anchor hidden-xs" href="#D1---post-Kona-draft" title="D1---post-Kona-draft"><span class="octicon octicon-link"></span></a><span>D1 - (post-Kona draft)</span></h3><ul>
<li><span>Added discussion of pros/cons of returning pair&lt;T. bool&gt; vs. optional</span>&lt;T&gt;<span>.</span></li>
<li><span>Added discussion of timed waits and freestanding, given that </span>&lt;chrono&gt;<span> is not part of freestanding.</span></li>
<li><span>Added wording for </span><code>barrier::try_wait_for</code><span> and </span><code>barrier::try_wait_until</code><span>.</span></li>
<li><span>Added motivating examples.</span></li>
<li><span>Fixed </span><code>barrier::try_wait_for/_until</code><span> signatures; they were incorrectly accepting an </span><code>arrival_token&amp;&amp;</code><span>, but since these can be called in a loop consuming the </span><code>arrival_token</code><span> is incorrect.</span></li>
<li><span>Removed discussion of ‘hinted’ wait mechanism. The design surface area of this proposal is such that it should be a separate paper, brought forward an interested party.</span></li>
<li><span>Removed fallible untimed </span><code>try_wait</code><span>.</span></li>
</ul><h2 id="Introduction" data-id="Introduction"><a class="anchor hidden-xs" href="#Introduction" title="Introduction"><span class="octicon octicon-link"></span></a><span>Introduction</span></h2><p><a href="https://wg21.link/p1135r6" target="_blank" rel="noopener"><span>P1135R6</span></a><span> introduced serval new concurrency primitives to the C++20 concurrency library:</span></p><ul>
<li><code>&lt;atomic&gt;</code><span>: added the class </span><code>atomic_flag</code><span>, the </span><code>wait</code><span> and </span><code>notify_one/_all</code><span> to class template </span><code>atomic&lt;&gt;</code><span>, and free function versions of these.</span></li>
<li><code>&lt;semaphore&gt;</code><span>: added class template </span><code>counting_semaphore&lt;&gt;</code><span> and class </span><code>binary_semaphore</code><span>.</span></li>
<li><code>&lt;barrier&gt;</code><span>,</span><code>&lt;latch&gt;</code><span>: added class template </span><code>barrier&lt;&gt;</code><span> and class </span><code>latch</code><span>.</span></li>
</ul><p><span>Though each element included was long coming, and had much implementation experience behind it, fresh user feedback tells us that some improvements could still be made:</span></p><ol>
<li><span>Return last observed value from </span><code>atomic/atomic_ref::wait</code><span>; this value is lost otherwise.</span></li>
<li><span>Add timed versions of </span><code>atomic/atomic_ref/atomic_flag::wait</code><span> APIs and other concurrency primitves like </span><code>barrier</code><span> and </span><code>latch</code><span>, to make it easier to implement concurrency primitives that expose timed waiting facilities themselves by reusing these (e.g., to enable implementing </span><code>&lt;semaphore&gt;</code><span>, which already exposes </span><code>try_acquire</code><span>/</span><code>try_acquire_for</code><span>/</span><code>try_acquire_unti</code><span>, on top of </span><code>atomic</code><span>).</span></li>
<li><span>Avoid spurious polling in </span><code>atomic/atomic_ref/atomic_flag::wait</code><span> by accepting a predicate.</span></li>
</ol><p><span>This proposal proposes extensions to address these shortcomings. This </span><a href="https://gitlab.com/rodgert/gcc/-/commit/dab70764cd68236472656a9394a32185a9ccc890" target="_blank" rel="noopener"><span>branch</span></a><span> demonstrates its implementability in libstdc++.</span></p><h2 id="Design" data-id="Design"><a class="anchor hidden-xs" href="#Design" title="Design"><span class="octicon octicon-link"></span></a><span>Design</span></h2><p><span>The design of the features above is mostly orthogonal, and this section explores them independently.</span></p><h3 id="Return-last-observed-value-on-wait-success" data-id="Return-last-observed-value-on-wait-success"><a class="anchor hidden-xs" href="#Return-last-observed-value-on-wait-success" title="Return-last-observed-value-on-wait-success"><span class="octicon octicon-link"></span></a><span>Return last observed value on wait success</span></h3><p><span>The design to return the last observed value on wait success adds a new API that returns the old value:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token operator">&gt;</span>
T <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_value</span><span class="token punctuation">(</span>
    T old<span class="token punctuation">,</span> 
    memory_order order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token keyword">noexcept</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>A new template member is added to respect the WG21 policy of avoiding breaking the ABI of </span><code>atomic::wait</code><span>.</span></p><table>
<tbody><tr>
  <td colspan="2">
    <b>Example 0:</b> wait-value   
  </td>    
</tr>
<tr>
  <td> <b>Before</b> </td>    
  <td> <b>After</b>  </td>
</tr>
<tr>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
a<span class="token punctuation">.</span><span class="token function">wait</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> o <span class="token operator">=</span> a<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>o <span class="token operator">!=</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// MAY FAIL!</span>
</code></pre>
</td>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> o <span class="token operator">=</span> a<span class="token punctuation">.</span><span class="token function">wait_value</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">assert</span><span class="token punctuation">(</span>o <span class="token operator">!=</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// OK!  </span>
</code></pre>
</td>
</tr>
</tbody></table><p><span>The </span><code>atomic&lt;T&gt;::wait_value</code><span> method guarantees that the thread is unblocked only if the value changed.</span></p><p><em><span>Before</span></em><span> this paper, the new </span><code>atomic&lt;T&gt;</code><span> value that unblocked the wait is not returned to the caller. This has the following two shortcomings:</span></p><ul>
<li><strong><span>That value is lost forever</span></strong><span> (correctness): after the thread is unblocked, the value might change back to the old value before the unblocked thread calls </span><code>atomic&lt;T&gt;::load</code><span> again (</span><a href="https://en.wikipedia.org/wiki/ABA_problem" target="_blank" rel="noopener"><span>ABA Problem</span></a><span>).</span></li>
<li><strong><span>That value must often be reloaded</span></strong><span> (performance): applications need the new value often, which forces them to call </span><code>atomic&lt;T&gt;::load</code><span> to re-load the value, even though </span><code>atomic::wait&lt;T&gt;</code><span> had already loaded it (required to test that the value did change preventing spurious unblocking).</span></li>
</ul><p><em><span>After</span></em><span> this paper, the value returned by </span><code>wait_value</code><span> is returned to the caller, eliminating the need for the subsequent load.</span></p><h4 id="API-naming" data-id="API-naming"><a class="anchor hidden-xs" href="#API-naming" title="API-naming"><span class="octicon octicon-link"></span></a><span>API naming</span></h4><p><span>This proposal names this new API </span><code>wait_value</code><span>. Some other options are:</span></p><ul>
<li><code>wait_last</code></li>
<li><code>wait_fetch</code></li>
</ul><h3 id="Fallible-and-timed-waiting-APIs" data-id="Fallible-and-timed-waiting-APIs"><a class="anchor hidden-xs" href="#Fallible-and-timed-waiting-APIs" title="Fallible-and-timed-waiting-APIs"><span class="octicon octicon-link"></span></a><span>Fallible and timed waiting APIs</span></h3><p><span>The design of the fallible timed versions of wait APIs adds three new APIs to </span><code>atomic</code><span>, </span><code>atomic_ref</code><span>, </span><code>atomic_flag</code><span>, </span><code>barrier</code><span>, and </span><code>latch</code><span> (</span><code>sempahore</code><span> already has </span><code>try_acquire</code><span>/</span><code>try_acquire_for</code><span>, and </span><code>try_acquire_until</code><span>). For </span><code>atomic</code><span> these are</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">try_wait</span><span class="token punctuation">(</span>
    T value<span class="token punctuation">,</span>
    memory_order order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token keyword">noexcept</span><span class="token punctuation">;</span>    

<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Rep</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Period</span><span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_for</span><span class="token punctuation">(</span>
    T value<span class="token punctuation">,</span>
    duration<span class="token operator">&lt;</span>Rep<span class="token punctuation">,</span> Period<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> rel_time<span class="token punctuation">,</span>
    memory_order order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
    
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Clock</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Duration</span><span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_until</span><span class="token punctuation">(</span>
    T value<span class="token punctuation">,</span>
    time_point<span class="token operator">&lt;</span>Clock<span class="token punctuation">,</span> Duration<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> abs_time<span class="token punctuation">,</span>
    memory_order order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>They are non-blocking, i.e., they eventually return to the caller in a finite-set of steps, even if the value did not change. This enables the application to “do something else” before attempting to wait again.</span></p><p><span>On failure, i.e., if the value did not change, they return </span><code>nullopt</code><span> and the operation has no effects (it does not synchronize). On success, they return an </span><code>optional&lt;T&gt;</code><span> containing the last observed value, which is guaranteed to be different from the one the call site waited on.</span></p><p><span>The untimed </span><code>try_wait</code><span> overload waits for a finite </span><em><span>unspecified</span></em><span> duration. The implementation may pick a different duration every time, which is why assigning implementation-specific default arguments to the other untimed wait APIs does not suffice. This overload enables the implementation to attempt to wait for a dynamic system-specific amount of time (e.g. depending on system latencies, load, etc.). Furthermore, </span><code>try_wait</code><span> is </span><code>noexcept</code><span>, but the other APIs </span><code>wait_for</code><span> and </span><code>wait_until</code><span> may throw timeout-related exceptions.</span></p><p><span>Since </span><code>&lt;chrono&gt;</code><span> and </span><code>&lt;optional&gt;</code><span> are not freestanding, these APIs will not be available in freestanding implementations. C++23+ has mechanisms to partially support these in free-standing. We </span><em><span>should</span></em><span> attempt to support a subset of these new concurrency APIs in freestanding by:</span></p><ul>
<li><span>Supporting the subset of </span><code>optional</code><span> APIs that do not throw exceptions in freestanding.</span></li>
<li><span>Supporting the </span><code>&lt;chrono&gt;</code><span> durations in freestanding.</span></li>
</ul><p><span>In the following </span><strong><span>Example 1</span></strong><span>, the atomic variable </span><code>t</code><span> tracks how many tasks need to be processed. As tasks are processed, this counter is decremented. In the example, the application reports progress by printing the number of remaining tasks every second:</span></p><table>
<tbody><tr>
  <td colspan="2">
    <b>Example 1:</b> Print remaining tasks every 1s.   
  </td>    
</tr>
<tr>
  <td> <b>Before</b> </td>    
  <td> <b>After</b>  </td>
</tr>
<tr>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> t<span class="token punctuation">;</span>
<span class="token keyword">int</span> rem <span class="token operator">=</span> t<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> b <span class="token operator">=</span> clock<span class="token double-colon punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>rem <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 rem <span class="token operator">=</span> t<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">auto</span> e <span class="token operator">=</span> clock<span class="token double-colon punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>e <span class="token operator">-</span> b<span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">1</span>s<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   cout <span class="token operator">&lt;&lt;</span> rem<span class="token punctuation">;</span>
   b <span class="token operator">=</span> e<span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> t<span class="token punctuation">;</span>
<span class="token keyword">int</span> rem <span class="token operator">=</span> t<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">while</span> <span class="token punctuation">(</span>rem <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">auto</span> o <span class="token operator">=</span> t<span class="token punctuation">.</span><span class="token function">wait_for</span><span class="token punctuation">(</span>rem<span class="token punctuation">,</span> <span class="token number">1</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
 rem <span class="token operator">=</span> o<span class="token punctuation">.</span><span class="token function">value_or</span><span class="token punctuation">(</span>rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
 cout <span class="token operator">&lt;&lt;</span> rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span> 

    
    
</code></pre>
</td>
</tr>
</tbody></table><p><em><span>Before</span></em><span> this proposal, applications need to re-implement </span><code>atomic&lt;T&gt;::wait</code><span> logic, since it may block for a duration that exceeds the 1s reporting time. Doing this is properly is non-trivial and error prone, e.g., this example accidentally calls </span><code>atomic&lt;T&gt;::load</code><span> in a loop without any back-off.</span></p><p><em><span>After</span></em><span> this proposal, the application uses </span><code>wait_for</code><span> to efficiently and correctly wait for at most 1s.</span></p><p><span>For </span><code>barrier</code><span> and </span><code>latch</code><span>, the proposed fallible wait APIs accept </span><code>arrival_token&amp;</code><span>, since the token is re-used across multiple API calls. Since C++23, the wait APIs may modify the barrier value and advance the phase, but implementations that do so use </span><code>mutable</code><span> internally, and this proposal keeps them as </span><code>const</code><span> methods for consistency with the current wait APIs.</span></p><p><span>The proposed fallible APIs are the following:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">CF</span><span class="token operator">&gt;</span>
<span class="token keyword">bool</span> <span class="token class-name">barrier</span><span class="token operator">&lt;</span>CF<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">try_wait</span><span class="token punctuation">(</span>
    arrival_token<span class="token operator">&amp;</span> tok
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">CF</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Rep</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Period</span><span class="token operator">&gt;</span>
<span class="token keyword">bool</span> <span class="token class-name">barrier</span><span class="token operator">&lt;</span>CF<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_for</span><span class="token punctuation">(</span>
    arrival_token<span class="token operator">&amp;</span> tok<span class="token punctuation">,</span> 
    duration<span class="token operator">&lt;</span>Rep<span class="token punctuation">,</span> Period<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> rel_time
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">CF</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Clock</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Duration</span><span class="token operator">&gt;</span>
<span class="token keyword">bool</span> <span class="token class-name">barrier</span><span class="token operator">&lt;</span>CF<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_until</span><span class="token punctuation">(</span>
    arrival_token<span class="token operator">&amp;</span> tok<span class="token punctuation">,</span> 
    time_point<span class="token operator">&lt;</span>Clock<span class="token punctuation">,</span> Duration<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> abs_time
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>

<span class="token comment">// bool latch::try_wait() const noexcept; // Available since C++20</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">Rep</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Period</span><span class="token operator">&gt;</span>
<span class="token keyword">bool</span> latch<span class="token double-colon punctuation">::</span><span class="token function">wait_for</span><span class="token punctuation">(</span>
    duration<span class="token operator">&lt;</span>Rep<span class="token punctuation">,</span> Period<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> rel_time
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">Clock</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Duration</span><span class="token operator">&gt;</span>
<span class="token keyword">bool</span> latch<span class="token double-colon punctuation">::</span><span class="token function">wait_until</span><span class="token punctuation">(</span>
    time_point<span class="token operator">&lt;</span>Clock<span class="token punctuation">,</span> Duration<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> abs_time
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>In the following </span><strong><span>Example 2</span></strong><span>, an application uses a barrier to track the global amount of tasks to be processed. Once all tasks have been processed, the barrier completes. The processing thread processes its thread-local tasks first, marking the completion of its tasks by arriving at the barrier with the processed task count. Instead of blocking and idling until all tasks have been processed, the processing thread gives other threads 1 ms to complete their tasks, and on failure, it attempts to help other threads by stealing some of their tasks, until all tasks have been completed. In the same way that </span><code>arrive</code><span> and </span><code>wait</code><span> enable overlapping independent work in-between arriving and waiting at a barrier, fallible wait methods enable overlapping independent work while waiting on a barrier:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token comment">// Example 2</span>
std<span class="token double-colon punctuation">::</span>barrier <span class="token function">b</span><span class="token punctuation">(</span>task_count<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
<span class="token comment">// Processing thread:</span>
<span class="token keyword">auto</span> processed_task_count <span class="token operator">=</span> <span class="token function">process_thread_local_tasks</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
<span class="token keyword">auto</span> t <span class="token operator">=</span> b<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span>processed_task_count<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>b<span class="token punctuation">.</span><span class="token function">wait_for</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">1</span>ms<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">auto</span> stolen_task_count <span class="token operator">=</span> <span class="token function">steal_and_process_tasks</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   b<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span>stolen_task_count<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</div></div></code></pre><h3 id="Predicated-waiting-APIs" data-id="Predicated-waiting-APIs"><a class="anchor hidden-xs" href="#Predicated-waiting-APIs" title="Predicated-waiting-APIs"><span class="octicon octicon-link"></span></a><span>Predicated waiting APIs</span></h3><p><span>The wait APIs of C++ concurrency primitives wait for a value to change from </span><code>x</code><span> to some other value. It is very common for applications to need waiting on a more complex condition, e.g., “wait for the value to change to precisely </span><code>42</code><span>”, i.e., “wait until </span><code>x == 42</code><span>”.</span></p><p><span>With the current waiting APIs, the application is notified every time the value changes. This is very flexible, since it enables implementing any desired logic on top. The following </span><strong><span>Example 3</span></strong><span> shows how to wait until </span><code>x == 42</code><span>:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token comment">// Example 3: wait until x == 42.</span>
std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> x<span class="token punctuation">;</span>
<span class="token keyword">int</span> last <span class="token operator">=</span> x<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>last <span class="token operator">!=</span> <span class="token number">42</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">// Wait on 'x != last':</span>
   last <span class="token operator">=</span> x<span class="token punctuation">.</span><span class="token function">wait_value</span><span class="token punctuation">(</span>last<span class="token punctuation">)</span><span class="token punctuation">;</span>   
<span class="token punctuation">}</span>
<span class="token function">assert</span><span class="token punctuation">(</span>last <span class="token operator">==</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>Unfortunately, this is a forward progress, performance, and energy efficiency “gotcha”. Programs that wait for a condition different from “not equal to” (e.g. “wait for </span><code>x == 42</code><span>” above) using </span><code>atomic::wait</code><span> APIs include a re-try loop around the </span><code>wait</code><span> operation as shown in </span><strong><span>Example 3</span></strong><span>. The implementation is oblivious to the fact that the program has already been waiting for some time on a more complex condition, and each call to wait in this re-try loop looks to the implementation as the </span><em><span>first</span></em><span> call to wait.</span></p><p><span>This is problematic, because it leads to re-executing the implementation short-term polling strategy. Implementations do not implement waiting as simple busy-polling (loading the value in a loop). Instead they use concurrent algorithms that depend on “how long has this thread been waiting” to schedule system threads appropriately. If a thread is waiting for the first time, it’ll get many resources to provide low latency in case the condition is met quickly. As the waiting time increases, threads get less resources, to enable other threads in the system to run. This is crucial for ensuring forward progress of the whole system, since if a waiting thread prevents other threads from running, the condition its waiting on may never be met, causing the application to hang.</span></p><p><span>A waiting API that accepts a predicate instead of a value enbles the application to push the program-defined condition into </span><code>atomic::wait</code><span>, avoiding the outer re-try loop, and enabling the implementation to track time spent. At least two C++ standard library implementations currently already internally implement </span><code>atomic::wait</code><span> in terms of a wait taking a predicate.</span></p><p><span>The proposed design for the predicated </span><code>atomic::wait</code><span> API is analogous to </span><a href="https://eel.is/c++draft/thread.condition#condvar-13" target="_blank" rel="noopener"><code>condition_variable::wait</code></a><span> API, which take a </span><code>stop_waiting</code><span> predicate. None of the APIs is </span><code>noexcept</code><span>, since the predicate is allowed to throw. The design picks an argument order that differs from </span><code>condition_variable</code><span>: the order of arguments for </span><code>condition_variable</code><span> is “(lock, chrono duration/time point, predicate)”, but for the proposed APIs, and just like for  </span><code>atomic::wait_for</code><span>/</span><code>_until</code><span>, the condition (</span><code>old</code><span> value or </span><code>stop_predicate</code><span>) comes before the chrono types, which comes before the </span><code>memory_order</code><span> argument which has a default value.</span></p><p><span>The proposed design for the predicated </span><code>atomic::wait</code><span> and </span><code>atomic_ref::wait</code><span> APIs is:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token comment">// Untimed: blocks.</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">P</span><span class="token operator">&gt;</span>
  <span class="token keyword">requires</span> predicate<span class="token operator">&lt;</span>P<span class="token punctuation">,</span> T<span class="token operator">&gt;</span>
T <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_with_predicate</span><span class="token punctuation">(</span>
    P<span class="token operator">&amp;&amp;</span> stop_waiting<span class="token punctuation">,</span> 
    memory_order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>

<span class="token comment">// Timed, unspecified duration.</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">P</span><span class="token operator">&gt;</span>
  <span class="token keyword">requires</span> predicate<span class="token operator">&lt;</span>P<span class="token punctuation">,</span> T<span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">try_wait_with_predicate</span><span class="token punctuation">(</span>
    P<span class="token operator">&amp;&amp;</span> stop_waiting<span class="token punctuation">,</span> 
    memory_order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>

<span class="token comment">// Timed duration</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">P</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Rep</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Period</span><span class="token operator">&gt;</span>
  <span class="token keyword">requires</span> predicate<span class="token operator">&lt;</span>P<span class="token punctuation">,</span> T<span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_for_with_predicate</span><span class="token punctuation">(</span>
    P<span class="token operator">&amp;&amp;</span> stop_waiting<span class="token punctuation">,</span>
    duration<span class="token operator">&lt;</span>Rep<span class="token punctuation">,</span> Period<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> rel_time<span class="token punctuation">,</span>
    memory_order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span>

<span class="token comment">// Time point</span>
<span class="token keyword">template</span> <span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">P</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Clock</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">Duration</span><span class="token operator">&gt;</span>
  <span class="token keyword">requires</span> predicate<span class="token operator">&lt;</span>P<span class="token punctuation">,</span> T<span class="token operator">&gt;</span>
optional<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token class-name">atomic</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span><span class="token double-colon punctuation">::</span><span class="token function">wait_until_with_predicate</span><span class="token punctuation">(</span>
    P<span class="token operator">&amp;&amp;</span> stop_waiting<span class="token punctuation">,</span> 
    time_point<span class="token operator">&lt;</span>Clock<span class="token punctuation">,</span> Duration<span class="token operator">&gt;</span> <span class="token keyword">const</span><span class="token operator">&amp;</span> abs_time<span class="token punctuation">,</span>
    memory_order <span class="token operator">=</span> memory_order<span class="token double-colon punctuation">::</span>seq_cst
<span class="token punctuation">)</span> <span class="token keyword">const</span><span class="token punctuation">;</span> 
</div></div></code></pre><table>
<tbody><tr>
  <td colspan="2">
    <b>Example 4:</b> before/after vs Example 3.   
  </td>    
</tr>
<tr>
  <td> <b>Before</b> </td>    
  <td> <b>After</b>  </td>
</tr>
<tr>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> x<span class="token punctuation">;</span>
<span class="token keyword">int</span> last <span class="token operator">=</span> x<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>last <span class="token operator">!=</span> <span class="token number">42</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">// Wait on 'x != last':</span>
   last <span class="token operator">=</span> x<span class="token punctuation">.</span><span class="token function">wait_value</span><span class="token punctuation">(</span>last<span class="token punctuation">)</span><span class="token punctuation">;</span>   
<span class="token punctuation">}</span>
<span class="token function">assert</span><span class="token punctuation">(</span>last <span class="token operator">==</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
</td>
<td>
<pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> x<span class="token punctuation">;</span>
<span class="token keyword">int</span> last <span class="token operator">=</span>
 x<span class="token punctuation">.</span><span class="token function">wait_with_predicate</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">int</span> v<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">return</span> x <span class="token operator">==</span> <span class="token number">42</span><span class="token punctuation">;</span> 
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
<span class="token function">assert</span><span class="token punctuation">(</span>last <span class="token operator">==</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
</td>
</tr>
</tbody></table><p><em><span>Before</span></em><span> this proposal, the application that needs to wait on </span><code>x == 42</code><span> needs a re-try loop that causes the implementation to pick the short-term polling strategy every time </span><code>x</code><span> changes.</span></p><p><em><span>After</span></em><span> this proposal, the application passes a predicate to wait on </span><code>x == 42</code><span>. While </span><code>x</code><span> may change many times until this predicate is satisfied, the implementation is aware that </span><code>x</code><span> changing is not the condition the application is waiting on.</span></p><h2 id="Wording" data-id="Wording"><a class="anchor hidden-xs" href="#Wording" title="Wording"><span class="octicon octicon-link"></span></a><span>Wording</span></h2><h3 id="Return-last-observed-value-from-atomicwait" data-id="Return-last-observed-value-from-atomicwait"><a class="anchor hidden-xs" href="#Return-last-observed-value-from-atomicwait" title="Return-last-observed-value-from-atomicwait"><span class="octicon octicon-link"></span></a><span>Return last observed value from </span><code>atomic::wait</code></h3><p><span>Add new APIs to the list of atomic waiting operations in the Note at </span><a href="https://eel.is/c++draft/atomics.wait#2" target="_blank" rel="noopener"><span>[atomics.wait#2]</span></a><span>:</span></p><p><span>[Note 2: The following functions are atomic waiting operations:</span></p><ol>
<li><code>atomic&lt;T&gt;::wait</code><span> </span><ins><span>and </span><code>atomic&lt;T&gt;::wait_value</code></ins><span>,</span></li>
<li><code>atomic_flag::wait</code><span>,</span></li>
<li><code>atomic_wait</code><del><span> and</span></del><ins><span>,</span></ins><span> </span><code>atomic_wait_explicit</code><span>,</span><ins><span> </span><code>atomic_wait_value</code><span>, and </span><code>atomic_wait_value_explicit</code><span>,</span></ins></li>
<li><code>atomic_flag_wait</code><span> and </span><code>atomic_flag_wait_explicit</code><span>, and</span></li>
<li><code>atomic_ref&lt;T&gt;::wait</code><ins><span> and `atomic_ref</span>&lt;T&gt;<span>::wait_value</span></ins><span>.</span><br>
<span>— end note]</span></li>
</ol><p><span>To </span><a href="http://eel.is/c++draft/atomics.syn" target="_blank" rel="noopener"><span>[atomics.syn]</span></a><span>:</span></p><pre><code>namespace std {
 // [atomics.nonmembers], non-member functions
 template&lt;class T&gt;
 void atomic_wait(const volatile atomic&lt;T&gt;*,                                   // freestanding
                  typename atomic&lt;T&gt;::value_type) noexcept;
 template&lt;class T&gt;
 void atomic_wait(const atomic&lt;T&gt;*, typename atomic&lt;T&gt;::value_type) noexcept;  // freestanding
 template&lt;class T&gt;
 void atomic_wait_explicit(const volatile atomic&lt;T&gt;*,                          // freestanding
                           typename atomic&lt;T&gt;::value_type,
                           memory_order) noexcept;
 template&lt;class T&gt;
 void atomic_wait_explicit(const atomic&lt;T&gt;*, typename atomic&lt;T&gt;::value_type,   // freestanding
                           memory_order) noexcept;
 <ins>template&lt;class T&gt;
 typename atomic&lt;T&gt;::value_type
 atomic_wait_value(const volatile atomic&lt;T&gt;*,                 // freestanding
                   typename atomic&lt;T&gt;::value_type) noexcept;
 template&lt;class T&gt;
 typename atomic&lt;T&gt;::value_type 
 atomic_wait_value(const atomic&lt;T&gt;*,                          // freestanding
                   typename atomic&lt;T&gt;::value_type) noexcept;
 template&lt;class T&gt;
 typename atomic&lt;T&gt;::value_type
 atomic_wait_value_explicit(const volatile atomic&lt;T&gt;*,        // freestanding
                           typename atomic&lt;T&gt;::value_type,
                           memory_order) noexcept;
 template&lt;class T&gt;
 typename atomic&lt;T&gt;::value_type
 atomic_wait_value_explicit(const atomic&lt;T&gt;*,                 // freestanding
                            typename atomic&lt;T&gt;::value_type,
                            memory_order) noexcept;</ins>
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.generic.general" target="_blank" rel="noopener"><span>[atomics.ref.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref {  // [atomics.ref.generic.general]
    <ins>T wait_value(T, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics#lib:wait,atomic_ref%3cT%3e" target="_blank" rel="noopener"><span>[atomics.ref.ops]</span></a><span>:</span></p><pre><code>void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
<ins>T wait_value(T old, memory_order order = memory_order::seq_cst) const noexcept;</ins></code></pre><ul>
<li><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></li>
<li><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span>
<ol>
<li><span>Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span></li>
<li><span>If they compare unequal, </span><ins><code>wait</code></ins><span> returns</span><ins><span> and </span><code>wait_value</code><span> returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><span>Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.</span></li>
</ol>
</li>
<li><em><span>Remarks</span></em><span>: This function is an atomic waiting operation (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>) on atomic object </span><code>*ptr</code><span>.</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.int" target="_blank" rel="noopener"><span>[atomics.ref.int]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;integral&gt; {
    <ins>integral wait_value(integral, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.float" target="_blank" rel="noopener"><span>[atomics.ref.float]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;floating-point&gt; {
    <ins>floating-point wait_value(floating-point, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.pointer" target="_blank" rel="noopener"><span>[atomics.ref.pointer]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref&lt;T*&gt; {
    <ins>T* wait_value(T*, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.generic.general" target="_blank" rel="noopener"><span>[atomics.types.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic {
    <ins>T wait_value(T, memory_order = memory_order::seq_cst) const volatile noexcept;</ins>
    <ins>T wait_value(T, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.operations#lib:wait,atomic" target="_blank" rel="noopener"><span>[atomics.types.operations]</span></a><span>:</span></p><pre><code>void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
<ins>T wait_value(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;</ins>
<ins>T wait_value(T old, memory_order order = memory_order::seq_cst) const noexcept;</ins></code></pre><ul>
<li><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></li>
<li><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span>
<ol>
<li><span>Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span></li>
<li><span>If they compare unequal, </span><ins><code>wait</code><span> </span></ins><span>returns</span><ins><span> and </span><code>wait_value</code><span> returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><span>Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.</span></li>
</ol>
</li>
<li><em><span>Remarks</span></em><span>: </span><del><span>This function is an</span></del><ins><span>These functions are</span></ins><span> atomic waiting operation</span><ins><span>s</span></ins><span> (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>).</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.int" target="_blank" rel="noopener"><span>[atomics.types.int]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic&lt;integral&gt; {
    <ins>integral wait_value(integral, memory_order = memory_order::seq_cst) const volatile noexcept;</ins>
    <ins>integral wait_value(integral, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.float" target="_blank" rel="noopener"><span>[atomics.types.float]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic&lt;floating-point&gt; {
    <ins>floating-point wait_value(floating-point, memory_order = memory_order::seq_cst) const volatile noexcept;</ins>
    <ins>floating-point wait_value(floating-point, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.pointer" target="_blank" rel="noopener"><span>[atomics.types.pointer]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic&lt;T*&gt; {
    <ins>T* wait_value(T*, memory_order = memory_order::seq_cst) const volatile noexcept;</ins>
    <ins>T* wait_value(T*, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/util.smartptr.atomic.shared" target="_blank" rel="noopener"><span>[util.smartptr.atomic.shared]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic&lt;shared_ptr&lt;T&gt;&gt; {
    <ins>shared_ptr&lt;T&gt; wait_value(shared_ptr&lt;T&gt; old, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><p><span>and</span></p><pre><code>void wait_value(shared_ptr&lt;T&gt; old, memory_order order = memory_order::seq_cst) const noexcept;
<ins>shared_ptr&lt;T&gt;  wait_value(shared_ptr&lt;T&gt; old, memory_order order = memory_order::seq_cst) const noexcept;
</ins></code></pre><ul>
<li><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></li>
<li><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span>
<ol>
<li><span>Evaluates </span><code>load(order)</code><span> and compares it to </span><code>old</code><span>.</span></li>
<li><span>If the two are not equivalent, </span><ins><code>wait</code></ins><span> returns</span><ins><span> and </span><code>wait_value</code><span> returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><span>Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.</span></li>
</ol>
</li>
<li><em><span>Remarks</span></em><span>: Two </span><code>shared_ptr</code><span> objects are equivalent if they store the same pointer and either share ownership or are both empty. </span><del><span>This function is an</span></del><ins><span>These functions are</span></ins><span> atomic waiting operation</span><ins><span>s</span></ins><span> (</span><a href="http://eel.is/c++draft/atomics.wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>).</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/util.smartptr.atomic.weak" target="_blank" rel="noopener"><span>[util.smartptr.atomic.weak]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic&lt;weak_ptr&lt;T&gt;&gt; {
    <ins>weak_ptr&lt;T&gt; wait_value(weak_ptr&lt;T&gt; old, memory_order = memory_order::seq_cst) const noexcept;</ins>
  };
}</code></pre><pre><code>void wait(weak_ptr&lt;T&gt; old, memory_order order = memory_order::seq_cst) const noexcept;
<ins>weak_ptr&lt;T&gt; wait_value(weak_ptr&lt;T&gt; old, memory_order order = memory_order::seq_cst) const noexcept;</ins>
</code></pre><ul>
<li><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></li>
<li><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span>
<ol>
<li><span>Evaluates </span><code>load(order)</code><span> and compares it to </span><code>old</code><span>.</span></li>
<li><span>If the two are not equivalent, </span><ins><code>wait</code></ins><span> returns</span><ins><span> and </span><code>wait_value</code><span> returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><span>Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.</span></li>
</ol>
</li>
<li><em><span>Remarks</span></em><span>: Two </span><code>weak_ptr</code><span> objects are equivalent if they store the same pointer and either share ownership or are both empty. </span><del><span>This function is an</span></del><ins><span>These functions are</span></ins><span> atomic waiting operation</span><ins><span>s</span></ins><span> (</span><a href="http://eel.is/c++draft/atomics.wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>).</span></li>
</ul><p><span>No changes to </span><a href="http://eel.is/c++draft/atomics.nonmembers" target="_blank" rel="noopener"><span>[atomics.nonmembers]</span></a><span> are needed.</span></p><p><span>No changes to </span><a href="http://eel.is/c++draft/atomics.flag" target="_blank" rel="noopener"><span>[atomic.flag]</span></a><span>'s </span><code>wait</code><span> APIs are needed.</span></p><h3 id="Fallible-and-timed-versions-of-wait-APIs" data-id="Fallible-and-timed-versions-of-wait-APIs"><a class="anchor hidden-xs" href="#Fallible-and-timed-versions-of-wait-APIs" title="Fallible-and-timed-versions-of-wait-APIs"><span class="octicon octicon-link"></span></a><span>Fallible and timed versions of </span><code>::wait</code><span> APIs</span></h3><p><span>Add new APIs to the list of atomic waiting operations in the Note at </span><a href="https://eel.is/c++draft/atomics.wait#2" target="_blank" rel="noopener"><span>[atomics.wait#2]</span></a><span>:</span></p><p><span>[</span><em><span>Note 2</span></em><span>: The following functions are atomic waiting operations:</span></p><ol>
<li><code>atomic&lt;T&gt;::wait</code><span>,</span><ins><span> </span><code>atomic&lt;T&gt;::try_wait</code><span>, </span><code>atomic&lt;T&gt;::wait_for</code><span>, </span><code>atomic::&lt;T&gt;::wait_until</code><span>,</span></ins></li>
<li><code>atomic_flag::wait</code><span>, </span><ins><code>atomic_flag::try_wait</code><span>,  </span><code>atomic_flag::wait_for</code><span>, </span><code>atomic_flag::wait_until</code><span>, </span></ins></li>
<li><code>atomic_wait</code><del><span> and</span></del><ins><span>,</span></ins><span> </span><code>atomic_wait_explicit</code><span>,</span><ins><span> </span><code>atomic_try_wait</code><span>, and </span><code>atomic_try_wait_explicit</code><span>,</span></ins></li>
<li><code>atomic_flag_wait</code><del><span> and</span></del><ins><span>,</span></ins><span> </span><code>atomic_flag_wait_explicit</code><span>, </span><ins><code>atomic_flag_try_wait</code><span>, </span><code>atomic_flag_try_wait_explicit</code><span>,</span></ins><del><span>and</span></del></li>
<li><code>atomic_ref&lt;T&gt;::wait</code><ins><span>, </span><code>atomic_ref&lt;T&gt;::try_wait</code><span>, </span><code>atomic_ref&lt;T&gt;::wait_for</code><span>, </span><code>atomic_ref&lt;T&gt;::wait_until</code></ins><span>.</span><br>
<span>— </span><em><span>end note</span></em><span>]</span></li>
</ol><p><span>To </span><a href="http://eel.is/c++draft/atomics.syn" target="_blank" rel="noopener"><span>[atomics.syn]</span></a><span>:</span></p><blockquote>
<p><bdi><strong><span>EDITORIAL</span></strong><span>: only APIs that do not use </span><code>&lt;optional&gt;</code><span> or </span><code>&lt;chrono&gt;</code><span> added for C compatibility. That is, only </span><code>try_wait</code><span> is added for C compatibility, </span><code>wait_for</code><span> and </span><code>wait_until</code><span> are not added here.</span></bdi></p>
</blockquote><pre><code>namespace std {
 // [atomics.flag], flag type and operations
 
 void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept;  // freestanding
 void atomic_flag_wait(const atomic_flag*, bool) noexcept;           // freestanding
 void atomic_flag_wait_explicit(const volatile atomic_flag*,         // freestanding
                                 bool, memory_order) noexcept;
 void atomic_flag_wait_explicit(const atomic_flag*,                  // freestanding
                                 bool, memory_order) noexcept;
                                 
 <ins>bool atomic_flag_try_wait(const volatile atomic_flag*, bool) noexcept;  // freestanding
 bool atomic_flag_try_wait(const atomic_flag*, bool) noexcept;           // freestanding
 bool atomic_flag_try_wait_explicit(const volatile atomic_flag*,         // freestanding
                                    bool, memory_order) noexcept;
 bool atomic_flag_try_wait_explicit(const atomic_flag*,                  // freestanding
                                    bool, memory_order) noexcept;</ins>
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.generic.general" target="_blank" rel="noopener"><span>[atomics.ref.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref {  // [atomics.ref.generic.general]
    <ins>optional&lt;T&gt; try_wait(T, memory_order = memory_order::seq_cst) const noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;T&gt; wait_for(
      T, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T&gt; wait_until(
      T, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics#lib:wait,atomic_ref%3cT%3e" target="_blank" rel="noopener"><span>[atomics.ref.ops]</span></a><span>:</span></p><pre><code><ins>optional&lt;T&gt; try_wait(T old, memory_order = memory_order::seq_cst) const noexcept;
template &lt;class Rep, class Period&gt;
optional&lt;T&gt; wait_for(T old, 
    chrono::duration&lt;Rep, Period&gt; const&amp; rel_time,
    memory_order order = memory_order::seq_cst
) const;
template &lt;class Clock, class Duration&gt;
optional&lt;T&gt; wait_until(T old, 
    chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time,
    memory_order order = memory_order::seq_cst
) const;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span></ins></li>
<li><ins><span>If they compare unequal, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><bdi><strong><span>INCONSISTENCY</span></strong><span>: </span><code>try_wait</code><span> is noexcept, but here we say it throws. Add above “…and it does not throw.”. Add below: “…from </span><code>wait_for</code><span> and </span><code>wait_until</code><span>.”</span></bdi></li>
<li><ins><em><span>Throws</span></em><span>: Timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: This function is an atomic waiting operation (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>) on atomic object </span><code>*ptr</code></ins><span>.</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.int" target="_blank" rel="noopener"><span>[atomics.ref.int]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;integral&gt; {
    <ins>optional&lt;integral&gt; try_wait(integral, memory_order = memory_order::seq_cst) const noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;integral&gt; wait_for(
      integral, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;integral&gt; wait_until(
      integral, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.float" target="_blank" rel="noopener"><span>[atomics.ref.float]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;floating-point&gt; {
    <ins>optional&lt;floating-point&gt; try_wait(
      floating-point, 
      memory_order = memory_order::seq_cst
     ) const noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;floating-point&gt; wait_for(
      floating-point, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;floating-point&gt; wait_until(
      floating-point, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.pointer" target="_blank" rel="noopener"><span>[atomics.ref.pointer]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref&lt;T*&gt; {
    <ins>optional&lt;T*&gt; try_wait(T* old, memory_order = memory_order::seq_cst) const noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;T*&gt; wait_for(
      T*, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T*&gt; wait_until(
      T*, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.generic.general" target="_blank" rel="noopener"><span>[atomics.types.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic {
    <ins>optional&lt;T&gt; try_wait(T old, memory_order = memory_order::seq_cst) const noexcept;
    optional&lt;T&gt; try_wait(T old, memory_order = memory_order::seq_cst) const volatile noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;T&gt; wait_for(
      integral, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
     optional&lt;T&gt; wait_for(
      integral, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T&gt; wait_until(
      integral, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T&gt; wait_until(
      integral, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.operations#lib:wait,atomic" target="_blank" rel="noopener"><span>[atomics.types.operations]</span></a><span>:</span></p><pre><code><ins>optional&lt;T&gt; try_wait(T old, memory_order = memory_order::seq_cst) const noexcept;
optional&lt;T&gt; try_wait(T old, memory_order = memory_order::seq_cst) const volatile noexcept;
template &lt;class Rep, class Period&gt;
optional&lt;T&gt; wait_for(T old, 
                     chrono::duration&lt;Rep, Period&gt; const&amp; rel_time,
                     memory_order order = memory_order::seq_cst
                    ) const;
template &lt;class Rep, class Period&gt;
optional&lt;T&gt; wait_for(T old, 
                     chrono::duration&lt;Rep, Period&gt; const&amp; rel_time,
                     memory_order order = memory_order::seq_cst
                    ) const volatile;
template &lt;class Clock, class Duration&gt;
optional&lt;T&gt; wait_until(T old, 
                       chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time,
                       memory_order order = memory_order::seq_cst
                      ) const;
template &lt;class Clock, class Duration&gt;
optional&lt;T&gt; wait_until(T old, 
                       chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time,
                       memory_order order = memory_order::seq_cst
                      ) const volatile;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span></ins></li>
<li><ins><span>If they compare unequal, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><bdi><strong><span>INCONSISTENCY</span></strong><span>: </span><code>try_wait</code><span> is noexcept, but here we say it throws. Add above “…and it does not throw.”. Add below: “…from </span><code>wait_for</code><span> and </span><code>wait_until</code><span>.”</span></bdi></li>
<li><ins><em><span>Throws</span></em><span>: Timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: This function is an atomic waiting operation (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>) on atomic object </span><code>*ptr</code></ins><span>.</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.int" target="_blank" rel="noopener"><span>[atomics.types.int]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic&lt;integral&gt; {
    <ins>optional&lt;integral&gt; try_wait(integral, memory_order = memory_order::seq_cst) const noexcept;
    optional&lt;integral&gt; try_wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;integral&gt; wait_for(
      integral, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Rep, class Period&gt;
    optional&lt;integral&gt; wait_for(
      integral, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;
    template &lt;class Clock, class Duration&gt;
    optional&lt;integral&gt; wait_until(
      integral, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;integral&gt; wait_until(
      integral, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.float" target="_blank" rel="noopener"><span>[atomics.types.float]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;&gt; struct atomic&lt;floating-point&gt; {
    <ins>optional&lt;floating-point&gt; try_wait(floating-point, memory_order = memory_order::seq_cst) const noexcept;
    optional&lt;floating-point&gt; try_wait(floating-point, memory_order = memory_order::seq_cst) const volatile noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;floating-point&gt; wait_for(
      floating-point, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Rep, class Period&gt;
    optional&lt;floating-point&gt; wait_for(
      floating-point, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;
    template &lt;class Clock, class Duration&gt;
    optional&lt;floating-point&gt; wait_until(
      floating-point, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;floating-point&gt; wait_until(
      floating-point, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics.types.pointer" target="_blank" rel="noopener"><span>[atomics.types.pointer]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic&lt;T*&gt; {
    <ins>optional&lt;T*&gt; try_wait(T*, memory_order = memory_order::seq_cst) const noexcept;
    optional&lt;T*&gt; try_wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;T*&gt; wait_for(
      T*, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Rep, class Period&gt;
    optional&lt;T*&gt; wait_for(
      T*, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T*&gt; wait_until(
      T*, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;T*&gt; wait_until(
      T*, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/util.smartptr.atomic.shared" target="_blank" rel="noopener"><span>[util.smartptr.atomic.shared]</span></a><span>:</span></p><pre><code><ins>optional&lt;shared_ptr&lt;T&gt;&gt; try_wait(
    shared_ptr&lt;T&gt; old, 
    memory_order order = memory_order::seq_cst
) const noexcept;
template &lt;class Rep, class Period&gt;
optional&lt;shared_ptr&lt;T&gt;&gt; wait_for(
    shared_ptr&lt;T&gt; old, 
    chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
    memory_order order = memory_order::seq_cst
) const;
template &lt;class Clock, class Duration&gt;
optional&lt;shared_ptr&lt;T&gt;&gt; wait_until(
    shared_ptr&lt;T&gt; old, 
    chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
    memory_order order = memory_order::seq_cst
) const;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and compares it to </span><code>old</code><span>.</span></ins></li>
<li><ins><span>If the two are not equivalent, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><bdi><strong><span>INCONSISTENCY</span></strong><span>: </span><code>try_wait</code><span> is noexcept, but here we say it throws. Add above “…and it does not throw.”. Add below: “…from </span><code>wait_for</code><span> and </span><code>wait_until</code><span>.”</span></bdi></li>
<li><ins><em><span>Throws</span></em><span>: Timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: Two </span><code>shared_ptr</code><span> objects are equivalent if they store the same pointer and either share ownership or are both empty. These functions are atomic waiting operations (</span><a href="http://eel.is/c++draft/atomics.wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>).</span></ins></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/util.smartptr.atomic.weak" target="_blank" rel="noopener"><span>[util.smartptr.atomic.weak]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic&lt;weak_ptr&lt;T&gt;&gt; {
    <ins>optional&lt;weak_ptr&lt;T&gt;&gt; try_wait(
      weak_ptr&lt;T&gt;, 
      memory_order = memory_order::seq_cst
     ) const noexcept;
    template &lt;class Rep, class Period&gt;
    optional&lt;weak_ptr&lt;T&gt;&gt; wait_for(
      weak_ptr&lt;T&gt;l, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
     ) const;
    template &lt;class Clock, class Duration&gt;
    optional&lt;weak_ptr&lt;T&gt;&gt; wait_until(
      weak_ptr&lt;T&gt;, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;</ins>
  };
}</code></pre><pre><code><ins>optional&lt;weak_ptr&lt;T&gt;&gt; try_wait(
    weak_ptr&lt;T&gt; old, 
    memory_order order = memory_order::seq_cst
) const noexcept;
template &lt;class Rep, class Period&gt;
optional&lt;weak_ptr&lt;T&gt;&gt; wait_for(
    weak_ptr&lt;T&gt; old, 
    chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
    memory_order order = memory_order::seq_cst
) const;
template &lt;class Clock, class Duration&gt;
optional&lt;weak_ptr&lt;T&gt;&gt; wait_until(
    weak_ptr&lt;T&gt; old, 
    chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
    memory_order order = memory_order::seq_cst
) const;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and compares it to </span><code>old</code><span>.</span></ins></li>
<li><ins><span>If the two are not equivalent, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><bdi><strong><span>INCONSISTENCY</span></strong><span>: </span><code>try_wait</code><span> is noexcept, but here we say it throws. Add above “…and it does not throw.”. Add below: “…from </span><code>wait_for</code><span> and </span><code>wait_until</code><span>.”</span></bdi></li>
<li><ins><em><span>Throws</span></em><span>: Timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: Two </span><code>weak_ptr</code><span> objects are equivalent if they store the same pointer and either share ownership or are both empty. These functions are atomic waiting operations (</span><a href="http://eel.is/c++draft/atomics.wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>).</span></ins></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/atomics.flag" target="_blank" rel="noopener"><span>[atomic.flag]</span></a><span>:</span></p><pre><code>namespace std {
  struct atomic_flag {
    <ins>bool try_wait(bool, memory_order = memory_order::seq_cst) const noexcept;
    bool try_wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
    template &lt;class Rep, class Period&gt;
    bool wait_for(
      bool, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
    ) const;
    template &lt;class Rep, class Period&gt;
    bool wait_for(
      bool, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time, 
      memory_order = memory_order::seq_cst
    ) const volatile;
    template &lt;class Clock, class Duration&gt;
    bool wait_until(
      bool, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const;
     template &lt;class Clock, class Duration&gt;
     bool wait_until(
      bool, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
      memory_order = memory_order::seq_cst
     ) const volatile;</ins>
  };
}</code></pre><pre><code><ins>bool atomic_flag_try_wait(const atomic_flag* object, bool old) noexcept;
bool atomic_flag_try_wait(const volatile atomic_flag* object, bool old) noexcept;
bool atomic_flag_try_wait_explicit(const atomic_flag* object, bool old, memory_order order) noexcept;
bool atomic_flag_try_wait_explicit(const volatile atomic_flag* object, bool old, memory_order order) noexcept;
bool atomic_flag::try_wait(bool old, memory_order order = memory_order::seq_cst) const noexcept;
bool atomic_flag::try_wait(bool old, memory_order order = memory_order::seq_cst) const volatile noexcept;
</ins></code></pre><p><ins><span>For </span><code>atomic_flag_try_wait</code><span> let </span><code>order</code><span> be </span><code>memory_order::seq_cst</code><span>. Let </span><code>flag</code><span> be </span><code>object</code><span> for the non-member functions, and </span><code>this</code><span> for the member functions.</span></ins></p><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span></ins></li>
<li><ins><span>If they compare unequal, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><ins><em><span>Throws</span></em><span>: Timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: This function is an atomic waiting operation (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>) on atomic object </span><code>*ptr</code></ins><span>.</span></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/thread.barrier" target="_blank" rel="noopener"><span>[thread.barrier]</span></a><span>:</span></p><pre><code>namespace std {
  template &lt;class Completion Function&gt;
  class barrier {
  
  public:
    <ins>bool try_wait(arrival_token&amp; tok) const;
    template &lt;class Rep, class Period&gt;
    bool wait_for(arrival_token&amp; tok, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time) const;
    template &lt;class Clock, class Duration&gt;
    bool wait_until(arrival_token&amp; tok, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time) const;</ins>
  };
}</code></pre><pre><code><ins>bool try_wait(arrival_token&amp; tok) const;
template &lt;class Rep, class Period&gt;
bool wait_for(arrival_token&amp; tok, chrono::duration&lt;Rep, Period&gt; const&amp; rel_time) const;
template &lt;class Clock, class Duration&gt;
bool wait_until(arrival_token&amp; tok, chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time) const;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>arrival</code><span> is associated with the phase synchronization point for the current phase or the immediately preceding phase of the same barrier object.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Blocks at the synchronization point associated with </span><code>arrival</code><span> until the phase completion step of the synchronization point’s phase is run or the timeout expired. If it is unblocked by the timeout there is no effect and it returns </span><code>false</code><span>; otherwise, it returns </span><code>true</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span><br></ins><br>
<ins><span>An implementation must ensure that </span><code>wait_for</code><span> and </span><code>wait_until</code><span> do not consistently return </span><code>false</code><span> after the phase completion step associated with </span><code>arrival</code><span> has run.</span><br></ins><br>
<ins><span>[</span><em><span>Note</span></em><span>: If </span><code>arrival</code><span> is associated with the synchronization point for a previous phase, the call returns immediately. — </span><em><span>end note</span></em><span>]</span></ins></li>
<li><ins><em><span>Throws</span></em><span>: </span><code>system_error</code><span> when an exception is required (</span><a href="http://eel.is/c++draft/thread.req.exception" target="_blank" rel="noopener"><span>thread.req.exception</span></a><span>) or timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Error conditions</span></em><span>: Error conditions: Any of the error conditions allowed for mutex types (</span><a href="http://eel.is/c++draft/thread.mutex.requirements.mutex" target="_blank" rel="noopener"><span>thread.mutex.requirements.mutex</span></a><span>).</span></ins></li>
</ul><p><span>To </span><a href="http://eel.is/c++draft/thread.latch" target="_blank" rel="noopener"><span>thread.latch</span></a><span>:</span></p><pre><code>namespace std {
  class latch {
  public:
    bool try_wait() const noexcept;
    <ins>template &lt;class Rep, class Period&gt;
    bool wait_for(chrono::duration&lt;Rep, Period&gt; const&amp; rel_time) const;
    template &lt;class Clock, class Duration&gt;
    bool wait_until(chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time) const;</ins>
  };
}</code></pre><pre><code>bool try_wait() const noexcept;</code></pre><ul>
<li><del><strong><span>Returns</span></strong><span>: With very low probability </span><code>false</code><span>. Otherwise </span><code>counter == 0</code><span>.</span></del></li>
</ul><p><bdi><strong><span>SG1</span></strong><span>: the change below reformulates </span><code>try_wait</code><span> in terms of a timeout. This seems equivalent to the current formulation, but may be a breaking change.</span></bdi></p><p><ins><span>template &lt;class Rep, class Period&gt;</span><br>
<span>bool wait_for(chrono::duration&lt;Rep, Period&gt; const&amp; rel_time) const;</span><br>
<span>template &lt;class Clock, class Duration&gt;</span><br>
<span>bool wait_until(chrono::time_point&lt;Clock, Duration&gt; const&amp; abs_time) const;</span></ins></p><ul>
<li><ins><em><span>Effects</span></em><span>: If counter equals zero, return immediately. Otherwise, blocks on </span><code>*this</code><span> until a call to </span><code>count_down</code><span> that decrements counter to zero or the timeout expires. If it is unblocked by the timeout there is no effect and it returns </span><code>false</code><span>; otherwise, it returns </span><code>true</code><span>.</span></ins><br><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for</code><span>).</span><br></ins><br>
<ins><span>The timeout for </span><code>try_wait</code><span> is finite but otherwise unspecified.</span></ins><br></li>
<li><ins><em><span>Throws</span></em><span>: </span><code>system_error</code><span> when an exception is required (</span><a href="http://eel.is/c++draft/thread.req.exception" target="_blank" rel="noopener"><span>thread.req.exception</span></a><span>) or timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Error conditions</span></em><span>: Error conditions: Any of the error conditions allowed for mutex types (</span><a href="http://eel.is/c++draft/thread.mutex.requirements.mutex" target="_blank" rel="noopener"><span>thread.mutex.requirements.mutex</span></a><span>).</span></ins></li>
</ul><h3 id="Fallible-timed-and-predicated-versions-of-wait-APIs" data-id="Fallible-timed-and-predicated-versions-of-wait-APIs"><a class="anchor hidden-xs" href="#Fallible-timed-and-predicated-versions-of-wait-APIs" title="Fallible-timed-and-predicated-versions-of-wait-APIs"><span class="octicon octicon-link"></span></a><span>Fallible, timed, and predicated versions of </span><code>::wait</code><span> APIs</span></h3><p><span>Add new APIs to the list of atomic waiting operations in the Note at </span><a href="https://eel.is/c++draft/atomics.wait#2" target="_blank" rel="noopener"><span>[atomics.wait#2]</span></a><span>:</span></p><p><span>[</span><em><span>Note 2</span></em><span>: The following functions are atomic waiting operations:</span></p><ol>
<li><code>atomic&lt;T&gt;::wait</code><span>,</span><ins><span> </span><code>atomic&lt;T&gt;::wait_with_predicate</code><span>, </span><code>atomic&lt;T&gt;::try_wait_with_predicate</code><span>, </span><code>atomic&lt;T&gt;::wait_for_with_predicate</code><span>, </span><code>atomic::&lt;T&gt;::wait_until_with_predicate</code><span>,</span></ins></li>
<li><code>atomic_flag::wait</code><span>,</span><ins><span> </span><code>atomic_flag::wait_with_predicate</code><span>, </span><code>try_wait_with_predicate</code><span>, </span><code>wait_for_with_predicate</code><span>, </span><code>wait_until_with_predicate</code><span>,</span></ins></li>
<li><code>atomic_wait</code><span> and </span><code>atomic_wait_explicit</code><span>,</span></li>
<li><code>atomic_flag_wait</code><span> and, </span><code>atomic_flag_wait_explicit</code><span>, and</span></li>
<li><code>atomic_ref&lt;T&gt;::wait</code><ins><span>, </span><code>atomic_ref&lt;T&gt;::wait_with_predicate</code><span>, </span><code>atomic_ref&lt;T&gt;::try_wait_with_predicate</code><span>, </span><code>atomic_ref&lt;T&gt;::wait_for_with_predicate</code><span>, </span><code>atomic_ref&lt;T&gt;::wait_until_with_predicate</code></ins><span>.</span><br>
<span>— </span><em><span>end note</span></em><span>]</span></li>
</ol><p><span>To </span><a href="http://eel.is/c++draft/atomics.ref.generic.general" target="_blank" rel="noopener"><span>[atomics.ref.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref {  // [atomics.ref.generic.general]
    <ins>template &lt;class T, class P&gt;
      requires predicate&lt;P, T&gt;
    T wait_with_predicate(
        P&amp;&amp; stop_waiting, 
        memory_order = memory_order::seq_cst) const;
    template &lt;class T, class P&gt;
      requires predicate&lt;P, T&gt;
    optional&lt;T&gt; 
    try_wait_with_predicate(
        P&amp;&amp; stop_waiting, 
        memory_order = memory_order::seq_cst) const;
    template &lt;class T, class P, class Rep, class Period&gt;
      requires predicate&lt;P, T&gt;
    optional&lt;T&gt; wait_for_with_predicate(
        duration&lt;Rep, Period&gt; const&amp; rel_time,
        P&amp;&amp; stop_waiting, 
        memory_order = memory_order::seq_cst) const;
    template &lt;class T, class P, class Clock, class Duration&gt;
      requires predicate&lt;P, T&gt;
    optional&lt;T&gt; wait_until_with_predicate(
        P&amp;&amp; stop_waiting, 
        time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
        memory_order = memory_order::seq_cst) const;</ins>
  };
}</code></pre><p><span>To </span><a href="http://eel.is/c++draft/atomics#lib:wait,atomic_ref%3cT%3e" target="_blank" rel="noopener"><span>[atomics.ref.ops]</span></a><span>:</span></p><pre><code><ins>template &lt;class T, class P&gt;
    requires predicate&lt;P, T&gt;
T wait_with_predicate(
    P&amp;&amp; stop_waiting, 
    memory_order = memory_order::seq_cst) const;
template &lt;class T, class Predicate&gt;
    requires predicate&lt;P, T&gt;
optional&lt;T&gt; try_wait_with_predicate(
    P&amp;&amp; stop_waiting, 
    memory_order = memory_order::seq_cst) const;
template &lt;class T, class Rep, class Period, class Predicate&gt;
    requires predicate&lt;P, T&gt;
optional&lt;T&gt; wait_for_with_predicate(
    duration&lt;Rep, Period&gt; const&amp; rel_time,
    P&amp;&amp; stop_waiting, 
    memory_order = memory_order::seq_cst) const;
template &lt;class T, class Clock, class Duration, class Predicate&gt;
    requires predicate&lt;P, T&gt;
optional&lt;T&gt; wait_until_with_predicate(
    P&amp;&amp; stop_waiting, 
    time_point&lt;Clock, Duration&gt; const&amp; abs_time, 
    memory_order = memory_order::seq_cst) const;</ins></code></pre><ul>
<li><ins><em><span>Preconditions</span></em><span>: </span><code>order</code><span> is neither </span><code>memory_order::release</code><span> nor </span><code>memory_order::acq_rel</code><span>.</span></ins></li>
<li><ins><em><span>Effects</span></em><span>: Repeatedly performs the following steps, in order:</span></ins>
<ol>
<li><ins><span>Evaluates </span><code>load(order)</code><span> and calls </span><code>stop_predicate</code><span> with its result.</span></ins></li>
<li><ins><span>If </span><code>stop_predicate</code><span> returns </span><code>true</code><span>, returns the result of the evaluation of </span><code>load(order)</code><span> in the previous step</span></ins><span>.</span></li>
<li><ins><span>Blocks until it is unblocked by an atomic notifying operation, or is unblocked spuriously, or if the timeout of </span><code>try_wait_with_predicate</code><span>, </span><code>wait_for_with_predicate</code><span>, or </span><code>wait_until_with_predicate</code><span> expired. If </span><code>try_wait_with_predicate</code><span>, </span><code>wait_for_with_predicate</code><span>, or </span><code>wait_until_with_predicate</code><span> are unblocked by the timeout there is no effect and these return </span><code>nullopt</code><span>.</span><br></ins><br>
<ins><span>The timeout expires (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>) when the current time is after </span><code>abs_time</code><span> (for </span><code>wait_until_with_predicate</code><span>) or when at least </span><code>rel_time</code><span> has passed from the start of the function (for </span><code>wait_for_with_predicate</code><span>).</span></ins><br><br>
<ins><span>The timeout for </span><code>try_wait_with_predicate</code><span> is finite but otherwise unspecified.</span></ins></li>
</ol>
</li>
<li><ins><em><span>Throws</span></em><span>: any exception thrown by </span><code>stop_waiting</code><span>. The </span><code>wait_for_with_predicate</code><span> and </span><code>wait_until_with_predicate</code><span> also throw timeout-related exceptions (</span><a href="http://eel.is/c++draft/thread.req.timing" target="_blank" rel="noopener"><span>thread.req.timing</span></a><span>).</span></ins></li>
<li><ins><em><span>Remarks</span></em><span>: These functions are atomic waiting operations (</span><a href="http://eel.is/c++draft/atomics#wait" target="_blank" rel="noopener"><span>atomics.wait</span></a><span>) on atomic object </span><code>*ptr</code></ins><span>.</span></li>
</ul><blockquote>
<p><bdi><strong><span>EDITORIAL</span></strong><span>: intentionally omitting all other modifications required for the predicated APIs until initial design feedback from LEWG. But intended to be analogous for all </span><code>atomic_ref</code><span> and </span><code>atomic</code><span> specializations, and for </span><code>atomic_flag</code><span>. </span></bdi></p>
</blockquote></div>
    <div class="ui-toc dropup unselectable hidden-print" style="display:none;">
        <div class="pull-right dropdown">
            <a id="tocLabel" class="ui-toc-label btn btn-default" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false" title="Table of content">
                <i class="fa fa-bars"></i>
            </a>
            <ul id="ui-toc" class="ui-toc-dropdown dropdown-menu" aria-labelledby="tocLabel">
                <div class="toc"><ul class="nav">
<li><a href="#Improving-C-concurrency-features" title="Improving C++ concurrency features">Improving C++ concurrency features</a><ul class="nav">
<li><a href="#Revisions" title="Revisions">Revisions</a><ul class="nav">
<li><a href="#P2---pre-Tokyo-submitted" title="P2 - (pre-Tokyo submitted)">P2 - (pre-Tokyo submitted)</a></li>
<li><a href="#D2---post-Varna-draft" title="D2 - (post-Varna draft)">D2 - (post-Varna draft)</a></li>
<li><a href="#P1---Varna-submitted" title="P1 - (Varna submitted)">P1 - (Varna submitted)</a></li>
<li><a href="#D1---post-Kona-draft" title="D1 - (post-Kona draft)">D1 - (post-Kona draft)</a></li>
</ul>
</li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Design" title="Design">Design</a><ul class="nav">
<li><a href="#Return-last-observed-value-on-wait-success" title="Return last observed value on wait success">Return last observed value on wait success</a></li>
<li><a href="#Fallible-and-timed-waiting-APIs" title="Fallible and timed waiting APIs">Fallible and timed waiting APIs</a></li>
<li><a href="#Predicated-waiting-APIs" title="Predicated waiting APIs">Predicated waiting APIs</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a><ul class="nav">
<li><a href="#Return-last-observed-value-from-atomicwait" title="Return last observed value from atomic::wait">Return last observed value from atomic::wait</a></li>
<li><a href="#Fallible-and-timed-versions-of-wait-APIs" title="Fallible and timed versions of ::wait APIs">Fallible and timed versions of ::wait APIs</a></li>
<li><a href="#Fallible-timed-and-predicated-versions-of-wait-APIs" title="Fallible, timed, and predicated versions of ::wait APIs">Fallible, timed, and predicated versions of ::wait APIs</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
            </ul>
        </div>
    </div>
    <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" null null>
        <div class="toc"><ul class="nav">
<li><a href="#Improving-C-concurrency-features" title="Improving C++ concurrency features">Improving C++ concurrency features</a><ul class="nav">
<li><a href="#Revisions" title="Revisions">Revisions</a><ul class="nav">
<li><a href="#P2---pre-Tokyo-submitted" title="P2 - (pre-Tokyo submitted)">P2 - (pre-Tokyo submitted)</a></li>
<li><a href="#D2---post-Varna-draft" title="D2 - (post-Varna draft)">D2 - (post-Varna draft)</a></li>
<li><a href="#P1---Varna-submitted" title="P1 - (Varna submitted)">P1 - (Varna submitted)</a></li>
<li><a href="#D1---post-Kona-draft" title="D1 - (post-Kona draft)">D1 - (post-Kona draft)</a></li>
</ul>
</li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Design" title="Design">Design</a><ul class="nav">
<li><a href="#Return-last-observed-value-on-wait-success" title="Return last observed value on wait success">Return last observed value on wait success</a></li>
<li><a href="#Fallible-and-timed-waiting-APIs" title="Fallible and timed waiting APIs">Fallible and timed waiting APIs</a></li>
<li><a href="#Predicated-waiting-APIs" title="Predicated waiting APIs">Predicated waiting APIs</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a><ul class="nav">
<li><a href="#Return-last-observed-value-from-atomicwait" title="Return last observed value from atomic::wait">Return last observed value from atomic::wait</a></li>
<li><a href="#Fallible-and-timed-versions-of-wait-APIs" title="Fallible and timed versions of ::wait APIs">Fallible and timed versions of ::wait APIs</a></li>
<li><a href="#Fallible-timed-and-predicated-versions-of-wait-APIs" title="Fallible, timed, and predicated versions of ::wait APIs">Fallible, timed, and predicated versions of ::wait APIs</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous" defer></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
    <script>
        var markdown = $(".markdown-body");
        //smooth all hash trigger scrolling
        function smoothHashScroll() {
            var hashElements = $("a[href^='#']").toArray();
            for (var i = 0; i < hashElements.length; i++) {
                var element = hashElements[i];
                var $element = $(element);
                var hash = element.hash;
                if (hash) {
                    $element.on('click', function (e) {
                        // store hash
                        var hash = this.hash;
                        if ($(hash).length <= 0) return;
                        // prevent default anchor click behavior
                        e.preventDefault();
                        // animate
                        $('body, html').stop(true, true).animate({
                            scrollTop: $(hash).offset().top
                        }, 100, "linear", function () {
                            // when done, add hash to url
                            // (default click behaviour)
                            window.location.hash = hash;
                        });
                    });
                }
            }
        }

        smoothHashScroll();
        var toc = $('.ui-toc');
        var tocAffix = $('.ui-affix-toc');
        var tocDropdown = $('.ui-toc-dropdown');
        //toc
        tocDropdown.click(function (e) {
            e.stopPropagation();
        });

        var enoughForAffixToc = true;

        function generateScrollspy() {
            $(document.body).scrollspy({
                target: ''
            });
            $(document.body).scrollspy('refresh');
            if (enoughForAffixToc) {
                toc.hide();
                tocAffix.show();
            } else {
                tocAffix.hide();
                toc.show();
            }
            $(document.body).scroll();
        }

        function windowResize() {
            //toc right
            var paddingRight = parseFloat(markdown.css('padding-right'));
            var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));
            toc.css('right', right + 'px');
            //affix toc left
            var newbool;
            var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;
            //for ipad or wider device
            if (rightMargin >= 133) {
                newbool = true;
                var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;
                var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;
                tocAffix.css('left', left + 'px');
            } else {
                newbool = false;
            }
            if (newbool != enoughForAffixToc) {
                enoughForAffixToc = newbool;
                generateScrollspy();
            }
        }
        $(window).resize(function () {
            windowResize();
        });
        $(document).ready(function () {
            windowResize();
            generateScrollspy();
        });

        //remove hash
        function removeHash() {
            window.location.hash = '';
        }

        var backtotop = $('.back-to-top');
        var gotobottom = $('.go-to-bottom');

        backtotop.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (scrollToTop)
                scrollToTop();
            removeHash();
        });
        gotobottom.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (scrollToBottom)
                scrollToBottom();
            removeHash();
        });

        var toggle = $('.expand-toggle');
        var tocExpand = false;

        checkExpandToggle();
        toggle.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            tocExpand = !tocExpand;
            checkExpandToggle();
        })

        function checkExpandToggle () {
            var toc = $('.ui-toc-dropdown .toc');
            var toggle = $('.expand-toggle');
            if (!tocExpand) {
                toc.removeClass('expand');
                toggle.text('Expand all');
            } else {
                toc.addClass('expand');
                toggle.text('Collapse all');
            }
        }

        function scrollToTop() {
            $('body, html').stop(true, true).animate({
                scrollTop: 0
            }, 100, "linear");
        }

        function scrollToBottom() {
            $('body, html').stop(true, true).animate({
                scrollTop: $(document.body)[0].scrollHeight
            }, 100, "linear");
        }
    </script>
</body>

</html>
