<!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>
        Expose `std::atomic_ref` &apos;s object address
    </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-alert{border-left-style:solid;border-left-width:4px;color:inherit;margin-bottom:16px;padding:8px 16px}.markdown-alert .markdown-alert-title{align-items:center;display:flex;font-weight:500;line-height:1;white-space:break-spaces}.markdown-body .markdown-alert>*{margin-bottom:0;margin-top:16px}.markdown-body .markdown-alert .selection-popover,.markdown-body .markdown-alert>:first-child{margin-top:0}.markdown-alert.markdown-alert-note{border-left-color:#0969da}.markdown-alert.markdown-alert-note .markdown-alert-title{fill:currentColor;color:#0969da}.markdown-alert.markdown-alert-tip{border-left-color:#1a7f37}.markdown-alert.markdown-alert-tip .markdown-alert-title{fill:currentColor;color:#1a7f37}.markdown-alert.markdown-alert-important{border-left-color:#8250df}.markdown-alert.markdown-alert-important .markdown-alert-title{fill:currentColor;color:#8250df}.markdown-alert.markdown-alert-warning{border-left-color:#9a6700}.markdown-alert.markdown-alert-warning .markdown-alert-title{fill:currentColor;color:#9a6700}.markdown-alert.markdown-alert-caution{border-left-color:#d1242f}.markdown-alert.markdown-alert-caution .markdown-alert-title{fill:currentColor;color:#d1242f}.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 pre.pseudocode{white-space-collapse:collapse}.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-inner comment-enabled" data-hard-breaks="true" style=""><p><span>Document Number: P2835R4.</span><br>
<span>Date: 2024-05-21.</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, Mark Hoemmen, Carter H. Edwards, Bryce Adelstein Lelbach.</span><br>
<span>Audience: LEWG.</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="Expose-stdatomic_ref-s-object-address" data-id="Expose-stdatomic_ref-s-object-address" style=""><a class="anchor hidden-xs" href="#Expose-stdatomic_ref-s-object-address" title="Expose-stdatomic_ref-s-object-address"><span class="octicon octicon-link"></span></a><span>Expose </span><code>std::atomic_ref</code><span> 's object address</span></h1><p><span class="toc"><ul>
<li><a href="#Expose-stdatomic_ref-s-object-address" title="Expose std::atomic_ref 's object address">Expose std::atomic_ref 's object address</a><ul>
<li><a href="#Changelog" title="Changelog">Changelog</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Before-and-after-Tony-tables" title="Before-and-after (&quot;Tony&quot;) tables">Before-and-after ("Tony") tables</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a><ul>
<li><a href="#Intent-of-atomic_ref-proposal" title="Intent of atomic_ref proposal">Intent of atomic_ref proposal</a></li>
</ul>
</li>
<li><a href="#Use-cases" title="Use cases">Use cases</a><ul>
<li><a href="#Atomic-access-to-elements-of-a-data-structure" title="Atomic access to elements of a data structure">Atomic access to elements of a data structure</a></li>
<li><a href="#Contention-aware-data-structures" title="Contention-aware data-structures">Contention-aware data-structures</a></li>
</ul>
</li>
<li><a href="#Design" title="Design">Design</a></li>
<li><a href="#Impact-on-implementations" title="Impact on implementations">Impact on implementations</a></li>
<li><a href="#Wording" title="Wording">Wording</a></li>
</ul>
</li>
</ul>
</span></p><h2 id="Changelog" data-id="Changelog" style=""><a class="anchor hidden-xs" href="#Changelog" title="Changelog"><span class="octicon octicon-link"></span></a><span>Changelog</span></h2><ul>
<li><span>R4: St. Louis</span>
<ul>
<li>
<p><span>Switched to use </span><code>uintptr_t</code><span>.</span></p>
</li>
<li>
<p><span>(REVERTED) Update the return type from </span><code>const void *</code><span> to </span><code>address_return_t</code><span> which copies the cv-qualifiers of T; updated examples, godbolt samples, and returns clause accordingly.</span></p>
</li>
<li>
<p><a href="https://github.com/cplusplus/papers/issues/1545#issuecomment-2028998320" target="_blank" rel="noopener"><span>Include tokyo poll</span></a><span>:</span></p>
<ul>
<li><span>POLL:_ Forward “P2835R3: Expose std::atomic_ref 's object address” to LWG for C++26 (to be confirmed by an electronic poll).</span></li>
</ul>
<table>
<thead>
<tr>
<th><span>SF</span></th>
<th><span>F</span></th>
<th><span>N</span></th>
<th><span>A</span></th>
<th><span>SA</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><span>5</span></td>
<td><span>8</span></td>
<td><span>3</span></td>
<td><span>0</span></td>
<td><span>0</span></td>
</tr>
</tbody>
</table>
</li>
</ul>
<span>Outcome: Consensus in favor</span></li>
<li><span>R3: LEWG mailing list review</span>
<ul>
<li><span>Per request by one reviewer on the LEWG mailing list, three coauthors of P0019 (Carter H. Edwards, Mark Hoemmen, and Bryce Adelstein Lelbach) joined this proposal to express their approval.</span></li>
<li><span>Added background section.</span></li>
<li><span>Added history of why this API was not part of the original paper.</span></li>
<li><span>Update return type to </span><code>const void*</code><span>.</span></li>
<li><span>Rename API to </span><code>address()</code><span>.</span></li>
<li><span>Added rationale against </span><code>uintptr_t</code><span>.</span></li>
<li><span>Added rationale against </span><code>get()</code><span> and </span><code>data()</code><span>.</span></li>
<li><span>Add new use cases and examples.</span></li>
<li><span>Removed Discovery Patterns example.</span></li>
</ul>
</li>
<li><span>R2: Preparation for mailing list review</span>
<ul>
<li><span>Update links to compiler explorer.</span></li>
<li><span>Update API design rationale.</span></li>
<li><span>Update </span><code>__cpp_lib_atomic_ref</code><span> macro.</span></li>
</ul>
</li>
<li><span>R1:</span>
<ul>
<li><span>Add alternative API designs.</span></li>
</ul>
</li>
<li><span>R0: initial revision (Varna)</span></li>
</ul><h2 id="Introduction" data-id="Introduction" style=""><a class="anchor hidden-xs" href="#Introduction" title="Introduction"><span class="octicon octicon-link"></span></a><span>Introduction</span></h2><p><span>Applications that need atomic access to an object and want to reason about contention for performance cannot use C++20 </span><code>std::atomic_ref</code><span>. Some applications may change the object's storage type to </span><code>std::atomic</code><span>, but </span><code>std::atomic_ref</code><span>'s raison d'être is that many applications cannot.</span></p><p><span>This proposal extends </span><code>std::atomic_ref</code><span> with a member function that returns the object's address. This enables legacy applications that updated their APIs from </span><code>volatile int*</code><span> to </span><code>atomic_ref</code><span> to become conforming with the post-C++11 memory model, to recover the optimizations they lost while doing so, while enabling applications still stuck with </span><code>volatile*</code><span> on their APIs to migrate to use </span><code>atomic_ref</code><span>.</span></p><h2 id="Before-and-after-Tony-tables" data-id="Before-and-after-Tony-tables" style=""><a class="anchor hidden-xs" href="#Before-and-after-Tony-tables" title="Before-and-after-Tony-tables"><span class="octicon octicon-link"></span></a><span>Before-and-after ("Tony") tables</span></h2><table>
<tbody><tr>
<td>
<p><strong><span>Before</span></strong></p>
</td>
<td>
<p><strong><span>After</span></strong></p>
</td>
</tr><tr>
<td>
<pre><code class="cpp hljs"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">&lt;atomic&gt;</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">&lt;cassert&gt;</span></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> data<span class="token punctuation">;</span>

<span class="token keyword">void</span> <span class="token function">fn</span><span class="token punctuation">(</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><span class="token operator">&amp;</span> ref<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">auto</span><span class="token operator">*</span> addr <span class="token operator">=</span> <span class="token operator">&amp;</span>ref<span class="token punctuation">;</span>
    <span class="token function">assert</span><span class="token punctuation">(</span> <span class="token operator">&amp;</span>data <span class="token operator">==</span> <span class="token operator">&amp;</span>ref <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">fn</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
<td>
<pre><code class="cpp hljs"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">&lt;atomic&gt;</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">&lt;cassert&gt;</span></span>

<span class="token keyword">int</span> data<span class="token punctuation">;</span>

<span class="token keyword">void</span> <span class="token function">fn</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> ref<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token keyword">void</span><span class="token operator">*</span> addr <span class="token operator">=</span> ref<span class="token punctuation">.</span><span class="token function">address</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> <span class="token operator">&amp;</span>data <span class="token operator">==</span> ref<span class="token punctuation">.</span><span class="token function">address</span><span class="token punctuation">(</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> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">fn</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token punctuation">{</span>data<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
</tr>
</tbody></table><h2 id="Motivation" data-id="Motivation" style=""><a class="anchor hidden-xs" href="#Motivation" title="Motivation"><span class="octicon octicon-link"></span></a><span>Motivation</span></h2><p><code>std::atomic_ref&lt;T&gt;</code><span> ensures that all accesses to an existing </span><code>T</code><span> object are atomic.</span><br>
<span>Unlike with </span><code>std::atomic&lt;T&gt;</code><span>, for </span><code>std::atomic_ref&lt;T&gt;</code><span>, the </span><code>T</code><span> object exists and its lifetime strictly includes all </span><code>std::atomic_ref&lt;T&gt;</code><span> that refer to it.</span></p><p><span>Therefore, a </span><code>T</code><span> object that is used with </span><code>std::atomic_ref&lt;T&gt;</code><span> could be accessed with both atomic and non-atomic operations during its lifetime (in contrast to </span><code>std::atomic&lt;T&gt;</code><span>).</span></p><p><span>However, as long as one or more live </span><code>std::atomic_ref</code><span>s still reference the </span><code>T</code><span> object, the object can only be accessed through these </span><code>std::atomic_ref</code><span>s.  That is, non-atomic accesses are not allowed to be concurrent with accesses through </span><code>std::atomic_ref</code><span>.</span></p><blockquote>
<p><strong><span>Note</span></strong><span>: this enables implementations of </span><code>atomic_ref&lt;T&gt;</code><span> to, e.g., copy the value into an </span><code>atomic&lt;T&gt;</code><span> which is in a different memory location, operate on that, and once the last </span><code>atomic_ref</code><span> is destroyed, copy the value back (for which implementations must track the address of the original object's location).  This proposal does not recommend such an implementation, but it is legal.</span></p>
</blockquote><p><span>The following examples illustrate </span><code>atomic_ref</code><span> semantics.</span></p><p><span>This example is well-defined: non-atomic accesses to </span><code>data</code><span> happen only while there are no live </span><code>atomic_ref</code><span>s that reference </span><code>data</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>
<span></span>
<span></span></div><div class="code"><span class="token keyword">int</span> data <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">;</span> <span class="token comment">// Non-Atomic access</span>
<span class="token punctuation">{</span>
    <span class="token function">assert</span><span class="token punctuation">(</span>data <span class="token operator">==</span> <span class="token number">13</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> r<span class="token punctuation">{</span>data<span class="token punctuation">}</span><span class="token punctuation">;</span>
    r<span class="token punctuation">.</span><span class="token function">store</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Atomic access</span>
<span class="token punctuation">}</span> <span class="token comment">// All atomic_refs are destroyed here</span>

<span class="token comment">// No atomic_refs are live:</span>
<span class="token function">assert</span><span class="token punctuation">(</span>data <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
data <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>This example exhibits undefined behavior: a non-atomic access to </span><code>data</code><span> happens while there is still a live </span><code>atomic_ref</code><span> that references </span><code>data</code><span>.</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">int</span> data <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">;</span>           <span class="token comment">// Non-Atomic access</span>
atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> r<span class="token punctuation">{</span>data<span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// atomic_ref live </span>
data <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>               <span class="token comment">// UB: object accessed during lifetime of atomic_ref that refers to it</span>
</div></div></code></pre><p><span>The implementation of APIs using </span><code>std::atomic&lt;T&gt;*</code><span> may obtain the object address without breaking API changes.</span></p><pre><code class="cpp hljs"><span class="token keyword">void</span> <span class="token function">api_atomic</span><span class="token punctuation">(</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><span class="token operator">*</span> ptr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// can obtain address of underlying object:</span>
    uintptr_t address <span class="token operator">=</span> <span class="token generic-function"><span class="token function">reinterpret_cast</span><span class="token generic class-name"><span class="token operator">&lt;</span>uintptr_t<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>ptr<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><span>The implementation of APIs using </span><code>std::atomic_ref&lt;T&gt;</code><span> may not:</span></p><pre><code class="cpp hljs"><span class="token keyword">void</span> <span class="token function">api_atomic_ref</span><span class="token punctuation">(</span>atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> ref<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...cannot obtain the address of underlying object</span>
    <span class="token comment">// if constexpr(sizeof(ref) == sizeof(uintptr_t)) {</span>
    <span class="token comment">//   uintptr_t address = reinterpret_cast&lt;uintptr_t&gt;(&amp;ref); // UB</span>
    <span class="token comment">// }</span>
<span class="token punctuation">}</span>
</code></pre><p><span>This proposal extends the </span><code>atomic_ref</code><span> API with a member function </span><code>address()</code><span> to obtain the underlying object's address.</span></p><pre><code class="cpp hljs"><span class="token keyword">void</span> <span class="token function">api_atomic_ref_this_paper</span><span class="token punctuation">(</span>atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> ref<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// With this proposal, one can get the underlying object's address</span>
    uintptr_t address <span class="token operator">=</span> <span class="token generic-function"><span class="token function">reinterpret_cast</span><span class="token generic class-name"><span class="token operator">&lt;</span>uintptr_t<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>ref<span class="token punctuation">.</span><span class="token function">address</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h3 id="Intent-of-atomic_ref-proposal" data-id="Intent-of-atomic_ref-proposal" style=""><a class="anchor hidden-xs" href="#Intent-of-atomic_ref-proposal" title="Intent-of-atomic_ref-proposal"><span class="octicon octicon-link"></span></a><span>Intent of </span><code>atomic_ref</code><span> proposal</span></h3><p><span>The paper that introduced </span><code>atomic_ref</code><span> in C++ 20 is </span><a href="https://wg21.link/P0019R8" target="_blank" rel="noopener"><span>P0019R8</span></a><span>. The authors discussed this use case and decided the application should track </span><code>&amp;data</code><span> themselves. However, APIs evolve as usage patterns emerge: SG1 reviewed this paper to address this oversight, and forwarded it with </span><em><span>unanimous consent</span></em><span>. Multiple authors of the original </span><code>atomic_ref</code><span> paper are co-authors of this paper.</span></p><h2 id="Use-cases" data-id="Use-cases" style=""><a class="anchor hidden-xs" href="#Use-cases" title="Use-cases"><span class="octicon octicon-link"></span></a><span>Use cases</span></h2><p><span>This proposal enables legacy APIs that are still using </span><code>volatile*</code><span> to signal concurrency, due to their implementations needing the object's address internally (see Motivation), to finally migrate to the C++11 Memory Model.</span></p><p><span>Some of the reasons why these APIs need the object address are covered in this section. Others, like "C Foreign Function Interface (FFI)," are not currently covered in this document.</span></p><h3 id="Atomic-access-to-elements-of-a-data-structure" data-id="Atomic-access-to-elements-of-a-data-structure" style=""><a class="anchor hidden-xs" href="#Atomic-access-to-elements-of-a-data-structure" title="Atomic-access-to-elements-of-a-data-structure"><span class="octicon octicon-link"></span></a><span>Atomic access to elements of a data structure</span></h3><p><span>Applications that want to perform atomic access to the elements of a data structure need to make the data structure's element type </span><code>atomic</code><span>,</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code">std<span class="token double-colon punctuation">::</span>array<span class="token operator">&lt;</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><span class="token punctuation">,</span> N<span class="token operator">&gt;</span> array<span class="token punctuation">;</span>
</div></div></code></pre><p><span>and use pointers to </span><code>atomic</code><span> objects to access the elements.</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">int</span> <span class="token function">fetch_add_idx</span><span class="token punctuation">(</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><span class="token operator">*</span> base<span class="token punctuation">,</span> size_t i<span class="token punctuation">,</span> <span class="token keyword">int</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> base<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">fetch_add</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</div></div></code></pre><p><span>When the array is provided externally, e.g., from a third-party C API,</span><br>
<span>it is typically an array of </span><code>T</code><span>, not an array of </span><code>atomic&lt;T&gt;</code><span>.</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span></div><div class="code"><span class="token keyword">extern</span> <span class="token keyword">int</span> array<span class="token punctuation">[</span>N<span class="token punctuation">]</span><span class="token punctuation">;</span>
</div></div></code></pre><p><span>Before </span><code>atomic_ref</code><span> was introduced in C++20, it was common practice for applications to create APIs that drop the "atomicity" semantics.  Such applications would use </span><code>volatile</code><span> (with nonstandard meaning) to express their intent.</span></p><pre><code class="cpp hljs"><div class="wrapper"><div class="gutter linenumber"><span></span>
<span></span>
<span></span></div><div class="code"><span class="token keyword">int</span> <span class="token function">fetch_add_idx</span><span class="token punctuation">(</span><span class="token comment">/* not atomic */</span> <span class="token keyword">int</span> <span class="token keyword">volatile</span><span class="token operator">*</span> base<span class="token punctuation">,</span> size_t i<span class="token punctuation">,</span> <span class="token keyword">int</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token punctuation">{</span>base<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">fetch_add</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</div></div></code></pre><p><span>However, it is not possible for applications written in Standard C++ to encode "atomicity" semantics as part of their API without a way to extract the underlying's object address.  This proposal provides that way: the </span><code>address</code><span> member function.</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 function">fetch_add_idx</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> base<span class="token punctuation">,</span> size_t i<span class="token punctuation">,</span> <span class="token keyword">int</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">auto</span> p <span class="token operator">=</span> <span class="token generic-function"><span class="token function">static_cast</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">*</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>base<span class="token punctuation">.</span><span class="token function">address</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">return</span> std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token punctuation">{</span><span class="token operator">*</span><span class="token punctuation">(</span>p<span class="token operator">+</span>i<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">fetch_add</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</div></div></code></pre><p><span>This matches the original intended use case of </span><code>std::atomic_ref&lt;T&gt;</code><span>, namely accessing the elements of an existing array of </span><code>T</code><span> atomically.</span></p><p><span>In fact, for the partiular case of contiguous data structures, like the array above, </span><code>std::atomic_ref</code><span> was specifically designed to be a proxy reference type for </span><code>mdspan</code><span> accessors. The </span><code>atomic_accessor</code><span> class in </span><a href="https://wg21.link/p2689" target="_blank" rel="noopener"><span>P2689</span></a><span> has an </span><code>access(T* p, size_t i)</code><span> member function that returns </span><code>std::atomic_ref{*(p+i)}</code><span>. The </span><code>mdspan</code><span> proposal </span><a href="https://wg21.link/p0009" target="_blank" rel="noopener"><span>P0009</span></a><span> used </span><code>atomic_ref</code><span> and its corresponding accessor as justification for </span><code>mdspan</code><span> permitting custom accessors. (See e.g., the "Why custom accessors?" section of P0009.)</span></p><h3 id="Contention-aware-data-structures" data-id="Contention-aware-data-structures" style=""><a class="anchor hidden-xs" href="#Contention-aware-data-structures" title="Contention-aware-data-structures"><span class="octicon octicon-link"></span></a><span>Contention-aware data-structures</span></h3><p><span>Contention-aware data-structures rely on the object's address to tell different objects apart. The addresses are then used to, e.g., index into global lock tables.</span></p><p><span>Feedback during LEWG mailing review suggested that examples that were too advanced were unapproachable. R2 of the paper provided a fully working implementation of one such example in compiler-explorer, demonstrating a 1.25x performance improvement from this API. Similar algorithms are part of, e.g., C++ standard library implementations (e.g., </span><a href="https://github.com/NVIDIA/cccl/blob/b7d4228ab7268ed928984cd61096079bd671d25d/libcudacxx/include/cuda/std/detail/libcxx/include/__cuda/barrier.h#L231-L250" target="_blank" rel="noopener"><span>here</span></a><span>).</span></p><p><span>The following example (</span><a href="https://gcc.godbolt.org/z/9TebvT4Ge" target="_blank" rel="noopener"><span>godbolt</span></a><span>) illustrate how concurrent algorithms and data structures typically detect and react to contention in practice.  First, they obtain the object's address to tell it apart from other objects.  They often hash it.  Then, they use the (possibly hashed) address to index into global data structures (e.g., lock tables or timer tables) to improve contention.  Without this proposal, an API-breaking change would be required in order to apply these optimizations to an API that only accepts an </span><code>atomic_ref</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>
<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">constexpr</span> std<span class="token double-colon punctuation">::</span>size_t nary <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>array<span class="token operator">&lt;</span>std<span class="token double-colon punctuation">::</span>atomic<span class="token operator">&lt;</span>std<span class="token double-colon punctuation">::</span>size_t<span class="token operator">&gt;</span><span class="token punctuation">,</span> nary<span class="token operator">&gt;</span> contention<span class="token punctuation">;</span>

<span class="token comment">// Adds one to v (waits until contention is low):</span>
<span class="token keyword">void</span> <span class="token function">add_one</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>atomic_ref<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> v<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// NEEDS P2835: Get atomic_ref object address:</span>
    <span class="token keyword">auto</span> a <span class="token operator">=</span> <span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>uintptr_t<span class="token punctuation">)</span>v<span class="token punctuation">.</span><span class="token function">address</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// Hash address (or cache line address, etc.) by truncating </span>
    <span class="token comment">// to 32-bit and multiplying by Golden Ratio:</span>
    <span class="token keyword">auto</span> h <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span><span class="token keyword">uint32_t</span><span class="token punctuation">)</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>uintptr_t<span class="token punctuation">)</span>a<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">2654435761</span><span class="token punctuation">;</span>
    
    <span class="token comment">// Check for potential contention:</span>
    <span class="token keyword">auto</span> k <span class="token operator">=</span> h <span class="token operator">%</span> nary<span class="token punctuation">;</span>
    <span class="token keyword">auto</span> l <span class="token operator">=</span> contention<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">fetch_add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// Wait until contention is low (&lt;2 contending threads):</span>
    <span class="token keyword">while</span> <span class="token punctuation">(</span>contention<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// Modify object and drop from contention table:</span>
    v<span class="token punctuation">.</span><span class="token function">fetch_add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    contention<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">fetch_sub</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</div></div></code></pre><h2 id="Design" data-id="Design" style=""><a class="anchor hidden-xs" href="#Design" title="Design"><span class="octicon octicon-link"></span></a><span>Design</span></h2><p><span>The name and return type should prevent accidental misuse that could result from accessing the object through the address while there are still live </span><code>atomic_ref</code><span> that reference it.</span></p><p><span>We considered the following options.</span></p><ul>
<li><span>Return type:</span>
<ul>
<li><code>uintptr_t</code><span>:</span>
<ul>
<li><span>PRO: Correctly suggest that the value should not be used to access the object.</span></li>
<li><span>CON: it is an optional type, and therefore APIs using it must be optional.</span></li>
</ul>
</li>
<li><code>T const*</code><span>:</span>
<ul>
<li><span>PRO: works.</span></li>
<li><span>CON: makes it too easy for developers to accidentally access the referenced object while there are still live </span><code>atomic_ref</code><span> objects, resulting in undefined behavior.</span></li>
</ul>
</li>
<li><code>void volatile const*</code><span>:</span>
<ul>
<li><span>PRO: prevents accidental misuse and is not optional.</span></li>
<li><span>CON: requires casting </span><code>const</code><span> and </span><code>volatile</code><span> .</span></li>
</ul>
</li>
<li><code>address_return_t</code><span>: copies cv-qualifiers of </span><code>T</code>
<ul>
<li><span>PRO: prevents accidental misuse and is not optional.</span></li>
<li><span>CON: quite complex, for no good reason:</span></li>
</ul>
</li>
</ul>
</li>
</ul><pre><code class="c++ hljs"><span class="hljs-keyword">using</span> <span class="hljs-type">address_return_t</span> 
  = <span class="hljs-type">conditional_t</span>&lt;is_const_v&lt;T&gt; &amp;&amp; is_volatile_v&lt;T&gt;, <span class="hljs-type">void</span> <span class="hljs-type">const</span> <span class="hljs-keyword">volatile</span>*, 
    <span class="hljs-type">conditional_t</span>&lt;is_const_v&lt;T&gt;, <span class="hljs-type">void</span> <span class="hljs-type">const</span>*, 
    <span class="hljs-type">conditional_t</span>&lt;is_volatile_v&lt;T&gt;, <span class="hljs-type">void</span> <span class="hljs-keyword">volatile</span>*, 
    <span class="hljs-type">void</span>*&gt;&gt;&gt;;
</code></pre><ul>
<li><span>Name:</span>
<ul>
<li><code>data</code><span>: Throughout the Standard Library, types with a </span><code>data</code><span> member function always have a </span><code>size</code><span> member function.  The two functions together indicate that the type represents a contiguous range.  A </span><code>data</code><span> member function would thus incorrectly suggest that </span><code>atomic_ref</code><span> also represents a contiguous range.  Also, </span><code>mdspan</code><span> deliberately rejected the name </span><code>data</code><span> in favor of </span><code>data_handle</code><span>, because </span><code>mdspan</code><span> might not actually view a contiguous range and because </span><code>data_handle_type</code><span> might not necessarily be </span><code>element_type*</code><span>.</span></li>
<li><code>get</code><span>: All Standard Library types with a </span><code>get</code><span> member function return a pointer.</span></li>
<li><code>ref</code><span>: A name with "ref" or "reference" in it would incorrectly suggest that the return value may be used to access the object, just like </span><code>std::reference_wrapper</code><span>.</span></li>
<li><code>address</code><span>: Indicates that the intent of the API is returning the object's address only.  Does not suggest that the address may be used to access the object.  (Returning </span><code>uintptr_t</code><span> would suggest this even more strongly, but this is not possible, for the reasons listed above.)</span></li>
<li><code>unsafe_address</code><span>: This would be more explicit.  However, there is nothing "unsafe" about getting the address; only accessing the object through the address would be unsafe.</span></li>
</ul>
</li>
</ul><p><span>This design proposes using </span><code>uintptr_t</code><span> as the return type, and </span><code>address</code><span> as the name. This makes this API optional, conditional on </span><code>uintptr_t</code><span> availability.</span></p><p><span>If C++ were to require </span><code>uintptr_t</code><span> (e.g. see </span><a href="" target="_blank" rel="noopener"><span>P3248</span></a><span>), i.e., </span><code>uintptr_t</code><span> becomes non-optional, then this API should become non-optional.</span></p><h2 id="Impact-on-implementations" data-id="Impact-on-implementations" style=""><a class="anchor hidden-xs" href="#Impact-on-implementations" title="Impact-on-implementations"><span class="octicon octicon-link"></span></a><span>Impact on implementations</span></h2><p><span>This proposal does not impact any implementation we are aware of. We surveyed libc++, libstdc++, Microsoft STL, and libcu++.</span></p><h2 id="Wording" data-id="Wording" style=""><a class="anchor hidden-xs" href="#Wording" title="Wording"><span class="octicon octicon-link"></span></a><span>Wording</span></h2><p><span>Add the following 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 {
    private:
        T* ptr;  // exposition only
    public:
    // ...
    <ins>uintptr_t address() const noexcept; // optional</ins>
    // ...
  };
}</code></pre><p><span>Add the following to </span><a href="http://eel.is/c++draft/atomics.ref.ops" target="_blank" rel="noopener"><span>[atomic.ref.ops]</span></a><span>:</span></p><pre><code><ins>uintptr_t address() const noexcept;</ins></code></pre><p><ins><em><span>Returns</span></em><span>: </span><code>(uintptr_t)ptr</code><span>.</span></ins></p><p><span>Update </span><code>__cpp_lib_atomic_ref</code><span> version macro in </span><a href="https://eel.is/c++draft/version.syn#2" target="_blank" rel="noopener"><code>&lt;version&gt;</code><span> synopsis [version.syn]</span></a><span> to the C++ version this feature is introduced in:</span></p><pre><code>
#define __cpp_lib_atomic_ref <del>201806</del><ins>______</ins>L // freestanding, also in &lt;atomic&gt;
</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="#Expose-stdatomic_ref-s-object-address" title="Expose std::atomic_ref 's object address">Expose std::atomic_ref 's object address</a><ul class="nav">
<li><a href="#Changelog" title="Changelog">Changelog</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Before-and-after-Tony-tables" title="Before-and-after (&quot;Tony&quot;) tables">Before-and-after ("Tony") tables</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a><ul class="nav">
<li><a href="#Intent-of-atomic_ref-proposal" title="Intent of atomic_ref proposal">Intent of atomic_ref proposal</a></li>
</ul>
</li>
<li><a href="#Use-cases" title="Use cases">Use cases</a><ul class="nav">
<li><a href="#Atomic-access-to-elements-of-a-data-structure" title="Atomic access to elements of a data structure">Atomic access to elements of a data structure</a></li>
<li><a href="#Contention-aware-data-structures" title="Contention-aware data-structures">Contention-aware data-structures</a></li>
</ul>
</li>
<li><a href="#Design" title="Design">Design</a></li>
<li><a href="#Impact-on-implementations" title="Impact on implementations">Impact on implementations</a></li>
<li><a href="#Wording" title="Wording">Wording</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;"  >
        <div class="toc"><ul class="nav">
<li><a href="#Expose-stdatomic_ref-s-object-address" title="Expose std::atomic_ref 's object address">Expose std::atomic_ref 's object address</a><ul class="nav">
<li><a href="#Changelog" title="Changelog">Changelog</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Before-and-after-Tony-tables" title="Before-and-after (&quot;Tony&quot;) tables">Before-and-after ("Tony") tables</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a><ul class="nav">
<li><a href="#Intent-of-atomic_ref-proposal" title="Intent of atomic_ref proposal">Intent of atomic_ref proposal</a></li>
</ul>
</li>
<li><a href="#Use-cases" title="Use cases">Use cases</a><ul class="nav">
<li><a href="#Atomic-access-to-elements-of-a-data-structure" title="Atomic access to elements of a data structure">Atomic access to elements of a data structure</a></li>
<li><a href="#Contention-aware-data-structures" title="Contention-aware data-structures">Contention-aware data-structures</a></li>
</ul>
</li>
<li><a href="#Design" title="Design">Design</a></li>
<li><a href="#Impact-on-implementations" title="Impact on implementations">Impact on implementations</a></li>
<li><a href="#Wording" title="Wording">Wording</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>
