<html>
<head>
    <title>Proposed Text for Bidirectional Fences</title>
    <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema" />
    <meta http-equiv="Content-Language" content="en-us" />
    <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
</head>
<body bgcolor="#ffffff">
    <address>
        Document number: N2752=08-0262</address>
    <address>
        Programming Language C++</address>
    <address>
        &nbsp;</address>
    <address>
        Peter Dimov, &lt;<a href="mailto:pdimov@pdimov.com">pdimov@pdimov.com</a>&gt;</address>
    <address>
        Clark Nelson, &lt;<a href="mailto:clark.nelson@intel.com">clark.nelson@intel.com</a>&gt;</address>
    <address>
        &nbsp;</address>
    <address>
        2008-09-18</address>
    <h1>
        Proposed Text for Bidirectional Fences</h1>
    <p>
        All edits are relative to N2723.</p>
    <h2>
        Chapter 1 edits</h2>
    <p>
        Change 1.10 [intro.multithreaded] p4 as follows:</p>
    <blockquote>
        The library defines a number of atomic operations (clause 29) and 
		operations on locks (clause 30) that are specially identified as 
		synchronization operations. These operations play a special role in 
		making assignments in one thread visible to another. A synchronization 
		operation <ins>on one or more memory locations</ins> is either a consume 
		operation, an acquire operation, a release operation, or both an acquire 
		and release operation<del>, on one or more memory locations; the 
		semantics of these are described below</del>. <ins>A synchronization 
		operation without an associated memory location is a fence and can be 
		either an acquire fence, a release fence or both an acquire and release 
		fence.</ins> In addition, there are relaxed atomic operations, which are 
		not synchronization operations, and atomic read-modify-write operations, 
		which have special characteristics<del>, also described below</del>. [ <em>
		Note:</em> For example, a call that acquires a lock will perform an 
		acquire operation on the locations comprising the lock. Correspondingly, 
		a call that releases the same lock will perform a release operation on 
		those same locations. Informally, performing a release operation on A 
		forces prior side effects on other memory locations to become visible to 
		other threads that later perform a consume or an acquire operation on A. 
		We do not include &quot;relaxed&quot; atomic operations as synchronization 
		operations although, like synchronization operations, they cannot 
		contribute to data races.
        <em>&#8212;end note</em> ]</blockquote>
    <p>
        Change 1.10 [intro.multithreaded] p6 as follows:</p>
    <blockquote>
        A <em>release sequence</em> on an atomic object <em>M</em> is a maximal 
		contiguous sub-sequence of side effects in the modification order of <em>
		M</em>, where the first operation is a release, and every subsequent 
		operation
        <ul>
            <li>is performed by the same thread that performed the release, or</li>
            <li>is <del>a non-relaxed</del> <ins>an</ins> atomic 
			read-modify-write operation.</li>
        </ul>
    </blockquote>
    <p>
        Change 1.10 [intro.multithreaded] p7 as follows:</p>
    <blockquote>
        <ins>Certain library calls <em>synchronize with</em> other library calls 
		performed by another thread. In particular, an atomic operation</ins> <del>
		An evaluation</del> <em>A</em>
        that performs a release operation on an object <em>M</em> <del><em>
		synchronizes with</em></del>
        <ins>synchronizes with</ins>
        an <del>evaluation</del> <ins>atomic operation</ins> <em>B</em> that 
		performs an acquire operation on <em>M</em> and reads a value written by 
		any side effect in the release sequence headed by <em>A</em>. [ <em>
		Note:</em> Except in the specified cases, reading a later value does not 
		necessarily ensure visibility as described below. Such a requirement 
		would sometimes interfere with efficient implementation. <em>&#8212;end note</em> 
		] [ <em>Note:</em> The specifications of the synchronization operations 
		define when one reads the value written by another. For atomic 
		variables, the definition is clear. All operations on a given lock occur 
		in a single total order. Each lock acquisition &quot;reads the value written&quot; 
		by the last lock release. <em>&#8212;end note</em> ]</blockquote>
    <h2>
        Chapter 29 edits</h2>
    <p>Throughout 29, remove all five declarations of fence member functions 
	(for <code>bool</code>, <em>itype</em>, <code>address</code>, generic and <code>
	flag</code>):</p>
    <blockquote>
        <del><code>void fence(memory_order) const volatile;</code></del></blockquote>
    <p>Throughout 29, remove all six declarations of <code>atomic_fence</code> 
	functions (two each for <code>bool</code>, <em>itype</em> and <code>address</code>):</p>
    <blockquote>
        <del><code>void atomic_fence(const volatile atomic_<em>type</em>*, 
		memory_order);</code></del></blockquote>
    <p>In 29.4 [atomics.types.operations], delete the description of the 
		<code>atomic_fence</code> functions and the <code>fence</code> member 
	functions, including paragraphs 21 and 22.</p>
	<p>In both 29 &quot;Header <code>&lt;cstdatomic&gt;</code> synopsis&quot; and 29.5 
	[atomics.flag], delete the <code>atomic_flag_fence</code> function and the <code>
	atomic_global_fence_compatibility</code> object:</p>
    <blockquote>
    	...<br />
    	<code>void atomic_flag_clear_explicit(volatile atomic_flag*, 
		memory_order);</code><br />
        <del><code>void atomic_flag_fence(const volatile atomic_flag *object, 
		memory_order order);</code></del></blockquote>
	<blockquote><code>#define ATOMIC_FLAG_INIT</code> <i>unspecified</i><br />
		<del><code>extern const atomic_flag atomic_global_fence_compatibility;</code></del><br /></blockquote>
	<p>Add new declarations at the end of 29 &quot;Header <code>&lt;cstdatomic&gt;</code> 
	synopsis&quot;:</p>
	<blockquote><code>template&lt;&gt; struct atomic&lt;<em>integral</em>&gt;;</code></blockquote>
	<blockquote><ins>
        <code>// 29.6, fences</code><br />
        <code>void atomic_thread_fence(memory_order);</code><br />
        <code>void atomic_signal_fence(memory_order);</code>
    </ins><br />
    <code>}</code>
    </blockquote>
    <p>
        Change 29.1 [atomics.order] p2 as follows:</p>
    <blockquote>
        The <code>memory_order_seq_cst</code> operations that load a value are 
		acquire operations on the affected locations. The <code>
		memory_order_seq_cst</code> operations that store a value are release 
		operations on the affected locations. In addition, <del>in a consistent 
		execution,</del> there <del>must</del> <ins>shall</ins> be a single 
		total order <em>S</em> on all <code>memory_order_seq_cst</code>
        operations, consistent with the happens before order and modification 
		orders for all affected locations, such that each <code>
		memory_order_seq_cst</code>
        operation <ins>that loads a value</ins> observes either the last 
		preceding modification according to this order
        <em>S</em>, or the result of an operation that is not <code>
		memory_order_seq_cst</code>. [ <em>Note:</em> Although it is not 
		explicitly required that <em>S</em> include locks, it can always be 
		extended to an order that does include lock and unlock operations, since 
		the ordering between those is already included in the happens before 
		ordering.
        <em>&#8212;end note</em> ]</blockquote>
        <p>Add new paragraphs following 29.1 [atomics.order] p2:</p>
    <blockquote>
        <ins>For an atomic operation <em>B</em> that reads the value of an 
		atomic object <em>M</em>, if there is a <code>memory_order_seq_cst</code> 
		fence <em>X</em> sequenced before <em>B</em>, then <em>B</em> observes 
		either the last <code>memory_order_seq_cst</code> modification of <em>M</em> 
		preceding
            <em>X</em> in the total order <em>S</em> or a later modification of <em>
		M</em>
            in its modification order.</ins></blockquote>
    <blockquote>
        <ins>For atomic operations <em>A</em> and <em>B</em> on an atomic object <em>
		M</em>, where <em>A</em> modifies <em>M</em> and <em>B</em> takes its 
		value, if there is a <code>memory_order_seq_cst</code> fence <em>X</em> 
		such that <em>A</em> is sequenced before <em>X</em>
            and <em>B</em> follows <em>X</em> in <em>S</em>, then <em>B</em>
            observes either the effects of <em>A</em> or a later modification of <em>
		M</em> in its modification order.</ins></blockquote>
    <blockquote>
        <ins>For atomic operations <em>A</em> and <em>B</em> on an atomic 
		object <em>M</em>, where <em>A</em> modifies <em>M</em> and <em>B</em> 
		takes its value, if there are <code>memory_order_seq_cst</code> fences <em>
		X</em> and <em>Y</em>
            such that <em>A</em> is sequenced before <em>X</em>, <em>Y</em> is 
		sequenced before <em>B</em>, and <em>X</em> precedes <em>Y</em> in <em>S</em>, 
		then <em>B</em> observes either the effects of <em>A</em> or a later 
		modification on <em>M</em> in its modification order.</ins></blockquote>
    <p>
        Add a new section, 29.6 <em>[atomic.fences]</em>, with the following 
		contents:</p>
    <blockquote>
        <h3>
            29.6 Fences</h3>
    </blockquote>
    <blockquote>
        This section introduces synchronization primitives called <em>fences</em>. 
		Fences can have acquire semantics, release semantics, or both. A fence 
		with acquire semantics is called an <em>acquire fence</em>. A fence with 
		release semantics is called a <em>release fence</em>.</blockquote>
    <blockquote>
        A release fence <em>A</em> synchronizes with an acquire fence <em>B</em>
            if there exist atomic operations <em>X</em> and <em>Y</em>, both 
		operating on some atomic object <em>M</em>, such that <em>A</em> is 
		sequenced before <em>X</em>, <em>X</em> modifies <em>M</em>,
            <em>Y</em> is sequenced before <em>B</em>, and <em>Y</em> reads the 
		value written by <em>X</em> or a value written by any side effect in the 
		hypothetical release sequence <em>X</em> would head if it were a release 
		operation.</blockquote>
    <blockquote>
        A release fence <em>A</em> synchronizes with an atomic operation <em>B</em>
            that performs an acquire operation on an atomic object <em>M</em> if 
		there exists an atomic operation <em>X</em> such that <em>A</em> is 
		sequenced before <em>X</em>, <em>X</em> modifies
		<em>M</em>, and <em>B</em> reads the value written by <em>X</em> or a 
		value written by any side effect in the hypothetical release sequence <em>
		X</em>
            would head if it were a release operation.</blockquote>
    <blockquote>
        An atomic operation <em>A</em> that is a release operation on an atomic 
		object <em>M</em>
            synchronizes with an acquire fence <em>B</em> if there exists some 
		atomic operation <em>
		X</em> on <em>M</em> such that <em>
		X</em> is sequenced before <em>B</em> and reads the value written by <em>
		A</em> or a value written by any side effect in the release sequence 
		headed by <em>A</em>.</blockquote>
    <blockquote>
        <code>void atomic_thread_fence(memory_order mo);</code></blockquote>
    <blockquote>
        <em>Effects:</em> Depending on the value of <code>mo</code>, this 
		operation:
        <ul>
            <li>has no effects, if <code>mo == memory_order_relaxed</code>;</li>
            <li>is an acquire fence, if <code>mo == memory_order_acquire || mo 
			== memory_order_consume</code>;</li>
            <li>is a release fence, if <code>mo == memory_order_release</code>;</li>
            <li>is both an acquire fence and a release fence, if <code>mo == 
			memory_order_acq_rel</code>;</li>
            <li>is a sequentially consistent acquire and release fence, if <code>
			mo == memory_order_seq_cst</code>.</li>
        </ul>
    </blockquote>
    <blockquote>
        <code>void atomic_signal_fence(memory_order mo);</code></blockquote>
    <blockquote>
        <em>Effects:</em> equivalent to <code>atomic_thread_fence(mo)</code>, 
		except that synchronizes with relationships are established only between 
		a thread and a signal handler executed in the same thread.</blockquote>
    <blockquote>
        [<em>Note:</em> <code>atomic_signal_fence</code> can be used to specify 
		the order in which actions performed by the thread become visible to the 
		signal handler. <em>&#8212; end note</em>]</blockquote>
    <blockquote>
        [<em>Note:</em> Compiler optimizations or reorderings of loads and 
		stores are inhibited in the same way as with <code>atomic_thread_fence</code>, 
		but the hardware fence instructions that <code>atomic_thread_fence</code> 
		would have inserted are not emitted.
        <em>&#8212; end note</em>]</blockquote>
    <hr />
    <p>
        <em>Thanks to Hans Boehm, Lawrence Crowl, Paul McKenney and Raul Silvera 
		for reviewing this paper.</em></p>
    <p>
        <em>--end</em></p>
</body>
</html>
