<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>


<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>Observers for the three handler functions</title>

<style type="text/css">
  p {text-align:justify}
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  blockquote.note
  {
   background-color:#E0E0E0;
   padding-left: 15px;
   padding-right: 15px;
   padding-top: 1px;
   padding-bottom: 1px;
  }
</style>
</head><body>
<address style="text-align: left;">
Document number: N3189=10-0179 revision of N3122=10-0112<br>
Date: 2010-11-12<br>
Author: Daniel Krgler, additional edits by Pablo Halpern, Peter Sommerlad<br>
Project: Programming Language C++, Library Working Group<br>
Reply-to: <a href="mailto:daniel.kruegler@googlemail.com">Daniel Krgler</a><br>
</address>
<hr>
<h1 style="text-align: center;">Observers for the three <em>handler functions</em></h1>

<h2><a name="Introduction"></a>Introduction</h2>
<p>
With the specification of concurrency within the <tt>C++</tt> Standard, the library needed to
define new requirements on library components and of user-code in the presence of a multi-threaded
environment especially in regard to the possibility of <em>data races</em>. Therefore [new.delete.dataraces]/1 says:
</p><blockquote><p>
The library versions of <tt>operator new</tt> and <tt>operator delete</tt>, user replacement versions of 
global <tt>operator new</tt> and <tt>operator delete</tt>, and the <tt>C</tt> standard library functions 
<tt>calloc</tt>, <tt>malloc</tt>, <tt>realloc</tt>, and <tt>free</tt> shall not introduce data races (1.10) 
as a result of concurrent calls from different threads.[..]
</p></blockquote>
<p>
These requirements become a problem for a user-defined replacement of <tt>operator new</tt> that attempts to
mimic some parts of the default version, especially the requirement to check the state of the <tt>new_handler</tt>
as described in [new.delete.single]/1. User-code can only portably use the <em>mutating</em> function <tt>set_new_handler()</tt>
to <em>read</em> the value of that handler function. This means that each call of the <tt>new</tt> operator
potentially introduces a data races because user-code and library-code can rely on the contract that
it is ok to allocate from the free store concurrently.
</p><p>
Several solutions to this problem exist, but during the Rapperswil meeting it was agreed on to provide for
<tt>C++0x</tt> at least the minimum necessary, namely to provide non-mutating getter functions of the
<tt>new_handler</tt> and for consistency also for the <tt>unexpected_handler</tt> and the <tt>terminate_handler</tt>.
This minimum requirement could still cause data races, when either of these handlers is explicitly
changed during the run-time of a program after <tt>main</tt>, but this situation is assumed to be a relatively 
rare situation in most programs and can still be changed in the future.
</p><p>
	
</p><h2><a name="Discussion"></a>Discussion</h2>
<p>
This proposal addresses NB comments DE 14 and GB 71 and suggests to perform the following changes against the current draft:
</p><p>
</p><ul>
<li>Provide the non-modifying functions <tt>get_new_handler()</tt>, <tt>get_unexpected()</tt>, and <tt>get_terminate()</tt>.
	This is the immediate request of DE 14 and GB 71 as a minimal solution 
to fix the inherent potential of data races in user-defined
	<tt>operator new</tt> replacements that attempt to simulate the default behaviour.</li>
<li>Relax the current strong invariants of the <tt>set_unexpected</tt> and <tt>set_terminate</tt> functions - the handler is never
a null pointer value. This reduces requirements on the implementor to define a non-null default handler. The suggested wording
does make the effects of setting a null pointer handler unspecified, though.</li>
</ul>
<h2><a name="Discussion"></a>Discussion in Batavia</h2>
<p>Discussion in LWG concluded that wording for protecting the underlying function pointer 
locations should be in this paper. A sentence like "calls to get_new_handler() etc. 
and set_new_handler() etc shall not incur a data race" should be added to each of these handlers. 
Implementations can use
atomic&lt;fp&gt; or a mutex to ensure such if multiple threads are available. Library implementations of
today might start multiple threads before main() gets called. That is the reason why we want the
stronger guarantee to avoid problems.
</p><p>
In addition Hans wants to make sure that 
the observable behavior is sequentially consistent. 
So that other things happening before a
set_new_handler call setting a value of X are observable by another thread that calls
set_new_handler/get_new_handler that read that value X.
</p><pre>
thread 1:                       thread 2:
y = 42
set_new_handler(X) ----------   get_new_handler()==X
                              assert(y == 42)
