<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>P0019R1 : Atomic View</title>
<meta name="date" content="2016-02-04" />
<meta name="author" content="H. Carter Edwards" />
<meta name="author" content="Hans Boehm" />
<meta name="author" content="Olivier Giroux" />
<meta name="author" content="James Reus" />
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
  overflow: hidden;
}

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left, .figure.align-left, object.align-left {
  clear: left ;
  float: left ;
  margin-right: 1em }

img.align-right, .figure.align-right, object.align-right {
  clear: right ;
  float: right ;
  margin-left: 1em }

img.align-center, .figure.align-center, object.align-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.align-left {
  text-align: left }

.align-center {
  clear: both ;
  text-align: center }

.align-right {
  text-align: right }

/* reset inner alignment in figures */
div.align-right {
  text-align: inherit }

/* div.align-center * { */
/*   text-align: left } */

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font: inherit }

pre.literal-block, pre.doctest-block, pre.math, pre.code {
  margin-left: 2em ;
  margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
  border: 0px;
  border-top: 2px solid;
  border-bottom: 2px solid;
  border-collapse: collapse;
}
table.docutils.booktabs * {
  border: 0px;
}
table.docutils.booktabs th {
  border-bottom: thin solid;
  text-align: left;
}

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="p0019r1-atomic-view">
<h1 class="title">p0019r1 : Atomic View</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Project:</th><td class="field-body">ISO JTC1/SC22/WG21: Programming Language C++</td>
</tr>
<tr class="field"><th class="docinfo-name">Number:</th><td class="field-body">P0019r1</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
<td>2016-02-04</td></tr>
<tr class="field"><th class="docinfo-name">Reply-to:</th><td class="field-body"><a class="reference external" href="mailto:hcedwar&#64;sandia.gov">hcedwar&#64;sandia.gov</a></td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>H. Carter Edwards</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:hcedwar&#64;sandia.gov">hcedwar&#64;sandia.gov</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Hans Boehm</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:hboehm&#64;google.com">hboehm&#64;google.com</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Olivier Giroux</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:ogiroux&#64;nvidia.com">ogiroux&#64;nvidia.com</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>James Reus</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:reus1&#64;llnl.gov">reus1&#64;llnl.gov</a></td></tr>
<tr class="field"><th class="docinfo-name">Audience:</th><td class="field-body">SG1 Concurrency</td>
</tr>
<tr class="field"><th class="docinfo-name">URL:</th><td class="field-body"><a class="reference external" href="https://github.com/kokkos/ISO-CPP-Papers/blob/master/P0019.rst">https://github.com/kokkos/ISO-CPP-Papers/blob/master/P0019.rst</a></td>
</tr>
</tbody>
</table>
<div class="section" id="introduction">
<h1>1&nbsp;&nbsp;&nbsp;Introduction</h1>
<p>This paper proposes an extension to the atomic operations library [atomics]
for atomic operations applied to non-atomic objects.
The proposal is in five parts:
(1) the concept of an atomic view,
(2) application of this concept applied to single objects,
(3) application of this concept applied to members of a very large array, and
(4) motivating use cases and illustrative examples.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line-block">
<div class="line">template&lt; class T &gt; atomic_view ;</div>
<div class="line">template&lt; class T &gt; atomic_array_view ;</div>
</div>
<div class="line">}}</div>
</div>
</blockquote>
<p>Note: Feedback from SG1 Library Evolution Working Group (LEWG) on P0009r0,
Polymorphic Multidimensional Array View, noted that the term <em>view</em>
has the connotation of read-only. In response the P0009r0 <em>array_view</em>
name has been revised to <em>array_ref</em> in P0009r1.
The proposed names <em>atomic_view</em> and <em>atomic_array_view</em> may have
the same feedback from LEWG, potentially resulting in a similar
naming revision.</p>
</div>
<div class="section" id="atomic-view-concept">
<h1>2&nbsp;&nbsp;&nbsp;Atomic View Concept</h1>
<p>A class conforming to the atomic view concept
provides atomic operations for the viewed non-atomic object.
These operations replicate the operations on <strong>std::atomic&lt;T&gt;</strong> [29.5, Atomic types];
however, operations are const with respect to the atomic view object
in contrast to the non-const and volatile operations of a <strong>std::atomic&lt;T&gt;</strong> object.
An atomic view does not own (neither exclusively nor shared) the viewed non-atomic object.</p>
<p>The following <em>atomic-view-concept</em> specification is included to define requirements
for classes conforming to the <em>atomic-view-concept</em> and does not imply the existiance
of a template class of this name.</p>
<blockquote>
<div class="line-block">
<div class="line">template&lt; class T &gt;</div>
<div class="line">struct <em>atomic-view-concept</em> {</div>
<div class="line-block">
<div class="line">// Functionality matches corresponding member of atomic&lt;T&gt;</div>
<div class="line">static constexpr bool is_always_lock_free = <em>implementation defined</em> ;</div>
<div class="line">bool is_lock_free() const noexcept;</div>
<div class="line">void store( T , memory_order = memory_order_seq_cst ) const noexcept;</div>
<div class="line">T load( memory_order = memory_order_seq_cst ) const noexcept;</div>
<div class="line">operator T() const noexcept ;</div>
<div class="line">T exchange( T , memory_order = memory_order_seq_cst ) const noexcept;</div>
<div class="line">bool compare_exchange_weak( T&amp; , T , memory_order , memory_order ) const noexcept;</div>
<div class="line">bool compare_exchange_strong( T&amp; , T , memory_order , memory_order ) const noexcept;</div>
<div class="line">bool compare_exchange_weak( T&amp; , T , memory_order = memory_order_seq_cst ) const noexcept;</div>
<div class="line">bool compare_exchange_strong( T&amp;, T, memory_order = memory_order_seq_cst ) const noexcept;</div>
<div class="line">T operator=(T) const noexcept ;</div>
<div class="line"><br /></div>
<div class="line">// Functionality that may exist and deviate from corresponding member of atomic&lt;T&gt;, if any.</div>
<div class="line"><em>atomic-view-concept</em> ();</div>
<div class="line"><em>atomic-view-concept</em> ( const <em>atomic-view-concept</em> &amp; );</div>
<div class="line"><em>atomic-view-concept</em> ( <em>atomic-view-concept</em> &amp;&amp; );</div>
<div class="line"><em>atomic-view-concept</em> &amp; operator = ( const <em>atomic-view-concept</em> &amp; );</div>
<div class="line"><em>atomic-view-concept</em> &amp; operator = ( <em>atomic-view-concept</em> &amp;&amp; );</div>
<div class="line"><br /></div>
<div class="line">constexpr bool operator() const noexcept;</div>
</div>
<div class="line">};</div>
</div>
<p>Requires: Type <em>T</em> is trivially copyable.</p>
</blockquote>
<p>Constructors and assignment operators of an <em>atomic-view-concept</em> may acquire shared resources
such as concurrent locks to support atomic operations on the non-atomic object. and</p>
<p><strong>constexpr bool operator() const noexept ;</strong></p>
<blockquote>
Returns if the <em>atomic-view-concept</em> object wraps a non-null pointer.
A default constructed <em>atomic-view-concept</em> object returns false.</blockquote>
<p>A class conforming to the atomic view concept shall provide the
following operations when T is an integral type.
These operations replicate the operations on <em>std::atomic&lt;integral&gt;</em> [29.5, Atomic types];
however, operations are const with respect to the atomic view object
in contrast to the non-const and volatile operations of a <strong>std::atomic&lt;integral&gt;</strong> object.</p>
<blockquote>
<div class="line-block">
<div class="line">template&lt;&gt; struct <em>atomic-view-concept</em> &lt; <em>integral</em> &gt; {</div>
<div class="line"><br /></div>
<div class="line-block">
<div class="line"><em>integral</em> fetch_add( <em>integral</em> , memory_order = memory_order_seq_cst) const noexcept;</div>
<div class="line"><em>integral</em> fetch_sub( <em>integral</em> , memory_order = memory_order_seq_cst) const noexcept;</div>
<div class="line"><em>integral</em> fetch_and( <em>integral</em> , memory_order = memory_order_seq_cst) const noexcept;</div>
<div class="line"><em>integral</em> fetch_or(  <em>integral</em> , memory_order = memory_order_seq_cst) const noexcept;</div>
<div class="line"><em>integral</em> fetch_xor( <em>integral</em> , memory_order = memory_order_seq_cst) const noexcept;</div>
<div class="line"><br /></div>
<div class="line"><em>integral</em> operator++(int) const noexcept;</div>
<div class="line"><em>integral</em> operator--(int) const noexcept;</div>
<div class="line"><em>integral</em> operator++() const noexcept;</div>
<div class="line"><em>integral</em> operator--() const noexcept;</div>
<div class="line"><em>integral</em> operator+=( <em>integral</em> ) const noexcept;</div>
<div class="line"><em>integral</em> operator-=( <em>integral</em> ) const noexcept;</div>
<div class="line"><em>integral</em> operator&amp;=( <em>integral</em> ) const noexcept;</div>
<div class="line"><em>integral</em> operator|=( <em>integral</em> ) const noexcept;</div>
<div class="line"><em>integral</em> operator^=( <em>integral</em> ) const noexcept;</div>
</div>
<div class="line">};</div>
</div>
</blockquote>
<p>Note that for consistency the <em>atomic-view-concept</em><strong>&lt;</strong><em>integral</em><strong>&gt;</strong>
mathematical operator overloads retain the same mathematical inconsistency
with respect to the mathematical operators for the <em>integral</em> type,
as illustrated below.</p>
<pre class="code c++ literal-block">
<span class="keyword type">int</span> <span class="name function">i</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">)</span>
<span class="operator">++</span><span class="punctuation">(</span> <span class="operator">++</span><span class="name">i</span> <span class="punctuation">);</span>        <span class="comment single">// ++i returns an lvalue
</span><span class="punctuation">(</span> <span class="name">i</span> <span class="operator">+=</span> <span class="literal number integer">1</span> <span class="punctuation">)</span> <span class="operator">+=</span> <span class="literal number integer">2</span> <span class="punctuation">;</span> <span class="comment single">// i+= returns an lvalue
</span>
<span class="name">std</span><span class="operator">::</span><span class="name">atomic</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">ai</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">);</span>
<span class="operator">++</span><span class="punctuation">(</span> <span class="operator">++</span><span class="punctuation">(</span> <span class="name">ai</span> <span class="punctuation">)</span> <span class="punctuation">);</span>    <span class="comment single">// error: ++ai returns an rvalue
</span><span class="punctuation">(</span> <span class="name">ai</span> <span class="operator">+=</span> <span class="literal number integer">1</span> <span class="punctuation">)</span> <span class="operator">+=</span> <span class="literal number integer">2</span> <span class="punctuation">;</span> <span class="comment single">// error: ai+= returns an rvalue</span>
</pre>
<!--  -->
</div>
<div class="section" id="atomic-view-for-a-single-object">
<h1>3&nbsp;&nbsp;&nbsp;Atomic View for a Single Object</h1>
<p>An <strong>atomic_view&lt;T&gt;</strong> object is used to perform
atomic operations on the globally accessible viewed non-atomic object.
The intent is for <strong>atomic_view&lt;T&gt;</strong> to provide the best-performing
implementation of <em>atomic-view-concept</em> operations for the type T.
All atomic operations on an instance of <strong>atomic_view&lt;T&gt;</strong>
are atomic with respect to any other instance that views the same
globally accessible object, as defined by equality of pointers to that object.</p>
<p>[Note: Introducing concurrency within legacy codes may require
replacing operations on existing non-atomic objects with atomic operations
such that the non-atomic object cannot be replaced with a <em>std::atomic</em> object. - end note]</p>
<p>[Note: An object may be heavily used non-atomically in well-defined phases
of an application.  Forcing such objects to be exclusively <em>std::atomic</em>
would incur an unnecessary performance penalty.  - end note]</p>
<blockquote>
<div class="line-block">
<div class="line">template&lt; class T &gt; struct atomic_view { // conforms to atomic view concept</div>
<div class="line"><br /></div>
<div class="line-block">
<div class="line">explicit atomic_view( T &amp; ); // wrapping constructor is NOT noexcept</div>
<div class="line"><br /></div>
<div class="line">atomic_view();</div>
<div class="line">atomic_view( atomic_view &amp;&amp; ) noexcept ;</div>
<div class="line">atomic_view( const atomic_view &amp; ) noexcept ;</div>
<div class="line">atomic_view &amp; operator = ( atomic_view &amp;&amp; ) noexcept ;</div>
<div class="line">atomic_view &amp; operator = ( const atomic_view &amp; ) noexcept ;</div>
<div class="line">~atomic_view() noexcept ;</div>
</div>
<div class="line">};</div>
</div>
<p>Requires: Type <em>T</em> is trivially copyable.</p>
</blockquote>
<p>[Note: The intent is for atomic operations of
<em>atomic_view&lt;T&gt;</em> to directly update the referenced object.
The <em>wrapping constructor</em> may acquire a resource,
such as a lock from a collection of address-sharded locks,
to perform atomic operations.
When such a resource is necessary subsequent
copy and move constructors and assignment operators
may reduce overhead by copying or moving the previously
acquired resource as opposed to re-acquiring that resource.
– end note]</p>
<p><strong>atomic_view&lt;T&gt;::atomic_view();</strong></p>
<blockquote>
Effects: This instance does not reference a globally accessible object.</blockquote>
<p><strong>atomic_view&lt;T&gt;::atomic_view( T &amp; obj );</strong></p>
<blockquote>
<p>Requires: The referenced obj must be properly aligned for its type T,
otherwise behavior is undefined.</p>
<p>Requires: While any <em>atomic_view</em> instance exists for a referenced object
all accesses of that object shall occur through an <em>atomic_view</em> referencing
that object, otherwise behavior is undefined.
Multiple instances of an <em>atomic_view</em> may be constructed with the wrapping constructor
which reference the same globally accessible object.</p>
<p>Effects: This wrapping constructor wraps the globally accessible referenced object.
Atomic operations on this instance are atomic with respect to atomic operations
on any <strong>atomic_view</strong> instance that reference the same globally accessible object.
[Note: This constructor is allowed to throw an exception if the referenced object is
not properly aligned. - end note]
[Note: This constructor may obtain a resource as necessary to support atomic operations.
This constructor is allowed to throw an exception if such a resource could not be obtained. – end note]</p>
<p>Effects: All accesses of the wrapped object in the same execution context that appear before the
wrapping constructor shall happen before the wrapping constructor completes.
[Note: As if a memory fence were performed on the on the wrapped object within the wrapping constructor. - end note]</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword type">int</span> <span class="operator">&amp;</span> <span class="name">i</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">i</span> <span class="operator">=</span> <span class="literal number integer">42</span> <span class="punctuation">;</span>
  <span class="name">atomic_view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">ai</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">);</span>
  <span class="name">std</span><span class="operator">::</span><span class="name">async</span><span class="punctuation">(</span> <span class="punctuation">[</span><span class="operator">=</span><span class="punctuation">]()</span> <span class="punctuation">{</span> <span class="name">assert</span><span class="punctuation">(</span> <span class="name">ai</span><span class="punctuation">.</span><span class="name">load</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">42</span> <span class="punctuation">);</span> <span class="punctuation">});</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<div class="line-block">
<div class="line"><strong>atomic_view&lt;T&gt;::atomic_view( atomic_view &amp;&amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_view&lt;T&gt;::atomic_view( const atomic_view &amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_view&lt;T&gt; &amp; atomic_view&lt;T&gt;::operator = ( atomic_view &amp;&amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_view&lt;T&gt; &amp; atomic_view&lt;T&gt;::operator = ( const atomic_view &amp; rhs ) noexcept ;</strong></div>
</div>
<blockquote>
Effects: If <em>rhs</em> references a globally accessible object
then this instance references the same object otherwise
this instance does not reference a globally accessible object.
[Note: If <em>rhs</em> holds a resource to support atomic operations
then that resource should be copied or moved as appropriate. - end note]</blockquote>
<p><strong>atomic_view&lt;T&gt;::~atomic_view() noexcept ;</strong></p>
<blockquote>
Effects: This instance does not reference a globally accessible object.
[Note: If this instances holds a resource to support atomic operations
then that resource should be released or destroyed as appropriate. - end note]</blockquote>
</div>
<div class="section" id="atomic-view-for-a-very-large-array">
<h1>4&nbsp;&nbsp;&nbsp;Atomic View for a Very Large Array</h1>
<p>High performance computing (HPC) applications use very large arrays.
Computations with these arrays typically have distinct phases that
allocate and initialize members of the array,
update members of the array,
and read members of the array.
Parallel algorithms for initialization (e.g., zero fill)
have non-conflicting access when assigning member values.
Parallel algorithms for updates have conflicting access
to members which must be guarded by atomic operations.
Parallel algorithms with read-only access require best-performing
streaming read access, random read access, vectorization,
or other guaranteed non-conflicting HPC pattern.</p>
<p>An <strong>atomic_array_view</strong> object is used to perform
atomic operations on the viewed non-atomic members of the array.
The intent is for <strong>atomic_array_view</strong> to provide the
best-performing implementation of atomic-view-concept operations for the members of the array.</p>
<blockquote>
<div class="line-block">
<div class="line">template&lt; class T &gt; struct atomic_array_view {</div>
<div class="line"><br /></div>
<div class="line-block">
<div class="line">static constexpr bool is_always_lock_free = <em>implementation defined</em> ;</div>
<div class="line">bool is_lock_free() const noexcept ;</div>
<div class="line"><br /></div>
<div class="line">// Returns true if the view wraps an array and member access is valid.</div>
<div class="line">explicit bool operator() const noexcept ;</div>
<div class="line"><br /></div>
<div class="line">atomic_array_view( T * , size_t ); // Wrapping constructor is NOT noexcept</div>
<div class="line">atomic_array_view() noexcept ;</div>
<div class="line">atomic_array_view( atomic_array_view &amp;&amp; ) noexcept ;</div>
<div class="line">atomic_array_view( const atomic_array_view &amp; ) noexcept ;</div>
<div class="line">atomic_array_view &amp; operator = ( atomic_array_view &amp;&amp; ) noexcept ;</div>
<div class="line">atomic_array_view &amp; operator = ( const atomic_array_view &amp; ) noexcept ;</div>
<div class="line">~atomic_array_view() noexcept ;</div>
<div class="line"><br /></div>
<div class="line">size_t size() const noexcept ;</div>
<div class="line"><br /></div>
<div class="line">using reference = <em>implementation-defined-atomic-view-concept-type</em> ;</div>
<div class="line"><br /></div>
<div class="line">reference operator[]( size_t ) const noexcept ;</div>
</div>
<div class="line">};</div>
</div>
<p>Requires: Type <em>T</em> is trivially copyable.</p>
</blockquote>
<p>[Note: The <em>wrapping constructor</em> may acquire resources,
such as a set of locks, to perform atomic operations.
When such a resource is necessary subsequent
copy and move constructors and assignment operators
may reduce overhead by copying or moving the previously
acquired resource as opposed to re-acquiring that resource.
The intent is to enable amortization of the time and space overhead
of obtaining and releasing such resources. – end note]
– end note]</p>
<p><strong>using reference =</strong> <em>implementation-defined-atomic-view-concept-type</em> <strong>;</strong></p>
<blockquote>
The <strong>reference</strong> type conforms to <em>atomic-view-concept</em> for type T.</blockquote>
<div class="line-block">
<div class="line"><strong>static constexpr bool is_always_lock_free =</strong> <em>implementation defined</em> <strong>;</strong></div>
<div class="line"><strong>bool atomic_array_view&lt;T&gt;::is_lock_free() const noexcept ;</strong></div>
</div>
<blockquote>
Effects: Whether atomic operations on members are (always) lock free.</blockquote>
<p><strong>atomic_array_view&lt;T&gt;::atomic_array_view( T * ptr , size_t N );</strong></p>
<blockquote>
<p>Requires: The array referenced by [ptr .. ptr+N-1] must be properly aligned for its type T, otherwise behavior is undefined.</p>
<p>Requires: While any <em>atomic_array_view</em> instance exists for a referenced array
all accesses of that array and its members shall occur through an <em>atomic_array_view</em> referencing
that array, otherwise behavior is undefined.
Multiple concurrent instances of an <em>atomic_array_view</em> may be constructed with the wrapping constructor
which references any of the any globally accessible members (i.e., has an overlapping range)
if-and-only-if the <em>atomic_array_view</em> type <strong>is_always_lock_free</strong>.
If NOT <strong>is_always_lock_free</strong> then construction of multiple concurrent instances
via the wrapping constructor has undefined behavior.
[Note: This allows a non-lock-free <em>atomic_array_view</em> to acquire a set of locks
that are exclusively associated with the wrapped array. - end note]</p>
<p>Effects: The <em>wrapping constructor</em> wraps the referenced globally accessible array [ptr .. ptr+N-1].
Atomic operations on members of this instance are atomic with respect to atomic operations
on members any <strong>atomic_array_view</strong> instance that references the same globally accessible array.
[Note: This constructor is allowed to throw an exception if the referenced array is
not properly aligned. - end note]
[Note: This constructor may obtain resources as necessary to support atomic operations on members.
This constructor is allowed to throw an exception if such resources could not be obtained. – end note]</p>
<p>Effects: All accesses of the wrapped array members in the same execution context that appear before the
wrapping constructor shall happen before the wrapping constructor completes.
[Note: As if a memory fence were performed on the wrapped array within the wrapping constructor. - end note]</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword type">int</span> <span class="operator">*</span> <span class="name">i</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">i</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal number integer">42</span> <span class="punctuation">;</span>
  <span class="name">i</span><span class="punctuation">[</span><span class="name">N</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal number integer">42</span> <span class="punctuation">;</span>
  <span class="name">atomic_array_view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">ai</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">,</span><span class="name">N</span><span class="punctuation">);</span>
  <span class="name">std</span><span class="operator">::</span><span class="name">async</span><span class="punctuation">(</span> <span class="punctuation">[</span><span class="operator">=</span><span class="punctuation">]()</span>
    <span class="punctuation">{</span>
      <span class="name">assert</span><span class="punctuation">(</span> <span class="name">ai</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">].</span><span class="name">load</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">42</span> <span class="punctuation">);</span>
      <span class="name">assert</span><span class="punctuation">(</span> <span class="name">ai</span><span class="punctuation">[</span><span class="name">N</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">].</span><span class="name">load</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">42</span> <span class="punctuation">);</span>
    <span class="punctuation">});</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<div class="line-block">
<div class="line"><strong>atomic_array_view&lt;T&gt;::atomic_array_view( atomic_array_view &amp;&amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_array_view&lt;T&gt;::atomic_array_view( const atomic_array_view &amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_array_view&lt;T&gt; &amp; atomic_array_view&lt;T&gt;::operator = ( atomic_array_view &amp;&amp; rhs ) noexcept ;</strong></div>
<div class="line"><strong>atomic_array_view&lt;T&gt; &amp; atomic_array_view&lt;T&gt;::operator = ( const atomic_array_view &amp; rhs ) noexcept ;</strong></div>
</div>
<blockquote>
Effects: If <em>rhs</em> references a globally accessible array
then this instance references the same array otherwise
this instance does not reference a globally accessible object.
[Note: If <em>rhs</em> holds resources to support atomic operations
then that resource should be copied or moved as appropriate.
It may be appropriate for these resources to be managed
with <em>std::shared_ptr</em> semantics. - end note]</blockquote>
<p><strong>atomic_array_view&lt;T&gt;::~atomic_array_view() noexcept ;</strong></p>
<blockquote>
Effects: This instance does not reference a globally accessible object.
[Note: If this instances holds resources to support atomic operations
then those resources should be released or destroyed as appropriate. - end note]</blockquote>
<p><strong>atomic_array_view&lt;T&gt;::reference  atomic_array_view&lt;T&gt;::operator[]( size_t i ) const noexcept ;</strong></p>
<blockquote>
<p>Requires: i &lt; N.  The program is ill-formed if I is out of bounds.</p>
<p>Requires: The returned <strong>reference</strong> object must be destroyed or
re-assigned before the last associated <em>atomic_array_view</em> instance
is destroyed, otherwise behavior is undefined.</p>
<p>Returns: An instance of <strong>reference</strong> type for the i-th member of the <strong>atomic_array_view</strong>, where indexing is zero-based.
[Note: The intent is for efficient generation of the returned object with respect to obtaining a resource,
such as a shared locking mechanism, that may be required to support atomic operations on the referenced member. – end note]</p>
</blockquote>
</div>
<div class="section" id="notes-and-examples">
<h1>5&nbsp;&nbsp;&nbsp;Notes and Examples</h1>
<div class="section" id="atomic-array-view">
<h2>5.1&nbsp;&nbsp;&nbsp;Atomic Array View</h2>
<p>Under the HPC use case the member access operator,
proxy type constructor, or proxy type destructor
will be frequently invoked; therefore,
an implementation should trade off decreased overhead
in these operations versus increased overhead in the wrapper constructor and final destructor.</p>
<p>Usage Scenario for <strong>atomic_array_view&lt;T&gt;</strong></p>
<ol class="loweralpha simple">
<li>A very large array of trivially copyable members is allocated.</li>
<li>A parallel algorithm initializes members through non-conflicting assignments.</li>
<li>The array is wrapped by an atomic_array_view&lt;T&gt;.</li>
<li>One or more parallel algorithms update members of the array through atomic view operations.</li>
<li>The atomic_array_view&lt;T&gt; is destructed.</li>
<li>Parallel algorithms access array members through non-conflicting reads, writes, or updates.</li>
</ol>
<p>Example:</p>
<pre class="code c++ literal-block">
<span class="comment single">// atomic array view wrapper constructor:
</span><span class="name">atomic_array_view</span><span class="operator">&lt;</span><span class="name">T</span><span class="operator">&gt;</span> <span class="name">array</span><span class="punctuation">(</span> <span class="name">ptr</span> <span class="punctuation">,</span> <span class="name">N</span> <span class="punctuation">);</span>

<span class="comment single">// atomic operation on a member:
</span><span class="name">array</span><span class="punctuation">[</span><span class="name">i</span><span class="punctuation">].</span><span class="name">atomic</span><span class="operator">-</span><span class="name">operation</span><span class="punctuation">(...);</span>

<span class="comment single">// atomic operations through a temporary value
// within a concurrent function:
</span><span class="name">atomic_array_view</span><span class="operator">&lt;</span><span class="name">T</span><span class="operator">&gt;::</span><span class="name">reference</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">array</span><span class="punctuation">[</span><span class="name">i</span><span class="punctuation">];</span>
<span class="name">x</span><span class="punctuation">.</span><span class="name">atomic</span><span class="operator">-</span><span class="name">operation</span><span class="operator">-</span><span class="name">a</span><span class="punctuation">(...);</span>
<span class="name">x</span><span class="punctuation">.</span><span class="name">atomic</span><span class="operator">-</span><span class="name">operation</span><span class="operator">-</span><span class="name">b</span><span class="punctuation">(...);</span>
</pre>
<!--  -->
<p>Possible interface for <strong>atomic_array_view&lt;T&gt;::reference</strong></p>
<pre class="code c++ literal-block">
<span class="keyword">struct</span> <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span> <span class="punctuation">{</span>   <span class="comment single">// conforms to atomic view concept
</span>
  <span class="comment single">// Construction limited to move
</span>  <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span><span class="punctuation">(</span><span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span> <span class="operator">&amp;&amp;</span> <span class="punctuation">)</span> <span class="operator">=</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
  <span class="operator">~</span><span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span><span class="punctuation">();</span>

  <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span><span class="punctuation">()</span> <span class="operator">=</span> <span class="keyword">delete</span> <span class="punctuation">;</span>
  <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span> <span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="operator">=</span> <span class="keyword">delete</span> <span class="punctuation">;</span>
  <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span> <span class="operator">&amp;</span>
    <span class="keyword">operator</span> <span class="operator">=</span> <span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">implementation</span><span class="operator">-</span><span class="name">defined</span><span class="operator">-</span><span class="name">proxy</span><span class="operator">-</span><span class="name">type</span> <span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="operator">=</span> <span class="keyword">delete</span> <span class="punctuation">;</span>
<span class="punctuation">};</span>
</pre>
<!--  -->
<p>Wrapping constructor options for <strong>atomic_array_view&lt;T&gt;</strong></p>
<p>A wrapping constructor of the form (T*begin, T*end) could be valid.
However, the (T*ptr, size_t N) version is preferred to minimize potential
confusion with construction from non-contiguous iterators.
Wrapping constructors for standard contiguous containers would also be valid.
However, such constructors could have potential confusion as to whether
he atomic_array_view would or would not track resizing operations applied to the input container.</p>
<p>Implementation note for <strong>atomic_array_view&lt;T&gt;</strong></p>
<blockquote>
All non-atomic accesses of array members that appear before the wrapping constructor must happen before subsequent atomic operations on the atomic_array_view members.  For example:</blockquote>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword type">int</span> <span class="operator">*</span> <span class="name">i</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">i</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal number integer">42</span> <span class="punctuation">;</span>
  <span class="name">i</span><span class="punctuation">[</span><span class="name">N</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal number integer">42</span> <span class="punctuation">;</span>
  <span class="name">atomic_array_view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">ai</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">,</span><span class="name">N</span><span class="punctuation">);</span>
  <span class="comment single">// Operations on ‘i’ must happen before operations on ‘ai’
</span>  <span class="name">foreach</span><span class="punctuation">(</span> <span class="name">parallel_policy</span><span class="punctuation">,</span> <span class="literal number integer">0</span><span class="punctuation">,</span> <span class="name">M</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">=</span><span class="punctuation">](</span> <span class="keyword type">int</span> <span class="name">j</span> <span class="punctuation">){</span> <span class="operator">++</span><span class="name">ai</span><span class="punctuation">[</span><span class="name">j</span><span class="operator">%</span><span class="name">N</span><span class="punctuation">]</span> <span class="punctuation">;</span> <span class="punctuation">}</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
</div>
<div class="section" id="mathematically-consistent-integral-operator-overloads">
<h2>5.2&nbsp;&nbsp;&nbsp;Mathematically Consistent Integral Operator Overloads</h2>
<p>As previously noted the <strong>std::atomic&lt;</strong><em>integral</em><strong>&gt;</strong>
mathematical operator overloads are inconsistent with the mathematical
operators for <em>integral</em>.
The <em>atomic-view-concept</em><strong>&lt;</strong><em>integral</em><strong>&gt;</strong> retains these inconsistent
operator overloads.
Consistent mathematical operator semantics would be restored with the following
operator specifications.
However, such a change would break backward compatibility and is therefore
only noted and not a proposed change.</p>
<div class="line-block">
<div class="line">template&lt;&gt; struct atomic &lt; <em>integral</em> &gt; {</div>
<div class="line"><br /></div>
<div class="line-block">
<div class="line">volatile atomic &amp; operator++(int) volatile noexcept ;</div>
<div class="line">atomic &amp; operator++(int) noexcept ;</div>
<div class="line">volatile atomic &amp; operator--(int) volatile noexcept ;</div>
<div class="line">atomic &amp; operator--(int) noexcept ;</div>
<div class="line"><br /></div>
<div class="line">// fetch-and-increment, fetch-and-decrement operators:</div>
<div class="line"><em>integral</em> operator++() volatile noexcept ;</div>
<div class="line"><em>integral</em> operator++() noexcept ;</div>
<div class="line"><em>integral</em> operator--() volatile noexcept ;</div>
<div class="line"><em>integral</em> operator--() noexcept ;</div>
<div class="line"><br /></div>
<div class="line">volatile atomic &amp; operator+=( <em>integral</em> ) volatile noexcept;</div>
<div class="line">atomic &amp; operator+=( <em>integral</em> ) noexcept;</div>
<div class="line">volatile atomic &amp; operator-=( <em>integral</em> ) volatile noexcept;</div>
<div class="line">atomic &amp; operator-=( <em>integral</em> ) noexcept;</div>
<div class="line">volatile atomic &amp; operator&amp;=( <em>integral</em> ) volatile noexcept;</div>
<div class="line">atomic &amp; operator&amp;=( <em>integral</em> ) noexcept;</div>
<div class="line">volatile atomic &amp; operator|=( <em>integral</em> ) volatile noexcept;</div>
<div class="line">atomic &amp; operator|=( <em>integral</em> ) noexcept;</div>
<div class="line">volatile atomic &amp; operator^=( <em>integral</em> ) volatile noexcept;</div>
<div class="line">atomic &amp; operator^=( <em>integral</em> ) noexcept;</div>
</div>
<div class="line">};</div>
<div class="line"><br /></div>
<div class="line">template&lt;&gt; struct <em>atomic-view-concept</em> &lt; <em>integral</em> &gt; {</div>
<div class="line"><br /></div>
<div class="line-block">
<div class="line">const <em>atomic-view-concept</em> &amp; operator++(int) const noexcept;</div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator--(int) const noexcept;</div>
<div class="line"><br /></div>
<div class="line"><em>integral</em> operator++() const noexcept;</div>
<div class="line"><em>integral</em> operator--() const noexcept;</div>
<div class="line"><br /></div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator+=( <em>integral</em> ) const noexcept;</div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator-=( <em>integral</em> ) const noexcept;</div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator&amp;=( <em>integral</em> ) const noexcept;</div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator|=( <em>integral</em> ) const noexcept;</div>
<div class="line">const <em>atomic-view-concept</em> &amp; operator^=( <em>integral</em> ) const noexcept;</div>
</div>
<div class="line">};</div>
</div>
</div>
</div>
</div>
</body>
</html>
