<!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>
        Extend barrier APIs with memory_order
    </title>
    <link rel="icon" type="image/ico" href="https://isocpp.org/favicon.ico">

    <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{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto}.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{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.markdown-body{font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body:after,.markdown-body:before{display:table;content:""}.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;padding-right:4px;margin-left:-20px;line-height:1}.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-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e7e7e7;border:0}.markdown-body blockquote{font-size:16px;padding:0 1em;color:#777;border-left:.25em solid #ddd}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:1px solid #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.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{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.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{padding-bottom:.3em;border-bottom:1px solid #eee}.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{font-size:.85em;color:#777}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{padding:0;list-style-type:none}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #ddd}.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{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{max-width:none;vertical-align:text-top;background-color:transparent}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #ddd}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{display:block;padding:5px 0 0;clear:both;color:#333}.markdown-body span.align-center{display:block;overflow:hidden;clear:both}.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{display:block;overflow:hidden;clear:both}.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{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{letter-spacing:-.2em;content:"\00a0"}.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{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border-radius:3px}.markdown-body pre code,.markdown-body pre tt{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border: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{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{font-weight:700;background:#f8f8f8;border-top:0}.news .alert .markdown-body blockquote{padding:0 0 0 40px;border:0 none}.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{float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle;cursor:default!important}.markdown-body{padding-top:40px;padding-bottom:40px;max-width:758px;overflow:visible!important;position:relative}.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{text-align:right;position:relative;display:inline-block;cursor:default;z-index:4;padding:0 8px 0 0;min-width:20px;box-sizing:content-box;color:#afafaf!important;border-right:3px solid #6ce26c!important}.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-left:none;border-top:none;border-bottom:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-spacing:0;border-collapse:inherit!important}.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{overflow:unset;margin-bottom: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>p:last-child{margin-bottom: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{text-align:center;background-color:inherit;border-radius:0;white-space:inherit;overflow:visible}.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{max-width:100%;height:100%}.markdown-body pre>code.wrap{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.markdown-body .alert>p:last-child,.markdown-body .alert>ul:last-child{margin-bottom:0}.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{cursor:pointer;display:table;text-align:center;background-position:50%;background-repeat:no-repeat;background-size:contain;background-color:#000;overflow:hidden}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{width:100%;object-fit:contain;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{width:100%;height:100%;position:absolute;top:0;left:0}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{position:absolute;height:auto;width:auto;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;opacity:.3;transition:opacity .2s;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{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%}.figma{display:table;position:relative;width:100%;padding-bottom:56.25%}.figma iframe{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%;border:1px solid #eee}.markmap-container{height:300px}.markmap-container>svg{width:100%;height:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{position:relative;z-index:2;max-width:760px;margin:25px auto -25px;color:#777}.toc .invisable-node{list-style-type:none}.ui-toc{position:fixed;bottom:20px;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{height:40px;padding:10px 4px;border-top-left-radius:0;border-bottom-left-radius:0}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{opacity:1;color:#fff;transition:opacity .2s}.ui-toc-label:focus{opacity:.3;background-color:#ccc;color:#000}.ui-toc-label:hover{opacity:1;background-color:#ccc;transition:opacity .2s}.ui-toc-dropdown{margin-top:20px;margin-bottom:20px;padding-left:10px;padding-right:10px;max-width:45vw;width:25vw;max-height:70vh;overflow:auto;text-align:inherit}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{padding-right:0;letter-spacing:.0029em}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}.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{padding-left:19px;color:#000;text-decoration:none;background-color:transparent;border-left:1px solid #000}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{padding-right:19px;border-left:none;border-right:1px solid #000}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{padding-left:18px;font-weight:700;color:#000;background-color:transparent;border-left:2px solid #000}.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{padding-right:18px;border-left:none;border-right:2px solid #000}.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{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{padding-top:1px;padding-bottom:1px;padding-left:40px;font-size:12px;font-weight:400}.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{padding-left:28px;font-weight:500}.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{padding-left:38px;font-weight:500}.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}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}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}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}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}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{position:fixed;top:0;max-width:15vw;max-height:70vh;overflow:auto}.back-to-top,.expand-toggle,.go-to-bottom{display:block;padding:4px 10px;margin-top:10px;margin-left:10px;font-size:12px;font-weight:500;color:#999}.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{width:20px;height:20px;display:block;border-radius:50%;margin-top:2px;margin-bottom:2px;margin-right:5px;background-position:50%;background-repeat:no-repeat;background-size:cover}.ui-user-icon.small{width:18px;height:18px;display:inline-block;vertical-align:middle;margin:0 0 .2em}.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;text-decoration:none;padding-left:22px}.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{border-radius:2px;background-color:#333}.inline-spoiler-section .spoiler-text>*{opacity:0}.inline-spoiler-section .spoiler-img{filter:blur(10px)}.inline-spoiler-section.raw{border-radius:2px;background-color:#333}.inline-spoiler-section.raw>*{opacity:0}.inline-spoiler-section.unveil{cursor:auto}.inline-spoiler-section.unveil .spoiler-text{background-color:rgba(51,51,51,.1)}.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{position:relative;z-index:1;color:#222}.markdown-body.slides:before{content:"";display:block;position:absolute;top:0;left:0;right:0;bottom:0;z-index:-1;background-color:currentColor;box-shadow:0 0 0 50vw}.markdown-body.slides section[data-markdown]{position:relative;margin-bottom:1.5em;background-color:#fff;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{position:absolute;top:50%;left:1em;right:1em;transform:translateY(-50%);max-height:100%;overflow:hidden}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{content:"";position:absolute;top:-1.5em;right:1em;height:1.5em;border:3px solid #777}.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;letter-spacing:.025em;font-family:Source Sans Pro,Helvetica,Arial,sans-serif}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-inner comment-enabled" data-hard-breaks="true"><p><span>Document Number: P2628R0</span><br>
<span>Date: 2022-07-01</span><br>
<span>Reply to: 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>
<span>Authors: Gonzalo Brito Gadeschi</span><br>
<span>Audience: Concurrency</span></p><style>
ins {
    color:green; 
    background-color:yellow;
    text-decoration:underline;
}
del { 
    color:red;
    background-color:yellow;
    text-decoration:line-through;
}
    .markdown-body { 
    max-width: 900px; 
}
</style><h1 id="Extend-barrier-APIs-with-memory_order" data-id="Extend-barrier-APIs-with-memory_order"><a class="anchor hidden-xs" href="#Extend-barrier-APIs-with-memory_order" title="Extend-barrier-APIs-with-memory_order"><span class="octicon octicon-link"></span></a><span>Extend </span><code>barrier</code><span> APIs with </span><code>memory_order</code></h1><p><span class="toc"><ul>
<li><a href="#Extend-barrier-APIs-with-memory_order" title="Extend barrier APIs with memory_order">Extend barrier APIs with memory_order</a><ul>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Tony-Tables" title="Tony Tables">Tony Tables</a></li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Compatibility-with-P2535" title="Compatibility with P2535">Compatibility with P2535</a></li>
</ul>
</li>
</ul>
</span></p><h2 id="Motivation" data-id="Motivation"><a class="anchor hidden-xs" href="#Motivation" title="Motivation"><span class="octicon octicon-link"></span></a><span>Motivation</span></h2><p><code>std::barrier</code><span> is a synchronization primitive that orders memory visibility across threads. Its operations - </span><code>arrive</code><span>, </span><code>wait</code><span>, </span><code>arrive_and_wait</code><span>, </span><code>arrive_and_drop</code><span> - guarantee visibility of </span><strong><span>all</span></strong><span> memory operations performed before the </span><code>arrive</code><span> to all threads that are unblocked from the </span><code>wait</code><span> (after they are unblocked from it).</span></p><p><span>Sometimes, guaranteeing the memory visibility of </span><strong><span>all</span></strong><span> memory operations is not required nor desired.</span></p><p><span>Examples:</span></p><ol>
<li><strong><span>Communicating “outside” the C++ abstract machine</span></strong><span>. Examples:</span>
<ol>
<li><span>Every thread participating in the barrier opens, writes to, and closes a file. Threads use a barrier to synchronize whether all files have been closed using </span><code>bar.arrive_and_wait(1, memory_order_relaxed)</code><span>. The memory visibility is ensured by the filesystem outside the C++ abstract machine. This is similar to how, e.g., </span><code>MPI_Ibarrier</code><span> does not establish cumulativity across MPI ranks for memory operations on </span><code>MPI_Windows</code><span>.</span></li>
<li><span>Every thread participating in the barrier is responsible for configuring a part of a machine via </span><code>volatile</code><span> operations. After the machine is configured, one thread should start it before releasing any threads from the barrier. Threads achieve this by using </span><code>memory_order_relaxed</code><span> arrive/wait operations together with a </span><code>CompletionFunction</code><span> that is run after the last thread arrived.</span></li>
</ol>
</li>
<li><strong><span>Object fences</span></strong><span>: </span><a href="https://wg21.link/P2535" target="_blank" rel="noopener"><span>P2535</span></a><span> - and </span><a href="https://wg21.link/p0153" target="_blank" rel="noopener"><span>P0153</span></a><span> before it - proposes </span><code>atomic_object_fence</code><span> and </span><code>atomic_message_fence</code><span>. These fences only apply to a sub-set of all objects and memory operations. This paper enables applications to compose </span><code>std::barrier</code><span> with </span><a href="https://wg21.link/P2535" target="_blank" rel="noopener"><span>P2535</span></a><span> fences. This is explored in its own section further below.</span></li>
</ol><p><span>Other synchronization primitives could be extended in an analogous way as well, but we choose to focus on </span><code>std::barrier</code><span> during the initial revisions of this paper. Some synchronization primitives like </span><code>std::atomic::wait</code><span> already expose a </span><code>memory_order</code><span> parameter.</span></p><h2 id="Tony-Tables" data-id="Tony-Tables"><a class="anchor hidden-xs" href="#Tony-Tables" title="Tony-Tables"><span class="octicon octicon-link"></span></a><span>Tony Tables</span></h2><table>
<thead>
<tr>
<th><strong><span>Before</span></strong></th>
<th><strong><span>After</span></strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><span>// Thread 0:</span><br><span>x = 1;</span><br><span>atomic_object_fence(memory_order_release, x);</span><br><span>bar.arrive(); // release fence</span><br><br><span>// Thread 1</span><br><span>bar.arrive_and_wait(); // acquire fence</span><br><span>atomic_object_fence(memory_order_acquire, x);</span><br><span>assert(x == 1);</span></td>
<td><span>// Thread 0:</span><br><span>x = 1;</span><br><span>atomic_object_fence(memory_order_release, x);</span><br><span>bar.arrive(</span><ins><span>1, memory_order_relaxed</span></ins><span>); // no fence</span><br><br><span>// Thread 1</span><br><span>bar.arrive_and_wait(</span><ins><span>memory_order_relaxed</span></ins><span>);  // no fence </span><br><span>atomic_object_fence(memory_order_acquire, x);</span><br><span>assert(x == 1);</span></td>
</tr>
</tbody>
</table><p><strong><span>Before</span></strong><span>: does not benefit from </span><code>atomic_object_fence</code><span> since the barrier operations insert full-memory fences.</span></p><p><strong><span>After</span></strong><span>: benefits from </span><code>atomic_object_fence</code><span> since the barrier inserts no fences.</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><blockquote>
<p><strong><span>Note</span></strong><span>: an implementation is available </span><a href="https://godbolt.org/z/b4WcjhEnP" target="_blank" rel="noopener"><span>here</span></a><span> in the </span><code>barrier_memory_order.hpp</code><span> file.</span></p>
</blockquote><p><a href="http://eel.is/c++draft/thread.barrier.class" target="_blank" rel="noopener"><span>thread.barrier.class</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class CompletionFunction = see below&gt;
  class barrier {
  public:
    using arrival_token = see below;

    static constexpr ptrdiff_t max() noexcept;

    constexpr explicit barrier(ptrdiff_t expected,
                               CompletionFunction f = CompletionFunction());
    ~barrier();

    barrier(const barrier&amp;) = delete;
    barrier&amp; operator=(const barrier&amp;) = delete;

    [[nodiscard]] arrival_token arrive(ptrdiff_t update = 1<ins>, memory_order = memory_order_release</ins>);
    void wait(arrival_token&amp;&amp; arrival<ins>, memory_order = memory_order_acquire</ins>) const;

    void arrive_and_wait(<ins>ptrdiff_t update = 1, memory_order = memory_order_acq_rel</ins>);
    void arrive_and_drop(<ins>ptrdiff_t update = 1, memory_order = memory_order_release</ins>);

  private:
    CompletionFunction completion;      // exposition only
  };
}
</code></pre><blockquote>
<p><strong><span>Unresolved question:</span></strong><span> should we add </span><code>update = 1</code><span> parameters to the APIs that lack them? This revision does that only to show how that would look like.</span></p>
</blockquote><ol>
<li>
<p><span>Each barrier phase consists of the following steps:</span></p>
<ol>
<li><span>The expected count is decremented by each call to </span><code>arrive</code><span> or </span><code>arrive_and_drop</code><span>.</span></li>
<li><span>When the expected count reaches zero, the phase completion step is run. For the specialization with the default value of the </span><code>CompletionFunction</code><span> template parameter, the completion step is run as part of the call to </span><code>arrive</code><span> or </span><code>arrive_and_drop</code><span> that caused the expected count to reach zero. For other specializations, the completion step is run on one of the threads that arrived at the barrier during the phase.</span></li>
<li><span>When the completion step finishes, the expected count is reset to what was specified by the expected argument to the constructor, possibly adjusted by calls to </span><code>arrive_and_drop</code><span>, and the next phase starts.</span></li>
</ol>
</li>
<li>
<p><span>Each phase defines a phase synchronization point. Threads that arrive at the barrier during the phase can block on the phase synchronization point by calling </span><code>wait</code><span>, and will remain blocked until the phase completion step is run.</span></p>
</li>
<li>
<p><span>The phase completion step that is executed at the end of each phase has the following effects:</span></p>
<ol>
<li><span>Invokes the completion function, equivalent to </span><code>completion()</code><span>.</span></li>
<li><span>Unblocks all threads that are blocked on the phase synchronization point.</span></li>
</ol>
<p><ins><strong><span>UNRESOLVED QUESTION</span></strong><span>: do we need to change something else around here or does the “as if” below in “4.” suffice?</span></ins></p>
<p><span>The end of the completion step strongly happens before the returns from all calls that were unblocked by the completion step. For specializations that do not have the default value of the CompletionFunction template parameter, the behavior is undefined if any of the barrier object’s member functions other than </span><code>wait</code><span> are called while the completion step is in progress.</span></p>
</li>
<li>
<p><span>Concurrent invocations of the member functions of barrier, other than its destructor, do not introduce data races</span><ins><span> as if they were atomic operations performed with the </span><code>memory_order</code><span> associated with them</span></ins><span>. The member functions </span><code>arrive</code><span> and </span><code>arrive_and_drop</code><span> execute atomically.</span></p>
</li>
<li>
<p><code>CompletionFunction</code><span> shall meet the </span><code>Cpp17MoveConstructible</code><span> (Table 30) and </span><code>Cpp17Destructible</code><span> (Table 34) requirements. </span><code>is_nothrow_invocable_v&lt;CompletionFunction&amp;&gt;</code><span> shall be true.</span></p>
</li>
<li>
<p><span>The default value of the </span><code>CompletionFunction</code><span> template parameter is an unspecified type, such that, in addition to satisfying the requirements of </span><code>CompletionFunction</code><span>, it meets the </span><code>Cpp17DefaultConstructible</code><span> requirements (Table 29) and </span><code>completion()</code><span> has no effects.</span></p>
</li>
<li>
<p><code>barrier::arrival_token</code><span> is an unspecified type, such that it meets the </span><code>Cpp17MoveConstructible</code><span> (Table 30), </span><code>Cpp17MoveAssignable</code><span> (Table 32), and </span><code>Cpp17Destructible</code><span> (Table 34) requirements.</span></p>
</li>
</ol><pre><code>static constexpr ptrdiff_t max() noexcept;</code></pre><ul>
<li><span>Returns: The maximum expected count that the implementation supports.</span></li>
</ul><pre><code>constexpr explicit barrier(ptrdiff_t expected,
                           CompletionFunction f = CompletionFunction());</code></pre><ul>