</pre><p>also adjusted all throw() to noexcept.
</p>
<p>
</p><h2><a name="Proposed_resolution"></a>Proposed resolution</h2>
<p>
</p><ol>
<li>Change 3.7.4.1 Allocation functions [basic.stc.dynamic.allocation] as indicated:

<p>
</p><blockquote><p>
3 - An allocation function that fails to allocate storage can invoke the currently installed new-handler function
(18.6.2.3), if any. [ Note: A program-supplied allocation function can obtain the address of the currently
installed <tt>new_handler</tt> using the <tt>std::<del>s</del><ins>g</ins>et_new_handler function</tt> (18.6.2.4). &#8212; end note ]
</p></blockquote>
</li>
<li>Change 17.6.3.7 Handler functions [handler.functions] as follows:
<p>
</p><blockquote><p>
1 The C++ standard library provides default versions of the following handler functions (Clause 18):</p><p>
</p><ul>
<li><tt>unexpected_handler</tt></li>
<li><tt>terminate_handler</tt></li>
</ul><p>
2 A C++ program may install different handler functions during execution, by supplying a pointer to a function
defined in the program or the library as an argument to (respectively):</p><p>
</p><ul>
<li><tt>set_new_handler</tt></li>
<li><tt>set_unexpected</tt></li>
<li><tt>set_terminate</tt></li>
</ul>
<p>
<ins>
3 A C++ program may query the current handler function pointer with the following 
functions (respectively):</p><p>
</p><ul>
<li><tt><ins>get_new_handler</ins></tt></li>
<li><tt><ins>get_unexpected</ins></tt></li>
<li><tt><ins>get_terminate</ins></tt></li>
</ul><p><ins>
Calling the "set_" functions or the corresponding "get_" functions shall not incur a data race.
Each "set_" function synchronizes with  subsequent
calls to the corresponding "set_" or "get_" function taking the value set.
</ins></p>
</ins>
<p>
See also: subclauses 18.6.2, Storage allocation errors, and 18.8, Exception handling.
</p>
</blockquote><p>

</p></li><li>Change 18.6 [support.dynamic], header <tt>&lt;new&gt;</tt> synopsis as indicated:
<p>
</p><blockquote><pre>  namespace std {
    class bad_alloc;
    class bad_array_new_length;
    struct nothrow_t {};
    extern const nothrow_t nothrow;
    typedef void (*new_handler)();
    <ins>new_handler get_new_handler() noexcept;</ins>
    new_handler set_new_handler(new_handler new_p) <del>throw()</del><ins>noexcept</ins>;
  }
  ...
</pre></blockquote>
<p>

</p></li><li>Relax the current specification of the default behaviour of <tt>operator new</tt> such that implementations have more
freedom to realize the same effects:
<p>
18.6.1.1 Single-object forms [new.delete.single]
</p><blockquote><pre>void* operator new(std::size_t size) throw(std::bad_alloc);
</pre><p>
[...]</p><p>
4 Default behavior:</p><p>
</p><ul>
<li>Executes a loop: Within the loop, the function first attempts to allocate the requested storage.
Whether the attempt involves a call to the Standard C library function <tt>malloc</tt> is unspecified.</li>
<li>Returns a pointer to the allocated storage if the attempt is successful. Otherwise, if the <del>argument
in the most recent call to <tt>set_new_handler()</tt> ([set.new.handler]) was</del><ins>current <tt>new_handler</tt> ([get.new.handler]) 
is</ins> a null pointer <ins>value</ins>, throws <tt>bad_alloc</tt>.</li>
<li>Otherwise, the function calls the current <tt>new_handler</tt> function (18.6.2.3). If the called function
returns, the loop repeats.</li>
<li>The loop terminates when an attempt to allocate the requested storage is successful or when a
called <tt>new_handler</tt> function does not return.</li>
</ul>
</blockquote>
</li>
<li>Change 18.6.2.4/2 as indicated for better clarification that the initial <tt>new_handler</tt> is a null pointer. Following 
	18.6.2.4, [set.new.handler], insert a new subclause as indicated:
<p>
18.6.2.4 <tt>set_new_handler</tt> [set.new.handler]
</p><blockquote><pre>new_handler set_new_handler(new_handler new_p) <del>throw()</del><ins>noexcept</ins>;
</pre><p>
1 Effects: Establishes the function designated by <tt>new_p</tt> as the current <tt>new_handler</tt>.</p><p>
2 Returns: <del>0 on the first call, the previous <tt>new_handler</tt> on subsequent calls</del><ins>The previous <tt>new_handler</tt>.</ins></p><p>
<ins>3 <em>Remarks</em>: The initial <tt>new_handler</tt> is a null pointer.</ins></p><p>
</p></blockquote>
<p>
<ins>18.6.2.5 <tt>get_new_handler</tt> [get.new.handler]</ins>
</p><blockquote><pre><ins>new_handler get_new_handler() noexcept;</ins>
</pre><p>
<ins>1 Returns: The current <tt>new_handler</tt>. [Note: This may be a null pointer value &#8212; end note].</ins></p><p>
</p></blockquote><p>

</p></li><li>Change 18.8 [support.exception], header &lt;exception&gt; synopsis as indicated:
<p>
</p><blockquote><pre>  namespace std {
    ...
    typedef void (*unexpected_handler)();
    <ins>unexpected_handler get_unexpected() noexcept;</ins>
    unexpected_handler set_unexpected(unexpected_handler f) <del>throw()</del><ins>noexcept</ins>;
    void unexpected [[noreturn]] ();
    typedef void (*terminate_handler)();
    <ins>terminate_handler get_terminate() noexcept;</ins>
    terminate_handler set_terminate(terminate_handler f) <del>throw()</del><ins>noexcept</ins>;
    void terminate [[noreturn]] ();
    ...
  }
  ...
</pre></blockquote>
<p>

</p></li><li>Keep 18.8.2.2 [unexpected.handler] unchanged:
<p>
</p><blockquote><pre>typedef void (*unexpected_handler)();
</pre><p>
1 The type of a handler function to be called by <tt>unexpected()</tt> when a function attempts to throw an
exception not listed in its dynamic-exception-specification.</p><p>
2 Required behavior: An <tt>unexpected_handler</tt> shall not return. See also 15.5.2.</p><p>
3 Default behavior: The implementation's default <tt>unexpected_handler</tt> calls <tt>terminate()</tt>.
</p></blockquote><p>

</p></li><li>Replace the requirement that the new handler shall be not 
null by a normative remark that doing so has unspecified effects. 
Following 
18.8.2.3, [set.unexpected], insert a new subclause as indicated:
<p>
18.8.2.3 <tt>set_unexpected</tt> [set.unexpected]
</p><blockquote><pre>unexpected_handler set_unexpected(unexpected_handler f) <del>throw()</del><ins>noexcept</ins>;
</pre><p>
1 Effects: Establishes the function designated by f as the current <tt>unexpected_handler</tt>.</p><p>
2 <del>Requires: <tt>f</tt> shall not be a null pointer.</del><ins><em>Remarks</em>: It is unspecified whether a null pointer value 
designates the default <tt>unexpected_handler</tt>.</ins></p><p>
3 Returns: The previous <tt>unexpected_handler</tt>.</p><p>
</p></blockquote><p>
<ins>18.8.2.4 <tt>get_unexpected</tt> [get.unexpected]</ins>
</p><blockquote><pre><ins>unexpected_handler get_unexpected() noexcept;</ins>
</pre><p>
<ins>1 Returns: The current <tt>unexpected_handler</tt>. [Note: This may be a null pointer value &#8212; end note].</ins>
</p></blockquote><p>

</p></li><li>Change 18.8.2.4 [unexpected] (that has now been renumbered to 18.8.2.5) as indicated: The suggested rewording 
is supposed to achieve the following effects: Paragraph 1 does now solely concentrate on the conditions, <em>when</em>
<tt>unexpected</tt> is called, and paragraph 2 now solely concentrates on the call effects and clarifies that even
a null default handler behaves as-if it were a non-null pointer.
<p>
18.8.2.4 <tt>unexpected</tt> [unexpected]
</p><blockquote><pre>void unexpected [[noreturn]] ();
</pre><p>
1 <ins>Remarks:</ins> Called by the implementation when a function exits via an exception not allowed by its <em>exception-specification</em>
(15.5.2)<ins>, in effect immediately after evaluating the <em>throw-expression</em> (18.8.2.2)</ins>. May also be called directly by the program.</p><p>
2 Effects: <del>Calls the <tt>unexpected_handler</tt> function in effect immediately after evaluating the <em>throw-expression</em>
(18.8.2.2), if called by the implementation, or calls the current <tt>unexpected_handler</tt>, if called by the program.</del><ins>Calls the 
	current <tt>unexpected_handler</tt> function. [Note: A default <tt>unexpected_handler</tt> is always considered a callable handler in this
	context &#8212; end note]</ins>
</p></blockquote><p>

</p></li><li>Keep 18.8.3.1 [terminate.handler] unchanged:
<p>
</p><blockquote><pre>typedef void (*terminate_handler)();
</pre><p>
1 The type of a handler function to be called by <tt>terminate()</tt> when terminating exception processing.</p><p>
2 Required behavior: A <tt>terminate_handler</tt> shall terminate execution of the program without returning to the caller.</p><p>
3 Default behavior: The implementation's default <tt>terminate_handler</tt> calls <tt>abort()</tt>.
</p></blockquote><p>

</p></li><li>Following 18.8.3.2, [set.terminate], insert a new subclause as indicated:<p>
18.8.3.2 <tt>set_terminate</tt> [set.terminate]
</p><blockquote><pre>terminate_handler set_terminate(terminate_handler f) <del>throw()</del><ins>noexcept</ins>;
</pre><p>
1 Effects: Establishes the function designated by f as the current handler function for terminating exception processing.</p><p>
2 <del>Requires: f shall not be a null pointer.</del><ins><em>Remarks</em>: It is unspecified whether a null pointer value 
designates the default <tt>terminate_handler</tt>.</ins></p><p>
3 Returns: The previous <tt>terminate_handler</tt>.
</p></blockquote><p>
<ins>18.8.3.3 <tt>get_terminate</tt> [get.terminate]</ins>
</p><blockquote><pre><ins>terminate_handler get_terminate() noexcept;</ins>
</pre><p>
<ins>1 Returns: The current <tt>terminate_handler</tt>. [Note: This may be a null pointer value &#8212; end note].</ins>
</p></blockquote>
<p>

</p></li><li>Change 18.8.3.3 [terminate] (that has now been renumbered to 18.8.3.4) as indicated. The suggested rewording 
is supposed to achieve the following effects: Paragraph 1 does now solely concentrate on the conditions, <em>when</em>
<tt>terminate</tt> is called, and paragraph 2 now solely concentrates on the call effects and clarifies that even
a null default handler behaves as-if it were a non-null pointer.
<p>
18.8.3.3 <tt>terminate</tt> [terminate]
</p><blockquote><pre>void terminate [[noreturn]] ();
</pre><p>
1 <ins>Remarks:</ins> Called by the implementation when exception handling must be abandoned for any of several reasons
(15.5.1)<ins>, in effect immediately after evaluating the <em>throw-expression</em> (18.8.3.1)</ins>. May also be called 
directly by the program.</p><p>
2 Effects: <del>Calls the <tt>terminate_handler</tt> function in effect immediately after evaluating the <em>throw-expression</em>
(18.8.3.1), if called by the implementation, or calls the current <tt>terminate_handler</tt> function, if called by the program.</del><ins>Calls 
	the current <tt>terminate_handler</tt> function. [Note: A default <tt>terminate_handler</tt> is always considered a callable handler in this
	context &#8212; end note]</ins>
</p></blockquote><p>

</p></li></ol>
<p>

</p>
</body></html>