<!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: N3122=10-0112<br>
Date: 2010-08-16<br>
Author: Daniel Kr&uuml;gler<br>
Project: Programming Language C++, Library Working Group<br>
Reply-to: <a href="mailto:daniel.kruegler@googlemail.com">Daniel Kr&uuml;gler</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:
<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.[..]
</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>
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>
	
<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>
<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>
<p>
<h2><a name="Proposed_resolution"></a>Proposed resolution</h2>
<p>
<ol>
<li>Change 3.7.4.1 Allocation functions [basic.stc.dynamic.allocation] as indicated:

<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). &mdash; end note ]
</blockquote>
</li>
<li>Keep 17.6.3.7 Handler functions [handler.functions] unchanged:
<p>
<blockquote><p>
1 The C++ standard library provides default versions of the following handler functions (Clause 18):<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>
<ul>
<li><tt>set_new_handler</tt></li>
<li><tt>set_unexpected</tt></li>
<li><tt>set_terminate</tt></li>
</ul><p>
See also: subclauses 18.6.2, Storage allocation errors, and 18.8, Exception handling.
</blockquote><p>
</li>
<li>Change 18.6 [support.dynamic], header <tt>&lt;new&gt;</tt> synopsis as indicated:
<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() throw();</ins>
    new_handler set_new_handler(new_handler new_p) throw();
  }
  ...
</pre></blockquote>
<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]
<blockquote><pre>
void* operator new(std::size_t size) throw(std::bad_alloc);
</pre><p>
[...]<p>
4 Default behavior:<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]
<blockquote><pre>
new_handler set_new_handler(new_handler new_p) throw();
</pre><p>
1 Effects: Establishes the function designated by <tt>new_p</tt> as the current <tt>new_handler</tt>.<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>
<ins>3 <em>Remarks</em>: The initial <tt>new_handler</tt> is a null pointer.</ins><p>
</blockquote>
<p>
<ins>18.6.2.5 <tt>get_new_handler</tt> [get.new.handler]</ins>
<blockquote><pre>
<ins>new_handler get_new_handler() throw();</ins>
</pre><p>
<ins>1 Returns: The current <tt>new_handler</tt>. [Note: This may be a null pointer value &mdash; end note].</ins><p>
</blockquote><p>
</li>
<li>Change 18.8 [support.exception], header &lt;exception&gt; synopsis as indicated:
<p>
<blockquote><pre>
  namespace std {
    ...
    typedef void (*unexpected_handler)();
    <ins>unexpected_handler get_unexpected() throw();</ins>
    unexpected_handler set_unexpected(unexpected_handler f) throw();
    void unexpected [[noreturn]] ();
    typedef void (*terminate_handler)();
    <ins>terminate_handler get_terminate() throw();</ins>
    terminate_handler set_terminate(terminate_handler f) throw();
    void terminate [[noreturn]] ();
    ...
  }
  ...
</pre></blockquote>
<p>
</li>
<li>Keep 18.8.2.2 [unexpected.handler] unchanged:
<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>
2 Required behavior: An <tt>unexpected_handler</tt> shall not return. See also 15.5.2.<p>
3 Default behavior: The implementation's default <tt>unexpected_handler</tt> calls <tt>terminate()</tt>.
</blockquote><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]
<blockquote><pre>
unexpected_handler set_unexpected(unexpected_handler f) throw();
</pre><p>
1 Effects: Establishes the function designated by f as the current <tt>unexpected_handler</tt>.<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>
3 Returns: The previous <tt>unexpected_handler</tt>.<p>
</blockquote><p>
<ins>18.8.2.4 <tt>get_unexpected</tt> [get.unexpected]</ins>
<blockquote><pre>
<ins>unexpected_handler get_unexpected() throw();</ins>
</pre><p>
<ins>1 Returns: The current <tt>unexpected_handler</tt>. [Note: This may be a null pointer value &mdash; end note].</ins>
</blockquote><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]
<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>
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 &mdash; end note]</ins>
</blockquote><p>
</li>
<li>Keep 18.8.3.1 [terminate.handler] unchanged:
<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>
2 Required behavior: A <tt>terminate_handler</tt> shall terminate execution of the program without returning to the caller.<p>
3 Default behavior: The implementation's default <tt>terminate_handler</tt> calls <tt>abort()</tt>.
</blockquote><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]
<blockquote><pre>
terminate_handler set_terminate(terminate_handler f) throw();
</pre><p>
1 Effects: Establishes the function designated by f as the current handler function for terminating exception processing.<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>
3 Returns: The previous <tt>terminate_handler</tt>.
</blockquote><p>
<ins>18.8.3.3 <tt>get_terminate</tt> [get.terminate]</ins>
<blockquote><pre>
<ins>terminate_handler get_terminate() throw();</ins>
</pre><p>
<ins>1 Returns: The current <tt>terminate_handler</tt>. [Note: This may be a null pointer value &mdash; end note].</ins>
</blockquote>
<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]
<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>
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 &mdash; end note]</ins>
</blockquote><p>
</li>
</ol>
<p>

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