<li>
<p><span>Preconditions: </span><code>expected &gt;= 0</code><span> is true and </span><code>expected &lt;= max()</code><span> is true.</span></p>
</li>
<li>
<p><span>Effects: Sets both the initial expected count for each barrier phase and the current expected count for the first phase to expected. Initializes completion with </span><code>std::move(f)</code><span>. Starts the first phase.</span></p>
<p><span>[Note 1: If expected is 0 this object can only be destroyed. — end note]</span></p>
</li>
<li>
<p><span>Throws: Any exception thrown by </span><code>CompletionFunction</code><span>’s move constructor.</span></p>
</li>
</ul><pre><code>[[nodiscard]] arrival_token arrive(ptrdiff_t update = 1<ins>, memory_order order = memory_order_release</ins>);</code></pre><ul>
<li>
<p><span>Preconditions: </span><code>update &gt; 0</code><span> is true,</span><del><span> and</span></del><span> </span><code>update</code><span> is less than or equal to the expected count for the current barrier phase</span><ins><span>, and </span><code>order</code><span> is </span><code>memory_order_relaxed</code><span> or </span><code>memory_order_release</code></ins><span>.</span></p>
</li>
<li>
<p><span>Effects: Constructs an object of type </span><code>arrival_token</code><span> that is associated with the phase synchronization point for the current phase. Then, decrements the expected count by </span><code>update</code><span>.</span></p>
</li>
<li>
<p><span>Synchronization: The call to arrive strongly happens before the start of the phase completion step for the current phase.</span></p>
</li>
<li>
<p><span>Returns: The constructed </span><code>arrival_token</code><span> object.</span></p>
</li>
<li>
<p><span>Throws: </span><code>system_error</code><span> when an exception is required ([thread.req.exception]).</span></p>
</li>
<li>
<p><span>Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).</span></p>
<p><span>[Note 2: This call can cause the completion step for the current phase to start. — end note]</span></p>
</li>
</ul><pre><code>void wait(arrival_token&amp;&amp; arrival<ins>, memory_order order = memory_order_acquire</ins>) const;</code></pre><ul>
<li>
<p><span>Preconditions: arrival is associated with the phase synchronization point for the current phase or the immediately preceding phase of the same barrier object</span><ins><span>, and </span><code>order</code><span> is </span><code>memory_order_relaxed</code><span> or </span><code>memory_order_acquire</code></ins><span>.</span></p>
</li>
<li>
<p><span>Effects: Blocks at the synchronization point associated with </span><code>std::move(arrival)</code><span> until the phase completion step of the synchronization point’s phase is run.</span></p>
<p><span>[Note 3: If arrival is associated with the synchronization point for a previous phase, the call returns immediately. — end note]</span></p>
</li>
<li>
<p><span>Throws: </span><code>system_error</code><span> when an exception is required ([thread.req.exception]).</span></p>
</li>
<li>
<p><span>Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).</span></p>
</li>
</ul><pre><code>void arrive_and_wait(<ins>ptrdiff_t update = 1, memory_order order = memory_order_acq_rel</ins>);</code></pre><ul>
<li><ins><span>Preconditions: </span><code>order</code><span> is </span><code>memory_order_relaxed</code><span> or </span><code>memory_order_acq_rel</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><pre><code><span>order_arrive = order == memory_order_acq_rel? memory_order_release : order;</span><br>
<span>order_wait = order == memory_order_acq_rel? memory_order_acquire : order;</span><br>
<span>wait(arrive(</span><ins><span>update, order_arrive</span></ins><span>)</span><ins><span>, order_wait</span></ins><span>);</span></code></pre><span>.</span></li>
</ul><pre><code>void arrive_and_drop(<ins>ptrdiff_t update = 1, memory_order order = memory_order_release</ins>);</code></pre><ul>
<li><span>Preconditions: The expected count for the current barrier phase is greater than zero</span><ins><span>, </span><code>update &gt; 0</code><span> is true, </span><code>update</code><span> is less than or equal to the expected count for the current barrier phase, and </span><code>order</code><span> is </span><code>memory_order_relaxed</code><span> or </span><code>memory_order_release</code></ins><span>.</span></li>
</ul><blockquote>
<p><strong><span>Rationale for using </span><code>update</code><span> for initial and current phase counts</span></strong><span>: safety, this prevents the initial count from going under the current count accidentaly.</span></p>
</blockquote><ul>
<li>
<p><span>Effects: Decrements the initial expected count for all subsequent phases by </span><del><span>one</span></del><ins><span>update</span></ins><span>. Then decrements the expected count for the current phase by </span><del><span>one</span></del><ins><span>update</span></ins><span>.</span></p>
</li>
<li>
<p><span>Synchronization: The call to </span><code>arrive_and_drop</code><span> strongly happens before the start of the phase completion step for the current phase.</span></p>
</li>
<li>
<p><span>Throws: </span><code>system_error</code><span> when an exception is required ([thread.req.exception]).</span></p>
</li>
<li>
<p><span>Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).</span></p>
<p><span>[Note 4: This call can cause the completion step for the current phase to start. — end note]</span></p>
</li>
</ul><h2 id="Compatibility-with-P2535" data-id="Compatibility-with-P2535"><a class="anchor hidden-xs" href="#Compatibility-with-P2535" title="Compatibility-with-P2535"><span class="octicon octicon-link"></span></a><span>Compatibility with </span><a href="https://wg21.link/p2535" target="_blank" rel="noopener"><span>P2535</span></a></h2><p><a href="https://wg21.link/P2535" target="_blank" rel="noopener"><span>P2535</span></a><span> (and </span><a href="https://wg21.link/p0153" target="_blank" rel="noopener"><span>P0153</span></a><span> before it) propose extending C++ with object fences. If we were to add object fences to C++, it could make sense to further extend </span><code>barrier</code><span> APIs to support them, e.g., as follows:</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">int</span><span class="token operator">&amp;</span> data<span class="token punctuation">;</span>
data <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
bar_x<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> obj_fence<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar_y<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> obj_fence<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>These APIs would be semantically similar - although not identical - to the following code using the APIs in this proposal.</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></div><div class="code"><span class="token keyword">int</span><span class="token operator">&amp;</span> data<span class="token punctuation">;</span>
data <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token function">atomic_object_fence</span><span class="token punctuation">(</span>memory_order_release<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar_x<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">atomic_object_fence</span><span class="token punctuation">(</span>memory_order_release<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar_y<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>Combining both APIs is still valuable since it allows power users to write code with less fences where necessary:</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">int</span><span class="token operator">&amp;</span> data<span class="token punctuation">;</span>
data <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token function">atomic_object_fence</span><span class="token punctuation">(</span>memory_order_release<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar_x<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar_y<span class="token punctuation">.</span><span class="token function">arrive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">;</span>
</div></div></code></pre></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="#Extend-barrier-APIs-with-memory_order" title="Extend barrier APIs with memory_order">Extend barrier APIs with memory_order</a><ul class="nav">
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Tony-Tables" title="Tony Tables">Tony Tables</a></li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Compatibility-with-P2535" title="Compatibility with P2535">Compatibility with P2535</a></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="#Extend-barrier-APIs-with-memory_order" title="Extend barrier APIs with memory_order">Extend barrier APIs with memory_order</a><ul class="nav">
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Tony-Tables" title="Tony Tables">Tony Tables</a></li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Compatibility-with-P2535" title="Compatibility with P2535">Compatibility with P2535</a></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>
