Topic: Transaction lifetime oriented replacement for uncaught_exception


Author: David Krauss <potswa@gmail.com>
Date: Thu, 12 Sep 2013 01:24:39 -0700 (PDT)
Raw View
------=_Part_377_16741258.1378974279918
Content-Type: text/plain; charset=ISO-8859-1

This diverges from a current thread<https://groups.google.com/a/isocpp.org/forum/#%21topic/std-proposals/DZ7f9XLh3us>,
which in turn proposes a variation on other<https://groups.google.com/a/isocpp.org/forum/?fromgroups#%21searchin/std-proposals/destructor/std-proposals/CYXxUYYT_tE/7kiYV4gEkGEJ>
proposals <http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3614.pdf>.

Much effort has focused on providing the interface for an object to discern
whether it is being destroyed "normally" or "exceptionally." We already
have such an interface as std::uncaught_exception since C++98, but its
definition of "exceptional" was found to be defective<http://www.gotw.ca/gotw/047.htm>.
In the other thread, I suggest that the calling context alone does not
contain enough information to generally discern the destruction category
(so any such definition will be defective). Now I'm not sure that context
is relevant at all, but instead "normal" or "exceptional" is defined by a
relationship between the object and the exception object. The solution may
require few runtime library changes, but mainly an extension to
std::exception.

The only conceptual application seems to be transaction objects. Upon
destruction, such an object ascertains success or failure. So far, there
has not been a definition of success or failure, but the implicit consensus
is that failure is identical to destruction of the transaction by stack
unwinding. This breaks down, though, if the transaction is not scope-bound
(i.e. of automatic storage duration). It may be a fallacy caused by the
fact that stack unwinding is the last thing that happens to a transaction
which is scope-bound.

Suppose a transaction outlives its try block, and is destroyed in the catchblock instead.

std::optional< transaction > s;
try {
    s = transaction(); // Create transaction.
    if ( condition1() ) {
        throw 42;
    }
} catch ( ... ) {
    s = std::nullopt; // Destroy transaction.
}
if ( condition2() ) {
    s = std::nullopt; // Also destroy transaction.
}
// Natural end of transaction lifetime here.

The transaction in the throw 42 case is not living its full, natural life.
It died inside an exception handler. Although the handler could have
performed cleanup prior to the explicit destruction, such that the
operation could succeed, that is not the correct assumption for
exception-handling code that doesn't somehow say commit(). Likewise, if
there is an automatic commit and it throws, the original exception would be
lost and replaced by one from the more specific context of the commit
failure.

The conditional destruction if ( condition2() ) is similar, but nothing
contextually indicates failure, and there is no reason not to throw an
exception. Such syntax looks ugly here, to be sure. But if you have some
transaction objects and you indirectly incur their destruction, should they
be reverted or committed? (This is the gist of the whole issue.) Reversion
here means data loss. So, this destruction is more safely treated as
success.

I posit that a transaction should detect failure if its destruction was
precipitated by an exception which is younger than it. When a program
constructs an exception object (usually within a throw-expression), it must
be preparing to handle some condition. (I mean any object of a type
dedicated to exception handling, such as std::exception, not specifically
the temporary in implementation-specific storage.) Any transaction
constructed once the exception already exists cannot reasonably be looking
for failure of a preexisting condition. (Maybe if it's trying to collect on
a big insurance policy, but we should always make the strictly ethical
choice in such a dilemma. </joke>) While the exception object is
"activated" (between evaluation of throw and exit from the catch block), it
is responsible for the flow of execution, and destruction of any
preexisting transaction can be considered a consequence.

The "younger than" relationship must be implemented somehow, and despite
its temporal nature, accommodate multithreading. (I have no experience in
multithreaded exception handling, and this is probably uncharted territory,
so critiques are welcome.) Sentries and exceptions must initialize ticket
objects, upon construction, and the tickets totally order the creation of
the objects on a timeline. In a multithreading context, this requires
locking.

As for the interface, the ticket inside the exception object should
probably be hidden. A library function can find the newest active exception
and compare it to a given ticket, returning a Boolean value suitable for
flow control.

bool transaction_precedes_latest_exception( transaction_ticket );

Perhaps a general function to compare any ticket to any exception would
also be useful, but might place unreasonable demands on the implementation.
Given the above semantics, you could *not* simply temporarily throw (or
reactivate) the exception before querying the above function in a dedicated
catch block, because the comparison is against the newest exception object,
not the last one to be thrown.

Exception types not derived from std::exception, or not containing a ticket
or sequence information, would simply be transparent to the whole system.

It would improve flexibility (and likely help performance) to provide one
default, global ticket issuer, and allow the user to specify additional
issuers, perhaps with custom implementation to avoid unnecessary
synchronization. The application would thus be divided into exception
domains, and the "latest exception" query would skip exceptions from
domains different from the specified transaction. To achieve this, tickets
and exceptions would need an optional issuer parameter, and of course a
means of defining issuers would be needed.

So far, it seems to me that the simplest implementation of tickets would be
a linked list, but this results in the query being O(N) in the number of
transactions initiated since to the last (activated) exception object.

The good news? All this should be possible to prototype without any
language support. The only special operation is getting the last thrown
exception (or rather, notifying an exception that it is being thrown). But
in most usage std::exception doesn't exist *except* as an exception object,
or a temporary operand of a throw expression. A reasonable prototype can
simply ignore the distinction and suppose that any exception is activated
for its whole lifetime.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_377_16741258.1378974279918
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">This diverges from <a href=3D"https://groups.google.com/a/=
isocpp.org/forum/#%21topic/std-proposals/DZ7f9XLh3us">a current thread</a>,=
 which in turn proposes a variation on <a href=3D"https://groups.google.com=
/a/isocpp.org/forum/?fromgroups#%21searchin/std-proposals/destructor/std-pr=
oposals/CYXxUYYT_tE/7kiYV4gEkGEJ">other</a> <a href=3D"http://open-std.org/=
JTC1/SC22/WG21/docs/papers/2013/n3614.pdf">proposals</a>.<br><br>Much effor=
t has focused on providing the interface for an object to discern whether i=
t is being destroyed "normally" or "exceptionally." We already have such an=
 interface as <span style=3D"font-family: courier new,monospace;">std::unca=
ught_exception</span> since C++98, but its definition of "exceptional" was =
<a href=3D"http://www.gotw.ca/gotw/047.htm">found to be defective</a>. In t=
he other thread, I suggest that the calling context alone does not contain =
enough information to generally discern the destruction category (so any su=
ch definition will be defective). Now I'm not sure that context is relevant=
 at all, but instead "normal" or "exceptional" is defined by a relationship=
 between the object and the exception object. The solution may require few =
runtime library changes, but mainly an extension to <span style=3D"font-fam=
ily: courier new,monospace;">std::exception</span>.<br><br>The only concept=
ual application seems to be transaction objects. Upon destruction, such an =
object ascertains success or failure. So far, there has not been a definiti=
on of success or failure, but the implicit consensus is that failure is ide=
ntical to destruction of the transaction by stack unwinding. This breaks do=
wn, though, if the transaction is not scope-bound (i.e. of automatic storag=
e duration). It may be a fallacy caused by the fact that stack unwinding is=
 the last thing that happens to a transaction which is scope-bound.<br><br>=
Suppose a transaction outlives its <span style=3D"font-family: courier new,=
monospace;">try</span> block, and is destroyed in the <span style=3D"font-f=
amily: courier new,monospace;">catch</span> block instead.<br><br><div clas=
s=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-col=
or: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: =
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">optional</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> transaction </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> s</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">try</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; s =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> transaction</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #800;" class=3D"styled-by-prettify">// Create transaction.</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> condition1</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">throw</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prett=
ify">42</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &=
nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">catch</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; s </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">nullopt</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// Destroy transaction.</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">if=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> condition2</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>&nbsp; &nbsp; s </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">nullo=
pt</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #800;" class=3D"styled-by-prettify">// Also destroy transactio=
n.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// Natural end of transactio=
n lifetime here.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span></div></code></div><br>The transaction in the <span style=
=3D"font-family: courier new,monospace;">throw 42</span> case is not living=
 its full, natural life. It died inside an exception handler. Although the =
handler could have performed cleanup prior to the explicit destruction, suc=
h that the operation could succeed, that is not the correct assumption for =
exception-handling code that doesn't somehow say <span style=3D"font-family=
: courier new,monospace;">commit()</span>. Likewise, if there is an automat=
ic commit and it throws, the original exception would be lost and replaced =
by one from the more specific context of the commit failure.<br><br>The con=
ditional destruction <span style=3D"font-family: courier new,monospace;">if=
 ( condition2() )</span> is similar, but nothing contextually indicates fai=
lure, and there is no reason not to throw an exception. Such syntax looks u=
gly here, to be sure. But if you have some transaction objects and you indi=
rectly incur their destruction, should they be reverted or committed? (This=
 is the gist of the whole issue.) Reversion here means data loss. So, this =
destruction is more safely treated as success.<br><br>I posit that a transa=
ction should detect failure if its destruction was precipitated by an excep=
tion which is younger than it. When a program constructs an exception objec=
t (usually within a throw-expression), it must be preparing to handle some =
condition. (I mean any object of a type dedicated to exception handling, su=
ch as <span style=3D"font-family: courier new,monospace;">
std::exception</span>, not specifically the temporary in=20
implementation-specific storage.) Any transaction constructed once the exce=
ption already exists cannot reasonably be looking for failure of a preexist=
ing condition. (Maybe if it's trying to collect on a big insurance policy, =
but we should always make the strictly ethical choice in such a dilemma. &l=
t;/joke&gt;) While the exception object is "activated" (between evaluation =
of <span style=3D"font-family: courier new,monospace;">throw</span> and exi=
t from the <span style=3D"font-family: courier new,monospace;">catch</span>=
 block), it is responsible for the flow of execution, and destruction of an=
y preexisting transaction can be considered a consequence.<br><br>The "youn=
ger than" relationship must be implemented somehow, and despite its tempora=
l nature, accommodate multithreading. (I have no experience in multithreade=
d exception handling, and this is probably uncharted territory, so critique=
s are welcome.) Sentries and exceptions must initialize ticket objects, upo=
n construction, and the tickets totally order the creation of the objects o=
n a timeline. In a multithreading context, this requires locking.<br><br>As=
 for the interface, the ticket inside the exception object should probably =
be hidden. A library function can find the newest active exception and comp=
are it to a given ticket, returning a Boolean value suitable for flow contr=
ol.<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">b=
ool</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> transa=
ction_precedes_latest_exception</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> transaction_ticket </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span></div></code></div><br>Perhaps a general functio=
n to compare any ticket to any exception would=20
also be useful, but might place unreasonable demands on the=20
implementation. Given the above semantics, you could <i>not</i> simply temp=
orarily throw (or reactivate) the exception before querying the above funct=
ion in a dedicated catch block, because the comparison is against the newes=
t exception object, not the last one to be thrown.<br><br>Exception types n=
ot derived from <span style=3D"font-family: courier new,monospace;">std::ex=
ception</span>, or not containing a ticket or sequence information, would s=
imply be transparent to the whole system.<br><br>It would improve flexibili=
ty (and likely help performance) to provide=20
one default, global ticket issuer, and allow the user to specify=20
additional issuers, perhaps with custom implementation to avoid=20
unnecessary synchronization. The application would thus be divided into=20
exception domains, and the "latest exception" query would skip exceptions f=
rom domains different from the specified transaction. To achieve this, tick=
ets and exceptions would need an optional issuer parameter, and of course a=
 means of defining issuers would be needed.<br><br>So far, it seems to me t=
hat the simplest implementation of tickets would be a linked list, but this=
 results in the query being O(N) in the number of transactions initiated si=
nce to the last (activated) exception object.<br><br>The good news? All thi=
s should be possible to prototype without any language support. The only sp=
ecial operation is getting the last thrown exception (or rather, notifying =
an exception that it is being thrown). But in most usage <span style=3D"fon=
t-family: courier new,monospace;">std::exception</span> doesn't exist <i><s=
pan style=3D"font-family: arial,sans-serif;">except</span></i> as an except=
ion object, or a temporary operand of a <span style=3D"font-family: courier=
 new,monospace;">throw</span> expression. A reasonable prototype can simply=
 ignore the distinction and suppose that any <span style=3D"font-family: co=
urier new,monospace;">exception</span> is activated for its whole lifetime.=
<br></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_377_16741258.1378974279918--

.


Author: inkwizytoryankes@gmail.com
Date: Fri, 13 Sep 2013 12:03:39 -0700 (PDT)
Raw View
------=_Part_1353_28820778.1379099019992
Content-Type: text/plain; charset=ISO-8859-1



On Thursday, September 12, 2013 10:24:39 AM UTC+2, David Krauss wrote:
>
>
> I posit that a transaction should detect failure if its destruction was
> precipitated by an exception which is younger than it. When a program
> constructs an exception object (usually within a throw-expression), it must
> be preparing to handle some condition. (I mean any object of a type
> dedicated to exception handling, such as std::exception, not specifically
> the temporary in implementation-specific storage.) Any transaction
> constructed once the exception already exists cannot reasonably be looking
> for failure of a preexisting condition. (Maybe if it's trying to collect on
> a big insurance policy, but we should always make the strictly ethical
> choice in such a dilemma. </joke>) While the exception object is
> "activated" (between evaluation of throw and exit from the catch block),
> it is responsible for the flow of execution, and destruction of any
> preexisting transaction can be considered a consequence.
>
> The "younger than" relationship must be implemented somehow, and despite
> its temporal nature, accommodate multithreading. (I have no experience in
> multithreaded exception handling, and this is probably uncharted territory,
> so critiques are welcome.) Sentries and exceptions must initialize ticket
> objects, upon construction, and the tickets totally order the creation of
> the objects on a timeline. In a multithreading context, this requires
> locking.
>
> How you want made total order of exception in multithread program? You can
made list of them but you cant reasoning about order in that list. Another
thing is that exception form one thread can outlive multiple exceptions
form second thread. Because of this if you send transaction object to
another thread you cant predict how it will be destroyed.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1353_28820778.1379099019992
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Thursday, September 12, 2013 10:24:39 AM UTC+2,=
 David Krauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br>I posit that a transaction should detect failure if its destru=
ction was precipitated by an exception which is younger than it. When a pro=
gram constructs an exception object (usually within a throw-expression), it=
 must be preparing to handle some condition. (I mean any object of a type d=
edicated to exception handling, such as <span style=3D"font-family:courier =
new,monospace">
std::exception</span>, not specifically the temporary in=20
implementation-specific storage.) Any transaction constructed once the exce=
ption already exists cannot reasonably be looking for failure of a preexist=
ing condition. (Maybe if it's trying to collect on a big insurance policy, =
but we should always make the strictly ethical choice in such a dilemma. &l=
t;/joke&gt;) While the exception object is "activated" (between evaluation =
of <span style=3D"font-family:courier new,monospace">throw</span> and exit =
from the <span style=3D"font-family:courier new,monospace">catch</span> blo=
ck), it is responsible for the flow of execution, and destruction of any pr=
eexisting transaction can be considered a consequence.<br><br>The "younger =
than" relationship must be implemented somehow, and despite its temporal na=
ture, accommodate multithreading. (I have no experience in multithreaded ex=
ception handling, and this is probably uncharted territory, so critiques ar=
e welcome.) Sentries and exceptions must initialize ticket objects, upon co=
nstruction, and the tickets totally order the creation of the objects on a =
timeline. In a multithreading context, this requires locking.<br><br></div>=
</blockquote><div>How you want made total order of exception in multithread=
 program? You can made list of them but you cant reasoning about order in t=
hat list. Another thing is that exception form one thread can outlive multi=
ple exceptions form second thread. Because of this if you send transaction =
object to another thread you cant predict how it will be destroyed.<br></di=
v></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1353_28820778.1379099019992--

.


Author: David Krauss <potswa@gmail.com>
Date: Fri, 13 Sep 2013 18:03:52 -0700 (PDT)
Raw View
------=_Part_1730_12324739.1379120632066
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable



On Saturday, September 14, 2013 3:03:39 AM UTC+8, inkwizyt...@gmail.com=20
wrote:
>
>
>
> On Thursday, September 12, 2013 10:24:39 AM UTC+2, David Krauss wrote:
>>
>>
>> I posit that a transaction should detect failure if its destruction was=
=20
>> precipitated by an exception which is younger than it. When a program=20
>> constructs an exception object (usually within a throw-expression), it m=
ust=20
>> be preparing to handle some condition. (I mean any object of a type=20
>> dedicated to exception handling, such as std::exception, not=20
>> specifically the temporary in implementation-specific storage.) Any=20
>> transaction constructed once the exception already exists cannot reasona=
bly=20
>> be looking for failure of a preexisting condition. (Maybe if it's trying=
 to=20
>> collect on a big insurance policy, but we should always make the strictl=
y=20
>> ethical choice in such a dilemma. </joke>) While the exception object is=
=20
>> "activated" (between evaluation of throw and exit from the catch block),=
=20
>> it is responsible for the flow of execution, and destruction of any=20
>> preexisting transaction can be considered a consequence.
>>
>> The "younger than" relationship must be implemented somehow, and despite=
=20
>> its temporal nature, accommodate multithreading. (I have no experience i=
n=20
>> multithreaded exception handling, and this is probably uncharted territo=
ry,=20
>> so critiques are welcome.) Sentries and exceptions must initialize ticke=
t=20
>> objects, upon construction, and the tickets totally order the creation o=
f=20
>> the objects on a timeline. In a multithreading context, this requires=20
>> locking.
>>
>> How you want made total order of exception in multithread program? You=
=20
> can made list of them but you cant reasoning about order in that list.
>

The most the environment can do is to lock the list, for is own integrity.=
=20
The program should have its own synchronization around error handling, to=
=20
stop generating more problems after one is detected.

Transactions will only be rolled back if they are destroyed during the=20
course of exception handling, which on a different thread requires explicit=
=20
action. (It won't happen by unwinding.) So the user has to order the=20
exception only after all transactions that could be destroyed by it.

Unconditionally rolling back newer transactions (perhaps from another=20
thread) is easy: just make a new exception, even within the handling of an=
=20
"old" exception. But this sort of thing smells. You get a race condition=20
between the end of exception handling (when the program stops generating=20
new exceptions), and new transactions on other threads which=20
nondeterministically cease to get "kidnapped" by the loop on the exception=
=20
handling thread.

Unconditional committing can be done by assigning a new,=20
default-constructed ticket into the transaction before destroying it during=
=20
exception handling. It's a funny way to handle an exception, though.

Multiple ticket issuers should resolve any issues caused by differing=20
notions of what constitutes an error, and fix performance problems from=20
lock contention or list size. The idea is to provide the user with tools=20
for reasoning, as an extension of RAII to other contexts. Of course the=20
environment can't always be psychic.
=20

> Another thing is that exception form one thread can outlive multiple=20
> exceptions form second thread. Because of this if you send transaction=20
> object to another thread you cant predict how it will be destroyed.
>

Once an exception's final catch block exits, it's not considered current.=
=20
The existence of constructed, but not thrown, and handled, but not=20
destroyed, exceptions is the only part of this requiring runtime library=20
support.

Or if you mean something else, only the newest active exception *on the=20
current thread* should be considered by=20
transaction_precedes_latest_exception. So things won't just randomly be=20
canceled =97 the intent is to detect what exception is responsible for the=
=20
current control flow context.

Likewise std::rethrow_exception can reactivate a stale, old exception which=
=20
predates all live transactions. The user needs to be aware of the rules.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_1730_12324739.1379120632066
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Saturday, September 14, 2013 3:03:39 AM UTC+8, =
inkwizyt...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><br><br>On Thursday, September 12, 2013 10:24:39 AM UTC+2, D=
avid Krauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<br>I posit that a transaction should detect failure if its destruction was=
 precipitated by an exception which is younger than it. When a program cons=
tructs an exception object (usually within a throw-expression), it must be =
preparing to handle some condition. (I mean any object of a type dedicated =
to exception handling, such as <span style=3D"font-family:courier new,monos=
pace">
std::exception</span>, not specifically the temporary in=20
implementation-specific storage.) Any transaction constructed once the exce=
ption already exists cannot reasonably be looking for failure of a preexist=
ing condition. (Maybe if it's trying to collect on a big insurance policy, =
but we should always make the strictly ethical choice in such a dilemma. &l=
t;/joke&gt;) While the exception object is "activated" (between evaluation =
of <span style=3D"font-family:courier new,monospace">throw</span> and exit =
from the <span style=3D"font-family:courier new,monospace">catch</span> blo=
ck), it is responsible for the flow of execution, and destruction of any pr=
eexisting transaction can be considered a consequence.<br><br>The "younger =
than" relationship must be implemented somehow, and despite its temporal na=
ture, accommodate multithreading. (I have no experience in multithreaded ex=
ception handling, and this is probably uncharted territory, so critiques ar=
e welcome.) Sentries and exceptions must initialize ticket objects, upon co=
nstruction, and the tickets totally order the creation of the objects on a =
timeline. In a multithreading context, this requires locking.<br><br></div>=
</blockquote><div>How you want made total order of exception in multithread=
 program? You can made list of them but you cant reasoning about order in t=
hat list.</div></div></blockquote><div><br>The most the environment can do =
is to lock the list, for is own integrity. The program should have its own =
synchronization around error handling, to stop generating more problems aft=
er one is detected.<br><br>Transactions will only be rolled back if they ar=
e destroyed during the course of exception handling, which on a different t=
hread requires explicit action. (It won't happen by unwinding.) So the user=
 has to order the exception only after all transactions that could be destr=
oyed by it.<br><br>Unconditionally rolling back newer transactions (perhaps=
 from another thread) is easy: just make a new exception, even within the h=
andling of an "old" exception. But this sort of thing smells. You get a rac=
e condition between the end of exception handling (when the program stops g=
enerating new exceptions), and new transactions on other threads which nond=
eterministically cease to get "kidnapped" by the loop on the exception hand=
ling thread.<br><br>Unconditional committing can be done by assigning a new=
, default-constructed ticket into the transaction before destroying it duri=
ng exception handling. It's a funny way to handle an exception, though.<br>=
<br>Multiple ticket issuers should resolve any issues caused by differing n=
otions of what constitutes an error, and fix performance problems from lock=
 contention or list size. The idea is to provide the user with tools for re=
asoning, as an extension of RAII to other contexts. Of course the environme=
nt can't always be psychic.<br>&nbsp;</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div dir=3D"ltr"><div> Another thing is that exception form on=
e thread can outlive multiple exceptions form second thread. Because of thi=
s if you send transaction object to another thread you cant predict how it =
will be destroyed.<br></div></div></blockquote><div><br>Once an exception's=
 final <span style=3D"font-family: courier new,monospace;">catch</span> blo=
ck exits, it's not considered current. The existence of constructed, but no=
t thrown, and handled, but not destroyed, exceptions is the only part of th=
is requiring runtime library support.<br><br>Or if you mean something else,=
 only the newest active exception <i><span style=3D"font-family: arial,sans=
-serif;">on the current thread</span></i> should be considered by <code><sp=
an style=3D"color:#000">transaction_precedes_latest_<wbr>exception</span><s=
pan style=3D"color:#660"></span></code>. So things won't just randomly be c=
anceled =97 the intent is to detect what exception is responsible for the c=
urrent control flow context.<br><br>Likewise <span style=3D"font-family: co=
urier new,monospace;">std::rethrow_exception</span> can reactivate a stale,=
 old exception which predates all live transactions. The user needs to be a=
ware of the rules.<br></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1730_12324739.1379120632066--

.


Author: Evgeny Panasyuk <evgeny.panasyuk@gmail.com>
Date: Sun, 6 Oct 2013 11:29:13 -0700 (PDT)
Raw View
------=_Part_183_4500290.1381084153332
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: quoted-printable

12 oct 2013 =C7., 12:24:39 UTC+4 David Krauss :

> I posit that a transaction should detect failure if its destruction was=
=20
> precipitated by an exception which is younger than it.
>

Let me clarify, do you propose something like this?
class UnwindingIndicator
{
    ExceptionSerialNumber enter_state;
public:
    UnwindingIndicator()
        : enter_state( exception_serial_number() )
    {}
    bool failure() const
    {
        return enter_state < exception_serial_number();
    }
};

It is not reliable even if not take into account multi-threading or=20
std::rethrow_exception.
Just for example - http://ideone.com/qFTAVW :
#include <utility>
#include <memory>
using namespace std;

auto condition =3D true;
unique_ptr<int> global;

int main()
try
{
    unique_ptr<int> local;
    {
        struct ScopeExit
        {
            ~ScopeExit()
            try
            {
                unique_ptr<int> temp(new int(0));
                if(condition)
                    global =3D move(temp);
            } catch(...){}
        } scope_exit;
        throw 0;
    }
    local =3D move(global);
} catch(int){}
Depending on condition int can be destructed in destructor of "temp" or=20
"local". In both of them exception_serial_number() is same, but in one case=
=20
it is not failure (in "temp" destructor), but in other it is (in "local"=20
destructor).

I think that any kind of solution based on comparison of two exceptions=20
states is not reliable for 100%, by design.
C++ has heap objects, such objects can "fly" to any place with every=20
possible exception state since it's creation, it can be destructed in=20
context of any other destructor.
And whenever it is OK to throw from destructor of heap object depends more=
=20
on surrounding context, rather than solely on exception state, because=20
destruction may happen within any other destructor, where it may be safe to=
=20
throw, because that destructor has opportunity to catch, or it may be not=
=20
safe, because that destructor itself have thrown exception.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_183_4500290.1381084153332
Content-Type: text/html; charset=KOI8-R
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">12 oct 2013&nbsp;=C7., 12:24:39 UTC+4 David Krauss :<br><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I posit that a =
transaction should detect failure if its destruction was precipitated by an=
 exception which is younger than it.<br></div></blockquote><div><br>Let me =
clarify, do you propose something like this?<br><div class=3D"prettyprint" =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; word-wrap: break-word;"><code=
 class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">UnwindingIndicator</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">ExceptionSerialNumber</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> enter_state</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">public</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #606;" class=3D"s=
tyled-by-prettify">UnwindingIndicator</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> enter_state</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> exception_serial_number</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> failure</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
onst</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nb=
sp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> enter_state </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> exception_serial_number</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">};</span></div></code></div><br>It is not reliable even if not ta=
ke into account multi-threading or <span style=3D"font-family:courier new,m=
onospace">std::rethrow_exception</span>.<br>Just for example - http://ideon=
e.com/qFTAVW :<br><div class=3D"prettyprint" style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">#include</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;u=
tility&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">#inclu=
de</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;memory&gt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">using</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">namespace</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> condition </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">true</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>unique_p=
tr</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;int&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">global</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">try</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>&nbsp; &nbsp; unique_ptr</span><span style=3D"color: #080;" class=3D"sty=
led-by-prettify">&lt;int&gt;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">local</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">ScopeExit</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">~</span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">ScopeExit</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">try</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &n=
bsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
unique_ptr</span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
&lt;int&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> temp</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">new</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;=
" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">));</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp=
; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">condition</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nb=
sp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">global</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> move</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">temp<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &=
nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
atch</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(...){=
}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp=
; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> scope_exit</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">throw</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pretti=
fy">0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nb=
sp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbs=
p; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">local</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> move</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">global</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cat=
ch</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">){}</span></div></code><=
/div>Depending on condition int can be destructed in destructor of "temp" o=
r "local". In both of them <code class=3D"prettyprint"><span style=3D"color=
: #000;" class=3D"styled-by-prettify">exception_serial_number</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"></span></code> is same, but in o=
ne case it is not failure (in "temp" destructor), but in other it is (in "l=
ocal" destructor).<br><br>I think that any kind of solution based on compar=
ison of two exceptions states is not reliable for 100%, by design.<br>C++
 has heap objects, such objects can "fly" to any place with every=20
possible exception state since it's creation, it can be destructed in=20
context of any other destructor.<br>And whenever it is OK to throw from=20
destructor of heap object depends more on surrounding context, rather=20
than solely on exception state, because destruction may happen within=20
any other destructor, where it may be safe to throw, because that=20
destructor has opportunity to catch, or it may be not safe, because that
 destructor itself have thrown exception.<br></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_183_4500290.1381084153332--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Sun, 1 Jun 2014 10:22:06 -0700 (PDT)
Raw View
------=_Part_167_8763917.1401643326759
Content-Type: text/plain; charset=UTF-8

Having read the original thread, I'm slightly confused about why the
original idea was rejected?
You mentioned that a special "complete()" function would suffer from the
same problem as a destructor in that it would be unable to safely throw
exceptions, but I don't see why? The only potential problem I can see is if
a local "completable" object is constructed in a destructor. This would be
solved by wrapping it in a "try ... catch": fundamentally you are trying to
perform an operation which might throw an exception in an already
exceptional situation, so you would have to do that anyway.

I don't think it's possible to determine just from within the destructor
whether destruction is exceptional - it's a relation that's currently only
meaningful when the object is on the stack. For example, just compare
"unique_ptr" to "shared_ptr":
For "unique_ptr" it's clear that if ~unique_ptr() is called in an
exceptional way, then the heap allocated object should also be destructed
in an exceptional way.
For "shared_ptr", just because the last remaining reference was destructed
in an exceptional way does not mean the heap allocated object should be
also - doing that would result in completely different behaviours just
based on the ordering of two concurrent threads, and it's completely
impossible for the programmer to reason about.

(IMO, the best way to handle shared_ptr is for "default_deleter" to not be
implemented for completable objects: if the user really wants to use
shared_ptr with a completable object, then they would have to supply their
own deleter, and if that calls "complete" then it should handle any
exceptions that might be thrown)

Anyway, without cooperation from shared_ptr and unique_ptr, this shows that
it's completely impossible to determine the correct behaviour of the
destructor for a transaction object held by one of them.

I think this can be implemented with minimal changes to existing code, as
long as a trait "is_completable" or similar is introduced. "unique_ptr"
would be unchanged for normal classes, but if a class is completable, then
"unique_ptr" is also completable and simply forwards the call. If the
special member function "complete" is default-implemented, then that's a
special case which results in "is_completable" being false, and the
compiler being able to completely omit the call, so it has no performance
impact for objects which are not completable.


On Thursday, 12 September 2013 09:24:39 UTC+1, David Krauss wrote:
>
> This diverges from a current thread
> <https://groups.google.com/a/isocpp.org/forum/#%21topic/std-proposals/DZ7f9XLh3us>,
> which in turn proposes a variation on other
> <https://groups.google.com/a/isocpp.org/forum/?fromgroups#%21searchin/std-proposals/destructor/std-proposals/CYXxUYYT_tE/7kiYV4gEkGEJ>
> proposals <http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3614.pdf>.
>
> Much effort has focused on providing the interface for an object to
> discern whether it is being destroyed "normally" or "exceptionally." We
> already have such an interface as std::uncaught_exception since C++98,
> but its definition of "exceptional" was found to be defective
> <http://www.gotw.ca/gotw/047.htm>. In the other thread, I suggest that
> the calling context alone does not contain enough information to generally
> discern the destruction category (so any such definition will be
> defective). Now I'm not sure that context is relevant at all, but instead
> "normal" or "exceptional" is defined by a relationship between the object
> and the exception object. The solution may require few runtime library
> changes, but mainly an extension to std::exception.
>
> The only conceptual application seems to be transaction objects. Upon
> destruction, such an object ascertains success or failure. So far, there
> has not been a definition of success or failure, but the implicit consensus
> is that failure is identical to destruction of the transaction by stack
> unwinding. This breaks down, though, if the transaction is not scope-bound
> (i.e. of automatic storage duration). It may be a fallacy caused by the
> fact that stack unwinding is the last thing that happens to a transaction
> which is scope-bound.
>
> Suppose a transaction outlives its try block, and is destroyed in the
> catch block instead.
>
> std::optional< transaction > s;
> try {
>     s = transaction(); // Create transaction.
>     if ( condition1() ) {
>         throw 42;
>     }
> } catch ( ... ) {
>     s = std::nullopt; // Destroy transaction.
> }
> if ( condition2() ) {
>     s = std::nullopt; // Also destroy transaction.
> }
> // Natural end of transaction lifetime here.
>
> The transaction in the throw 42 case is not living its full, natural
> life. It died inside an exception handler. Although the handler could have
> performed cleanup prior to the explicit destruction, such that the
> operation could succeed, that is not the correct assumption for
> exception-handling code that doesn't somehow say commit(). Likewise, if
> there is an automatic commit and it throws, the original exception would be
> lost and replaced by one from the more specific context of the commit
> failure.
>
> The conditional destruction if ( condition2() ) is similar, but nothing
> contextually indicates failure, and there is no reason not to throw an
> exception. Such syntax looks ugly here, to be sure. But if you have some
> transaction objects and you indirectly incur their destruction, should they
> be reverted or committed? (This is the gist of the whole issue.) Reversion
> here means data loss. So, this destruction is more safely treated as
> success.
>
> I posit that a transaction should detect failure if its destruction was
> precipitated by an exception which is younger than it. When a program
> constructs an exception object (usually within a throw-expression), it must
> be preparing to handle some condition. (I mean any object of a type
> dedicated to exception handling, such as std::exception, not specifically
> the temporary in implementation-specific storage.) Any transaction
> constructed once the exception already exists cannot reasonably be looking
> for failure of a preexisting condition. (Maybe if it's trying to collect on
> a big insurance policy, but we should always make the strictly ethical
> choice in such a dilemma. </joke>) While the exception object is
> "activated" (between evaluation of throw and exit from the catch block),
> it is responsible for the flow of execution, and destruction of any
> preexisting transaction can be considered a consequence.
>
> The "younger than" relationship must be implemented somehow, and despite
> its temporal nature, accommodate multithreading. (I have no experience in
> multithreaded exception handling, and this is probably uncharted territory,
> so critiques are welcome.) Sentries and exceptions must initialize ticket
> objects, upon construction, and the tickets totally order the creation of
> the objects on a timeline. In a multithreading context, this requires
> locking.
>
> As for the interface, the ticket inside the exception object should
> probably be hidden. A library function can find the newest active exception
> and compare it to a given ticket, returning a Boolean value suitable for
> flow control.
>
> bool transaction_precedes_latest_exception( transaction_ticket );
>
> Perhaps a general function to compare any ticket to any exception would
> also be useful, but might place unreasonable demands on the implementation.
> Given the above semantics, you could *not* simply temporarily throw (or
> reactivate) the exception before querying the above function in a dedicated
> catch block, because the comparison is against the newest exception object,
> not the last one to be thrown.
>
> Exception types not derived from std::exception, or not containing a
> ticket or sequence information, would simply be transparent to the whole
> system.
>
> It would improve flexibility (and likely help performance) to provide one
> default, global ticket issuer, and allow the user to specify additional
> issuers, perhaps with custom implementation to avoid unnecessary
> synchronization. The application would thus be divided into exception
> domains, and the "latest exception" query would skip exceptions from
> domains different from the specified transaction. To achieve this, tickets
> and exceptions would need an optional issuer parameter, and of course a
> means of defining issuers would be needed.
>
> So far, it seems to me that the simplest implementation of tickets would
> be a linked list, but this results in the query being O(N) in the number of
> transactions initiated since to the last (activated) exception object.
>
> The good news? All this should be possible to prototype without any
> language support. The only special operation is getting the last thrown
> exception (or rather, notifying an exception that it is being thrown). But
> in most usage std::exception doesn't exist *except* as an exception
> object, or a temporary operand of a throw expression. A reasonable
> prototype can simply ignore the distinction and suppose that any exception
> is activated for its whole lifetime.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_167_8763917.1401643326759
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Having read the original thread, I'm slightly confused abo=
ut why the original idea was rejected?<br>You mentioned that a special "com=
plete()" function would suffer from the same problem as a destructor in tha=
t it would be unable to safely throw exceptions, but I don't see why? The o=
nly potential problem I can see is if a local "completable" object is const=
ructed in a destructor. This would be solved by wrapping it in a "try ... c=
atch": fundamentally you are trying to perform an operation which might thr=
ow an exception in an already exceptional situation, so you would have to d=
o that anyway.<br><br>I don't think it's possible to determine just from wi=
thin the destructor whether destruction is exceptional - it's a relation th=
at's currently only meaningful when the object is on the stack. For example=
, just compare "unique_ptr" to "shared_ptr":<br>For "unique_ptr" it's clear=
 that if ~unique_ptr() is called in an exceptional way, then the heap alloc=
ated object should also be destructed in an exceptional way.<br>For "shared=
_ptr", just because the last remaining reference was destructed in an excep=
tional way does not mean the heap allocated object should be also - doing t=
hat would result in completely different behaviours just based on the order=
ing of two concurrent threads, and it's completely impossible for the progr=
ammer to reason about.<br><br>(IMO, the best way to handle shared_ptr is fo=
r "default_deleter" to not be implemented for completable objects: if the u=
ser really wants to use shared_ptr with a completable object, then they wou=
ld have to supply their own deleter, and if that calls "complete" then it s=
hould handle any exceptions that might be thrown)<br><br>Anyway, without co=
operation from shared_ptr and unique_ptr, this shows that it's completely i=
mpossible to determine the correct behaviour of the destructor for a transa=
ction object held by one of them.<br><br>I think this can be implemented wi=
th minimal changes to existing code, as long as a trait "is_completable" or=
 similar is introduced. "unique_ptr" would be unchanged for normal classes,=
 but if a class is completable, then "unique_ptr" is also completable and s=
imply forwards the call. If the special member function "complete" is defau=
lt-implemented, then that's a special case which results in "is_completable=
" being false, and the compiler being able to completely omit the call, so =
it has no performance impact for objects which are not completable.<br><br>=
<br>On Thursday, 12 September 2013 09:24:39 UTC+1, David Krauss  wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">This diverges fro=
m <a href=3D"https://groups.google.com/a/isocpp.org/forum/#%21topic/std-pro=
posals/DZ7f9XLh3us" target=3D"_blank" onmousedown=3D"this.href=3D'https://g=
roups.google.com/a/isocpp.org/forum/#%21topic/std-proposals/DZ7f9XLh3us';re=
turn true;" onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.org/=
forum/#%21topic/std-proposals/DZ7f9XLh3us';return true;">a current thread</=
a>, which in turn proposes a variation on <a href=3D"https://groups.google.=
com/a/isocpp.org/forum/?fromgroups#%21searchin/std-proposals/destructor/std=
-proposals/CYXxUYYT_tE/7kiYV4gEkGEJ" target=3D"_blank" onmousedown=3D"this.=
href=3D'https://groups.google.com/a/isocpp.org/forum/?fromgroups#%21searchi=
n/std-proposals/destructor/std-proposals/CYXxUYYT_tE/7kiYV4gEkGEJ';return t=
rue;" onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.org/forum/=
?fromgroups#%21searchin/std-proposals/destructor/std-proposals/CYXxUYYT_tE/=
7kiYV4gEkGEJ';return true;">other</a> <a href=3D"http://open-std.org/JTC1/S=
C22/WG21/docs/papers/2013/n3614.pdf" target=3D"_blank" onmousedown=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fopen-std.org%2FJTC1%2FSC=
22%2FWG21%2Fdocs%2Fpapers%2F2013%2Fn3614.pdf\46sa\75D\46sntz\0751\46usg\75A=
FQjCNGmtPYiZeXczC0F27D131g7Fl-GRA';return true;" onclick=3D"this.href=3D'ht=
tp://www.google.com/url?q\75http%3A%2F%2Fopen-std.org%2FJTC1%2FSC22%2FWG21%=
2Fdocs%2Fpapers%2F2013%2Fn3614.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNGmtPY=
iZeXczC0F27D131g7Fl-GRA';return true;">proposals</a>.<br><br>Much effort ha=
s focused on providing the interface for an object to discern whether it is=
 being destroyed "normally" or "exceptionally." We already have such an int=
erface as <span style=3D"font-family:courier new,monospace">std::uncaught_e=
xception</span> since C++98, but its definition of "exceptional" was <a hre=
f=3D"http://www.gotw.ca/gotw/047.htm" target=3D"_blank" onmousedown=3D"this=
..href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.gotw.ca%2Fgotw%2F04=
7.htm\46sa\75D\46sntz\0751\46usg\75AFQjCNGt46BhCU0OJ-vl8oLnS_IHb_dNpA';retu=
rn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%=
2Fwww.gotw.ca%2Fgotw%2F047.htm\46sa\75D\46sntz\0751\46usg\75AFQjCNGt46BhCU0=
OJ-vl8oLnS_IHb_dNpA';return true;">found to be defective</a>. In the other =
thread, I suggest that the calling context alone does not contain enough in=
formation to generally discern the destruction category (so any such defini=
tion will be defective). Now I'm not sure that context is relevant at all, =
but instead "normal" or "exceptional" is defined by a relationship between =
the object and the exception object. The solution may require few runtime l=
ibrary changes, but mainly an extension to <span style=3D"font-family:couri=
er new,monospace">std::exception</span>.<br><br>The only conceptual applica=
tion seems to be transaction objects. Upon destruction, such an object asce=
rtains success or failure. So far, there has not been a definition of succe=
ss or failure, but the implicit consensus is that failure is identical to d=
estruction of the transaction by stack unwinding. This breaks down, though,=
 if the transaction is not scope-bound (i.e. of automatic storage duration)=
.. It may be a fallacy caused by the fact that stack unwinding is the last t=
hing that happens to a transaction which is scope-bound.<br><br>Suppose a t=
ransaction outlives its <span style=3D"font-family:courier new,monospace">t=
ry</span> block, and is destroyed in the <span style=3D"font-family:courier=
 new,monospace">catch</span> block instead.<br><br><div style=3D"background=
-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bo=
rder-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">op=
tional</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#00=
0"> transaction </span><span style=3D"color:#660">&gt;</span><span style=3D=
"color:#000"> s</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#008">try</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#0=
00"><br>&nbsp; &nbsp; s </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> transaction</span><span style=3D"color:#660">();</span=
><span style=3D"color:#000"> </span><span style=3D"color:#800">// Create tr=
ansaction.</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span =
style=3D"color:#008">if</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000"> condition1</span><span=
 style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; &nbsp; &n=
bsp; </span><span style=3D"color:#008">throw</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#066">42</span><span style=3D"color:#660">;=
</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#660">}</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">catch</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000"> </span><span style=3D"color:#660">..=
..</span><span style=3D"color:#000"> </span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>&nbsp; &nbsp; s </span><span style=3D"color:#6=
60">=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">nullopt</span><span style=3D"color:=
#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:#800"=
>// Destroy transaction.</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">if</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">(</span><span style=3D"color:#000"> condition2</span><span =
style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; s </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><=
span style=3D"color:#660">::</span><span style=3D"color:#000">nullopt</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">// Also destroy transaction.</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#800">// Natural end of transaction=
 lifetime here.</span><span style=3D"color:#000"><br></span></div></code></=
div><br>The transaction in the <span style=3D"font-family:courier new,monos=
pace">throw 42</span> case is not living its full, natural life. It died in=
side an exception handler. Although the handler could have performed cleanu=
p prior to the explicit destruction, such that the operation could succeed,=
 that is not the correct assumption for exception-handling code that doesn'=
t somehow say <span style=3D"font-family:courier new,monospace">commit()</s=
pan>. Likewise, if there is an automatic commit and it throws, the original=
 exception would be lost and replaced by one from the more specific context=
 of the commit failure.<br><br>The conditional destruction <span style=3D"f=
ont-family:courier new,monospace">if ( condition2() )</span> is similar, bu=
t nothing contextually indicates failure, and there is no reason not to thr=
ow an exception. Such syntax looks ugly here, to be sure. But if you have s=
ome transaction objects and you indirectly incur their destruction, should =
they be reverted or committed? (This is the gist of the whole issue.) Rever=
sion here means data loss. So, this destruction is more safely treated as s=
uccess.<br><br>I posit that a transaction should detect failure if its dest=
ruction was precipitated by an exception which is younger than it. When a p=
rogram constructs an exception object (usually within a throw-expression), =
it must be preparing to handle some condition. (I mean any object of a type=
 dedicated to exception handling, such as <span style=3D"font-family:courie=
r new,monospace">
std::exception</span>, not specifically the temporary in=20
implementation-specific storage.) Any transaction constructed once the exce=
ption already exists cannot reasonably be looking for failure of a preexist=
ing condition. (Maybe if it's trying to collect on a big insurance policy, =
but we should always make the strictly ethical choice in such a dilemma. &l=
t;/joke&gt;) While the exception object is "activated" (between evaluation =
of <span style=3D"font-family:courier new,monospace">throw</span> and exit =
from the <span style=3D"font-family:courier new,monospace">catch</span> blo=
ck), it is responsible for the flow of execution, and destruction of any pr=
eexisting transaction can be considered a consequence.<br><br>The "younger =
than" relationship must be implemented somehow, and despite its temporal na=
ture, accommodate multithreading. (I have no experience in multithreaded ex=
ception handling, and this is probably uncharted territory, so critiques ar=
e welcome.) Sentries and exceptions must initialize ticket objects, upon co=
nstruction, and the tickets totally order the creation of the objects on a =
timeline. In a multithreading context, this requires locking.<br><br>As for=
 the interface, the ticket inside the exception object should probably be h=
idden. A library function can find the newest active exception and compare =
it to a given ticket, returning a Boolean value suitable for flow control.<=
br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187=
,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><=
div><span style=3D"color:#008">bool</span><span style=3D"color:#000"> trans=
action_precedes_latest_<wbr>exception</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#000"> transaction_ticket </span><span style=3D"co=
lor:#660">);</span><span style=3D"color:#000"><br></span></div></code></div=
><br>Perhaps a general function to compare any ticket to any exception woul=
d=20
also be useful, but might place unreasonable demands on the=20
implementation. Given the above semantics, you could <i>not</i> simply temp=
orarily throw (or reactivate) the exception before querying the above funct=
ion in a dedicated catch block, because the comparison is against the newes=
t exception object, not the last one to be thrown.<br><br>Exception types n=
ot derived from <span style=3D"font-family:courier new,monospace">std::exce=
ption</span>, or not containing a ticket or sequence information, would sim=
ply be transparent to the whole system.<br><br>It would improve flexibility=
 (and likely help performance) to provide=20
one default, global ticket issuer, and allow the user to specify=20
additional issuers, perhaps with custom implementation to avoid=20
unnecessary synchronization. The application would thus be divided into=20
exception domains, and the "latest exception" query would skip exceptions f=
rom domains different from the specified transaction. To achieve this, tick=
ets and exceptions would need an optional issuer parameter, and of course a=
 means of defining issuers would be needed.<br><br>So far, it seems to me t=
hat the simplest implementation of tickets would be a linked list, but this=
 results in the query being O(N) in the number of transactions initiated si=
nce to the last (activated) exception object.<br><br>The good news? All thi=
s should be possible to prototype without any language support. The only sp=
ecial operation is getting the last thrown exception (or rather, notifying =
an exception that it is being thrown). But in most usage <span style=3D"fon=
t-family:courier new,monospace">std::exception</span> doesn't exist <i><spa=
n style=3D"font-family:arial,sans-serif">except</span></i> as an exception =
object, or a temporary operand of a <span style=3D"font-family:courier new,=
monospace">throw</span> expression. A reasonable prototype can simply ignor=
e the distinction and suppose that any <span style=3D"font-family:courier n=
ew,monospace">exception</span> is activated for its whole lifetime.<br></di=
v></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_167_8763917.1401643326759--

.


Author: David Krauss <potswa@gmail.com>
Date: Mon, 2 Jun 2014 15:08:46 +0800
Raw View
--Apple-Mail=_D10CB7B6-F77E-4CE3-92DF-00C5AF421FD2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-06-02, at 1:22 AM, Diggory Blake <diggsey@googlemail.com> wrote:

> Having read the original thread, I'm slightly confused about why the orig=
inal idea was rejected?

Which idea? I recall that one of the referenced proposals offers a summary =
of the simpler alternatives, and presents a compromise.

I think my solution is more universal. It handles more cases, no compromise=
 necessary.

> You mentioned that a special "complete()" function would suffer from the =
same problem as a destructor in that it would be unable to safely throw exc=
eptions, but I don't see why?

I can't find what you're referring to. The word "complete" does not appear =
in the quoted message or anywhere else in the thread.

A complete() function which may be called during unwinding would not be all=
owed to throw exceptions. That's the only time exceptions are forbidden. Gi=
ving destructors the intelligence to commit transactions, instead of the us=
er calling complete(), is the central problem.

> The only potential problem I can see is if a local "completable" object i=
s constructed in a destructor. This would be solved by wrapping it in a "tr=
y ... catch": fundamentally you are trying to perform an operation which mi=
ght throw an exception in an already exceptional situation, so you would ha=
ve to do that anyway.

No, that's the problem that needs to be solved. Being called indirectly by =
an unwinding destructor is what causes uncaught_exception() to return incor=
rect results.

try {} catch(...) {} is a non-solution. In general, failure may entail clea=
nup. Programmers should not be encouraged to write this. Also, a program sh=
ould not attempt to start what it cannot finish. If proper cleanup must pot=
entially throw, then the program needs to know whether throwing is safe bef=
ore starting in the first place.

> I don't think it's possible to determine just from within the destructor =
whether destruction is exceptional - it's a relation that's currently only =
meaningful when the object is on the stack. For example, just compare "uniq=
ue_ptr" to "shared_ptr":
> For "unique_ptr" it's clear that if ~unique_ptr() is called in an excepti=
onal way, then the heap allocated object should also be destructed in an ex=
ceptional way.

Is it exceptional to go out of scope in the normal execution of a destructo=
r which is called by stack unwinding? Nope. What ~unique_ptr or any other d=
estructor needs is a more context-free sense of exceptional circumstances t=
han uncaught_exception provides.

> For "shared_ptr", just because the last remaining reference was destructe=
d in an exceptional way does not mean the heap allocated object should be a=
lso - doing that would result in completely different behaviours just based=
 on the ordering of two concurrent threads, and it's completely impossible =
for the programmer to reason about.

This is a straw-man argument. The existence of a non-example does not precl=
ude the existence of valid examples. Rather than substitute any abstract da=
ta type, you have to reason in terms of transactions. A transaction is esse=
ntially a promise that some data will either be committed or cleaned-up. Pe=
rhaps this will be done by one of several threads. Demanding that transacti=
ons live on the stack essentially limits the language to synchronous I/O.

Multithreading is addressed by my previous message in this thread. I've pro=
vided deeper examples elsewhere. Essentially, multithreaded exception handl=
ing requires a thread to specify which exceptions it has adopted, such that=
 transactions generated in handling those exceptions may be allowed to comp=
lete. On the other hand, transactions that depend on whatever failure the e=
xception represents, must fail.

> Anyway, without cooperation from shared_ptr and unique_ptr, this shows th=
at it's completely impossible to determine the correct behaviour of the des=
tructor for a transaction object held by one of them.

Exception-handling utilities should be part of <exception> in the language =
support library. They should be orthogonal to memory management.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_D10CB7B6-F77E-4CE3-92DF-00C5AF421FD2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;06&ndash;02, at 1:22 AM, Diggory Blake &lt;<a href=3D"mailto:diggsey@=
googlemail.com">diggsey@googlemail.com</a>&gt; wrote:</div><br class=3D"App=
le-interchange-newline"><blockquote type=3D"cite"><div dir=3D"ltr">Having r=
ead the original thread, I'm slightly confused about why the original idea =
was rejected?<br></div></blockquote><div><br></div><div>Which idea? I recal=
l that one of the referenced proposals offers a summary of the simpler alte=
rnatives, and presents a compromise.</div><div><br></div><div>I think my so=
lution is more universal. It handles more cases, no compromise necessary.</=
div><br><blockquote type=3D"cite"><div dir=3D"ltr">You mentioned that a spe=
cial "complete()" function would suffer from the same problem as a destruct=
or in that it would be unable to safely throw exceptions, but I don't see w=
hy? </div></blockquote><div><br></div><div>I can&rsquo;t find what you&rsqu=
o;re referring to. The word &ldquo;complete&rdquo; does not appear in the q=
uoted message or anywhere else in the thread.</div><div><br></div><div>A <f=
ont face=3D"Courier">complete()</font> function which may be called during =
unwinding would not be allowed to throw exceptions. That&rsquo;s the only t=
ime exceptions are forbidden. Giving destructors the intelligence to commit=
 transactions, instead of the user calling <font face=3D"Courier">complete(=
)</font>, is the central problem.</div><br><blockquote type=3D"cite"><div d=
ir=3D"ltr">The only potential problem I can see is if a local "completable"=
 object is constructed in a destructor. This would be solved by wrapping it=
 in a "try ... catch": fundamentally you are trying to perform an operation=
 which might throw an exception in an already exceptional situation, so you=
 would have to do that anyway.<br></div></blockquote><div><br></div><div>No=
, that&rsquo;s the problem that needs to be solved. Being called indirectly=
 by an unwinding destructor is what causes <font face=3D"Courier">uncaught_=
exception()</font> to return incorrect results.</div><div><br></div><div><f=
ont face=3D"Courier">try {} catch(...) {}</font> is a non-solution. In gene=
ral, failure may entail cleanup. Programmers should not be encouraged to wr=
ite this. Also, a program should not attempt to start what it cannot finish=
.. If proper cleanup must potentially throw, then the program needs to know =
whether throwing is safe before starting in the first place.</div><br><bloc=
kquote type=3D"cite"><div dir=3D"ltr">I don't think it's possible to determ=
ine just from within the destructor whether destruction is exceptional - it=
's a relation that's currently only meaningful when the object is on the st=
ack. For example, just compare "unique_ptr" to "shared_ptr":<br>For "unique=
_ptr" it's clear that if ~unique_ptr() is called in an exceptional way, the=
n the heap allocated object should also be destructed in an exceptional way=
..<br></div></blockquote><div><br></div><div>Is it exceptional to go out of =
scope in the normal execution of a destructor which is called by stack unwi=
nding? Nope. What ~unique_ptr or any other destructor needs is a more conte=
xt-free sense of exceptional circumstances than uncaught_exception provides=
..</div><br><blockquote type=3D"cite"><div dir=3D"ltr">For "shared_ptr", jus=
t because the last remaining reference was destructed in an exceptional way=
 does not mean the heap allocated object should be also - doing that would =
result in completely different behaviours just based on the ordering of two=
 concurrent threads, and it's completely impossible for the programmer to r=
eason about.<br></div></blockquote><div><br></div><div>This is a straw-man =
argument. The existence of a non-example does not preclude the existence of=
 valid examples. Rather than substitute any abstract data type, you have to=
 reason in terms of transactions. A transaction is essentially a promise th=
at some data will either be committed or cleaned-up. Perhaps this will be d=
one by one of several threads. Demanding that transactions live on the stac=
k essentially limits the language to synchronous I/O.</div><div><br></div><=
div>Multithreading is addressed by my previous message in this thread. I've=
 provided deeper examples elsewhere. Essentially, multithreaded exception h=
andling requires a thread to specify which exceptions it has adopted, such =
that transactions generated in handling those exceptions may be allowed to =
complete. On the other hand, transactions that depend on whatever failure t=
he exception represents, must fail.</div><div><br></div><blockquote type=3D=
"cite"><div dir=3D"ltr">Anyway, without cooperation from shared_ptr and uni=
que_ptr, this shows that it's completely impossible to determine the correc=
t behaviour of the destructor for a transaction object held by one of them.=
<br></div></blockquote><div><br></div><div>Exception-handling utilities sho=
uld be part of <font face=3D"Courier">&lt;exception&gt;</font> in the langu=
age support library. They should be orthogonal to memory management.</div><=
/div><br></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_D10CB7B6-F77E-4CE3-92DF-00C5AF421FD2--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Mon, 2 Jun 2014 06:08:45 -0700 (PDT)
Raw View
------=_Part_2182_27150742.1401714525625
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

In the examples below I'm assuming that "transaction" is equivalent to=20
"transaction_scope" from the database proposal, ie. it should attempt to=20
commit the transaction if it exits scope normally, and roll back the=20
transaction otherwise.

On Monday, 2 June 2014 08:08:58 UTC+1, David Krauss wrote:
>
>
> On 2014=E2=80=9306=E2=80=9302, at 1:22 AM, Diggory Blake <dig...@googlema=
il.com=20
> <javascript:>> wrote:
>
> Having read the original thread, I'm slightly confused about why the=20
> original idea was rejected?
>
>
> Which idea? I recall that one of the referenced proposals offers a summar=
y=20
> of the simpler alternatives, and presents a compromise.
>
> I think my solution is more universal. It handles more cases, no=20
> compromise necessary.
>

In the first post of the first thread you linked to:=20
https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9XLh=
3us

It is suggesting the use of a special complete function.


> You mentioned that a special "complete()" function would suffer from the=
=20
> same problem as a destructor in that it would be unable to safely throw=
=20
> exceptions, but I don't see why?=20
>
>
> I can=E2=80=99t find what you=E2=80=99re referring to. The word =E2=80=9C=
complete=E2=80=9D does not appear=20
> in the quoted message or anywhere else in the thread.
>
>
See above.

=20

> A complete() function which may be called during unwinding would not be=
=20
> allowed to throw exceptions. That=E2=80=99s the only time exceptions are =
forbidden.=20
> Giving destructors the intelligence to commit transactions, instead of th=
e=20
> user calling complete(), is the central problem.=20
>

> The only potential problem I can see is if a local "completable" object i=
s=20
> constructed in a destructor. This would be solved by wrapping it in a "tr=
y=20
> ... catch": fundamentally you are trying to perform an operation which=20
> might throw an exception in an already exceptional situation, so you woul=
d=20
> have to do that anyway.
>
>
> No, that=E2=80=99s the problem that needs to be solved. Being called indi=
rectly by=20
> an unwinding destructor is what causes uncaught_exception() to return=20
> incorrect results.
>
> try {} catch(...) {} is a non-solution. In general, failure may entail=20
> cleanup. Programmers should not be encouraged to write this. Also, a=20
> program should not attempt to start what it cannot finish. If proper=20
> cleanup must potentially throw, then the program needs to know whether=20
> throwing is safe before starting in the first place.
>

They are different problems, see this example:

class C {
    ~C() {
        try {
            transaction o(<args>);
        } catch (...) {
            // Handle failure of transaction
        }
    }
};

void test() {
    C c;
    throw "Error";
}

If transaction uses 'uncaught_exception' to determine whether to commit or=
=20
roll-back the changes, the inner transaction will be rolled back, and=20
that's the problem that needs to be solved. If instead transaction is a=20
completable object, it will be completed (because it goes out of scope=20
normally, despite there being an exception in flight). In addition, it's=20
perfectly safe for the complete function to throw an exception, as long as=
=20
the try ... catch statement can handle it correctly.

Instead of having additional (and very complicated) runtime logic in the=20
destructor to determine if an exception should be thrown, and in the=20
process destroying the idea that destructors should not throw, classes=20
should put code that might throw in the complete function. Whether this=20
will be called is a compile-time decision with no extra overhead, and is=20
easy to reason about.
=20

>
> I don't think it's possible to determine just from within the destructor=
=20
> whether destruction is exceptional - it's a relation that's currently onl=
y=20
> meaningful when the object is on the stack. For example, just compare=20
> "unique_ptr" to "shared_ptr":
> For "unique_ptr" it's clear that if ~unique_ptr() is called in an=20
> exceptional way, then the heap allocated object should also be destructed=
=20
> in an exceptional way.
>
>
> Is it exceptional to go out of scope in the normal execution of a=20
> destructor which is called by stack unwinding? Nope. What ~unique_ptr or=
=20
> any other destructor needs is a more context-free sense of exceptional=20
> circumstances than uncaught_exception provides.
>

No, and if it goes out of scope during normal execution of a destructor=20
then the compiler will call the "complete" function, precisely because it=
=20
goes out of scope during normal execution. Whether the stack is unwinding=
=20
is irrelevant, the only thing that matters is if the current scope is being=
=20
left normally or exceptionally.

In this example, I believe that transaction1 should be committed (assuming=
=20
no other exceptions than those explicitly thrown) and transaction2 should=
=20
be rolled back, are you arguing otherwise?

void test() {
    {
        unique_ptr<transaction> transaction1 =3D make_unique<transaction>
(...);
    }
    {
        unique_ptr<transaction> transaction2 =3D make_unique<transaction>
(...);
        throw "Error";
    }
}
=20

>
> For "shared_ptr", just because the last remaining reference was destructe=
d=20
> in an exceptional way does not mean the heap allocated object should be=
=20
> also - doing that would result in completely different behaviours just=20
> based on the ordering of two concurrent threads, and it's completely=20
> impossible for the programmer to reason about.
>
>
> This is a straw-man argument. The existence of a non-example does not=20
> preclude the existence of valid examples. Rather than substitute any=20
> abstract data type, you have to reason in terms of transactions. A=20
> transaction is essentially a promise that some data will either be=20
> committed or cleaned-up. Perhaps this will be done by one of several=20
> threads. Demanding that transactions live on the stack essentially limits=
=20
> the language to synchronous I/O.
>
> Multithreading is addressed by my previous message in this thread. I've=
=20
> provided deeper examples elsewhere. Essentially, multithreaded exception=
=20
> handling requires a thread to specify which exceptions it has adopted, su=
ch=20
> that transactions generated in handling those exceptions may be allowed t=
o=20
> complete. On the other hand, transactions that depend on whatever failure=
=20
> the exception represents, must fail.
>
>
I'm not replacing transactions with shared_ptrs I'm talking about getting=
=20
correct behaviour when a transaction is not obviously owned by a single=20
thread, but is referenced by several shared_ptrs. Neither am I demanding=20
that transactions live on the stack, where did I say that? My example was=
=20
specifically about how to deal with them when they're not on the stack.=20
It's also not about multithreading exactly, it's about how to correctly=20
determine the relationship between exceptions and transactions, ie. which=
=20
exceptions should cause the transaction to fail.

Any logic you put in a potential replacement for "uncaught_exception" is=20
guaranteed to not be what many users want or expect. The only person who=20
can determine whether the transaction should complete or be rolled back is=
=20
the programmer in these cases, in my example this is done by them providing=
=20
their own deleter to shared_ptr, which can then freely choose to either=20
commit or rollback the transaction stored in the shared_ptr at the end of=
=20
its lifetime.

This is not a non-example, the logic for a unique_ptr<transaction> and that=
=20
for a shared_ptr<transaction> should be different: they are both perfectly=
=20
valid, with the former the transaction should behave exactly as if it was=
=20
created on the stack, and complete if it goes out of scope normally, but be=
=20
rolled back if it goes out of scope due to an exception, with the latter=20
the logic needs to be specified by the programmer (for example with a=20
custom deleter). How can your suggestion possibly handle both of these=20
cases?
=20

> Anyway, without cooperation from shared_ptr and unique_ptr, this shows=20
> that it's completely impossible to determine the correct behaviour of the=
=20
> destructor for a transaction object held by one of them.
>
>
> Exception-handling utilities should be part of <exception> in the=20
> language support library. They should be orthogonal to memory management.
>
>
Smart pointers are not just about memory management, they control the=20
lifetime of objects, and that is definitely not orthogonal to=20
exception-handling. Exceptions cause objects' lifetimes to end early, and=
=20
it's precisely this case that we're talking about.
=20

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_2182_27150742.1401714525625
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">In the examples below I'm assuming that "transaction" is e=
quivalent to "transaction_scope" from the database proposal, ie. it should =
attempt to commit the transaction if it exits scope normally, and roll back=
 the transaction otherwise.<br><br>On Monday, 2 June 2014 08:08:58 UTC+1, D=
avid Krauss  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=
=3D"word-wrap:break-word"><br><div><div>On 2014=E2=80=9306=E2=80=9302, at 1=
:22 AM, Diggory Blake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"vhixL9mca4kJ" onmousedown=3D"this.href=3D'javascript:';re=
turn true;" onclick=3D"this.href=3D'javascript:';return true;">dig...@googl=
email.com</a>&gt; wrote:</div><br><blockquote type=3D"cite"><div dir=3D"ltr=
">Having read the original thread, I'm slightly confused about why the orig=
inal idea was rejected?<br></div></blockquote><div><br></div><div>Which ide=
a? I recall that one of the referenced proposals offers a summary of the si=
mpler alternatives, and presents a compromise.</div><div><br></div><div>I t=
hink my solution is more universal. It handles more cases, no compromise ne=
cessary.</div></div></div></blockquote><div><br>In the first post of the fi=
rst thread you linked to: <a href=3D"https://groups.google.com/a/isocpp.org=
/forum/#!topic/std-proposals/DZ7f9XLh3us">https://groups.google.com/a/isocp=
p.org/forum/#!topic/std-proposals/DZ7f9XLh3us</a><br><br>It is suggesting t=
he use of a special complete function.<br><br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><br><blockqu=
ote type=3D"cite"><div dir=3D"ltr">You mentioned that a special "complete()=
" function would suffer from the same problem as a destructor in that it wo=
uld be unable to safely throw exceptions, but I don't see why? </div></bloc=
kquote><div><br></div><div>I can=E2=80=99t find what you=E2=80=99re referri=
ng to. The word =E2=80=9Ccomplete=E2=80=9D does not appear in the quoted me=
ssage or anywhere else in the thread.</div><div><br></div></div></div></blo=
ckquote><div><br>See above.<br><br>&nbsp;</div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div></div><div>A=
 <font face=3D"Courier">complete()</font> function which may be called duri=
ng unwinding would not be allowed to throw exceptions. That=E2=80=99s the o=
nly time exceptions are forbidden. Giving destructors the intelligence to c=
ommit transactions, instead of the user calling <font face=3D"Courier">comp=
lete()</font>, is the central problem. <br></div></div></div></blockquote><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-w=
ord"><div><br><blockquote type=3D"cite"><div dir=3D"ltr">The only potential=
 problem I can see is if a local "completable" object is constructed in a d=
estructor. This would be solved by wrapping it in a "try ... catch": fundam=
entally you are trying to perform an operation which might throw an excepti=
on in an already exceptional situation, so you would have to do that anyway=
..<br></div></blockquote><div><br></div><div>No, that=E2=80=99s the problem =
that needs to be solved. Being called indirectly by an unwinding destructor=
 is what causes <font face=3D"Courier">uncaught_exception()</font> to retur=
n incorrect results.</div><div><br></div><div><font face=3D"Courier">try {}=
 catch(...) {}</font> is a non-solution. In general, failure may entail cle=
anup. Programmers should not be encouraged to write this. Also, a program s=
hould not attempt to start what it cannot finish. If proper cleanup must po=
tentially throw, then the program needs to know whether throwing is safe be=
fore starting in the first place.</div></div></div></blockquote><div><br>Th=
ey are different problems, see this example:<br><br><div class=3D"prettypri=
nt" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 1=
87, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> C </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">~</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">C</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp;=
 &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">try</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &n=
bsp; &nbsp; &nbsp; &nbsp; transaction o</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(&lt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">args</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&gt;);</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">catch</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(...)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &=
nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">// Handle failure of transaction</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> test</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>&nbsp; &nbsp; C c</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">throw</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">"Err=
or"</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><=
br>If transaction uses 'uncaught_exception' to determine whether to commit =
or roll-back the changes, the inner transaction will be rolled back, and th=
at's the problem that needs to be solved. If instead transaction is a compl=
etable object, it will be completed (because it goes out of scope normally,=
 despite there being an exception in flight). In addition, it's perfectly s=
afe for the complete function to throw an exception, as long as the try ...=
 catch statement can handle it correctly.<br><br>Instead of having addition=
al (and very complicated) runtime logic in the destructor to determine if a=
n exception should be thrown, and in the process destroying the idea that d=
estructors should not throw, classes should put code that might throw in th=
e complete function. Whether this will be called is a compile-time decision=
 with no extra overhead, and is easy to reason about.<br>&nbsp;</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word">=
<div><br><blockquote type=3D"cite"><div dir=3D"ltr">I don't think it's poss=
ible to determine just from within the destructor whether destruction is ex=
ceptional - it's a relation that's currently only meaningful when the objec=
t is on the stack. For example, just compare "unique_ptr" to "shared_ptr":<=
br>For "unique_ptr" it's clear that if ~unique_ptr() is called in an except=
ional way, then the heap allocated object should also be destructed in an e=
xceptional way.<br></div></blockquote><div><br></div><div>Is it exceptional=
 to go out of scope in the normal execution of a destructor which is called=
 by stack unwinding? Nope. What ~unique_ptr or any other destructor needs i=
s a more context-free sense of exceptional circumstances than uncaught_exce=
ption provides.</div></div></div></blockquote><div><br>No, and if it goes o=
ut of scope during normal execution of a destructor then the compiler will =
call the "complete" function, precisely because it goes out of scope during=
 normal execution. Whether the stack is unwinding is irrelevant, the only t=
hing that matters is if the current scope is being left normally or excepti=
onally.<br><br>In this example, I believe that transaction1 should be commi=
tted (assuming no other exceptions than those explicitly thrown) and transa=
ction2 should be rolled back, are you arguing otherwise?<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> test</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; unique_ptr</span><span style=
=3D"color: #080;" class=3D"styled-by-prettify">&lt;transaction&gt;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> transaction1 </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> make_unique</span><sp=
an style=3D"color: #080;" class=3D"styled-by-prettify">&lt;transaction&gt;<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(...);</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbs=
p; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp=
; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp;=
 &nbsp; &nbsp; unique_ptr</span><span style=3D"color: #080;" class=3D"style=
d-by-prettify">&lt;transaction&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> transaction2 </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> make_unique</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify">&lt;transaction&gt;</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(...);</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">throw</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #080;" class=3D"styled-by-prettify">"Error"</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span></div></code></div>&nbsp;</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><br><blockqu=
ote type=3D"cite"><div dir=3D"ltr">For "shared_ptr", just because the last =
remaining reference was destructed in an exceptional way does not mean the =
heap allocated object should be also - doing that would result in completel=
y different behaviours just based on the ordering of two concurrent threads=
, and it's completely impossible for the programmer to reason about.<br></d=
iv></blockquote><div><br></div><div>This is a straw-man argument. The exist=
ence of a non-example does not preclude the existence of valid examples. Ra=
ther than substitute any abstract data type, you have to reason in terms of=
 transactions. A transaction is essentially a promise that some data will e=
ither be committed or cleaned-up. Perhaps this will be done by one of sever=
al threads. Demanding that transactions live on the stack essentially limit=
s the language to synchronous I/O.</div><div><br></div><div>Multithreading =
is addressed by my previous message in this thread. I've provided deeper ex=
amples elsewhere. Essentially, multithreaded exception handling requires a =
thread to specify which exceptions it has adopted, such that transactions g=
enerated in handling those exceptions may be allowed to complete. On the ot=
her hand, transactions that depend on whatever failure the exception repres=
ents, must fail.</div><div><br></div></div></div></blockquote><div><br>I'm =
not replacing transactions with shared_ptrs I'm talking about getting corre=
ct behaviour when a transaction is not obviously owned by a single thread, =
but is referenced by several shared_ptrs. Neither am I demanding that trans=
actions live on the stack, where did I say that? My example was specificall=
y about how to deal with them when they're not on the stack. It's also not =
about multithreading exactly, it's about how to correctly determine the rel=
ationship between exceptions and transactions, ie. which exceptions should =
cause the transaction to fail.<br><br>Any logic you put in a potential repl=
acement for "uncaught_exception" is guaranteed to not be what many users wa=
nt or expect. The only person who can determine whether the transaction sho=
uld complete or be rolled back is the programmer in these cases, in my exam=
ple this is done by them providing their own deleter to shared_ptr, which c=
an then freely choose to either commit or rollback the transaction stored i=
n the shared_ptr at the end of its lifetime.<br><br>This is not a non-examp=
le, the logic for a unique_ptr&lt;transaction&gt; and that for a shared_ptr=
&lt;transaction&gt; should be different: they are both perfectly valid, wit=
h the former the transaction should behave exactly as if it was created on =
the stack, and complete if it goes out of scope normally, but be rolled bac=
k if it goes out of scope due to an exception, with the latter the logic ne=
eds to be specified by the programmer (for example with a custom deleter). =
How can your suggestion possibly handle both of these cases?<br>&nbsp;</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break=
-word"><div><div></div><blockquote type=3D"cite"><div dir=3D"ltr">Anyway, w=
ithout cooperation from shared_ptr and unique_ptr, this shows that it's com=
pletely impossible to determine the correct behaviour of the destructor for=
 a transaction object held by one of them.<br></div></blockquote><div><br><=
/div><div>Exception-handling utilities should be part of <font face=3D"Cour=
ier">&lt;exception&gt;</font> in the language support library. They should =
be orthogonal to memory management.</div></div><br></div></blockquote><div>=
<br>Smart pointers are not just about memory management, they control the l=
ifetime of objects, and that is definitely not orthogonal to exception-hand=
ling. Exceptions cause objects' lifetimes to end early, and it's precisely =
this case that we're talking about.<br>&nbsp;<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2182_27150742.1401714525625--

.


Author: David Krauss <potswa@gmail.com>
Date: Tue, 3 Jun 2014 10:44:46 +0800
Raw View
--Apple-Mail=_8D219CDE-F474-4EA5-979E-7CB24B816489
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-06-02, at 9:08 PM, Diggory Blake <diggsey@googlemail.com> wrote:

> In the first post of the first thread you linked to: https://groups.googl=
e.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9XLh3us
>=20
> It is suggesting the use of a special complete function.

Well, in the second post of that thread I point out that the special comple=
te function is equivalent to the Boolean optional argument to the destructo=
r. So let us refer to that instead, since it has been formally proposed. (R=
edundancy with an existing proposal would be the reason for "rejecting" the=
 std-proposals post.)

Note that there's another thread and formal proposal linked from that messa=
ge. It's worth reading and reviewing.

> If transaction uses 'uncaught_exception' to determine whether to commit o=
r roll-back the changes, the inner transaction will be rolled back, and tha=
t's the problem that needs to be solved. If instead transaction is a comple=
table object, it will be completed (because it goes out of scope normally, =
despite there being an exception in flight). In addition, it's perfectly sa=
fe for the complete function to throw an exception, as long as the try ... =
catch statement can handle it correctly.

The question is how to implement "completable objects." Let us please not u=
se that terminology, though, since it already has two names.  The proposed =
version used a Boolean argument to the destructor, with true =3D> commitmen=
t and false =3D> rollback.

We can all agree that the programmer should easily be able to obtain two co=
de paths for these different cases. The question is how. With a Boolean pas=
sed to the destructor, it is responsible for passing that information to an=
y functions that might need it. With a commit() or complete() function, if =
it is called before the destructor, then it must leave the object in a stat=
e where rollback is a no-op, and the destructor still rolls back by default=
..

Making the information available only at the end-of-life of an object requi=
res that it be obtained specifically by a destructor, not by a deleter as y=
ou mention below, unless the Deleter concept is extended likewise with an o=
ptional parameter, and every path from a destructor to the deleter scrupulo=
usly maintains that flag.

And, what about nested destructor calls where the outer one is unwinding an=
d the inner one is going out of scope normally? The flag cannot be computed=
..

> This is not a non-example, the logic for a unique_ptr<transaction> and th=
at for a shared_ptr<transaction> should be different: they are both perfect=
ly valid, with the former the transaction should behave exactly as if it wa=
s created on the stack, and complete if it goes out of scope normally, but =
be rolled back if it goes out of scope due to an exception, with the latter=
 the logic needs to be specified by the programmer (for example with a cust=
om deleter). How can your suggestion possibly handle both of these cases?

How to write such a custom deleter? "Leave it to the programmer" is not a s=
olution; it's begging the question.

My suggestion is essentially to apply serial numbers to transactions and ex=
ceptions. At any point the program may ask whether a given transaction may =
be completed given the currently active (caught or uncaught) exceptions. Th=
is only requires comparing serial numbers: if the transaction is older than=
 the most recent exception, then it cannot currently be safely completed.

Serial numbers are complicated by multithreading, hence a small data struct=
ure may be required. I should review the details to be sure; I might not ha=
ve considered atomics as I should have.

Note that this may be done with a library, and doesn't require a core langu=
age change, except for the distinction between constructing an exception ob=
ject and actually throwing it.

>> Anyway, without cooperation from shared_ptr and unique_ptr, this shows t=
hat it's completely impossible to determine the correct behaviour of the de=
structor for a transaction object held by one of them.
>=20
> Exception-handling utilities should be part of <exception> in the languag=
e support library. They should be orthogonal to memory management.
>=20
> Smart pointers are not just about memory management, they control the lif=
etime of objects, and that is definitely not orthogonal to exception-handli=
ng. Exceptions cause objects' lifetimes to end early, and it's precisely th=
is case that we're talking about.

The lifetime of an object may be controlled without smart pointers. The poi=
nt is that smart pointers (and all memory management) should be user-implem=
entable and should not be compiler hooks.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_8D219CDE-F474-4EA5-979E-7CB24B816489
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;06&ndash;02, at 9:08 PM, Diggory Blake &lt;<a href=3D"mailto:diggsey@=
googlemail.com">diggsey@googlemail.com</a>&gt; wrote:</div><br class=3D"App=
le-interchange-newline"><blockquote type=3D"cite"><div style=3D"font-family=
: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fon=
t-weight: normal; letter-spacing: normal; line-height: normal; orphans: aut=
o; text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><=
div dir=3D"ltr"><div>In the first post of the first thread you linked to:<s=
pan class=3D"Apple-converted-space">&nbsp;</span><a href=3D"https://groups.=
google.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9XLh3us">https://gr=
oups.google.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9XLh3us</a><br=
><br>It is suggesting the use of a special complete function.<br></div></di=
v></div></blockquote><div><br></div><div>Well, in the second post of that t=
hread I point out that the special complete function is equivalent to the B=
oolean optional argument to the destructor. So let us refer to that instead=
, since it has been formally proposed. (Redundancy with an existing proposa=
l would be the reason for &ldquo;rejecting" the std-proposals post.)</div><=
div><br></div><div>Note that there&rsquo;s another thread and formal propos=
al linked from that message. It&rsquo;s worth reading and reviewing.</div><=
/div><div><br><blockquote type=3D"cite"><div style=3D"font-family: Helvetic=
a; font-size: 12px; font-style: normal; font-variant: normal; font-weight: =
normal; letter-spacing: normal; line-height: normal; orphans: auto; text-al=
ign: start; text-indent: 0px; text-transform: none; white-space: normal; wi=
dows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div dir=3D=
"ltr"><div>If transaction uses 'uncaught_exception' to determine whether to=
 commit or roll-back the changes, the inner transaction will be rolled back=
, and that's the problem that needs to be solved. If instead transaction is=
 a completable object, it will be completed (because it goes out of scope n=
ormally, despite there being an exception in flight). In addition, it's per=
fectly safe for the complete function to throw an exception, as long as the=
 try ... catch statement can handle it correctly.<br></div></div></div></bl=
ockquote><div><br></div><div>The question is how to implement &ldquo;comple=
table objects.&rdquo; Let us please not use that terminology, though, since=
 it already has two names. &nbsp;The proposed version used a Boolean argume=
nt to the destructor, with true =3D&gt; commitment and false =3D&gt; rollba=
ck.</div><div><br></div><div>We can all agree that the programmer should ea=
sily be able to obtain two code paths for these different cases. The questi=
on is how. With a Boolean passed to the destructor, it is responsible for p=
assing that information to any functions that might need it. With a commit(=
) or complete() function, if it is called before the destructor, then it mu=
st leave the object in a state where rollback is a no-op, and the destructo=
r still rolls back by default.</div><div><br></div><div>Making the informat=
ion available only at the end-of-life of an object requires that it be obta=
ined specifically by a destructor, not by a deleter as you mention below, u=
nless the Deleter concept is extended likewise with an optional parameter, =
and every path from a destructor to the deleter scrupulously maintains that=
 flag.</div><div><br></div><div>And, what about nested destructor calls whe=
re the outer one is unwinding and the inner one is going out of scope norma=
lly? The flag cannot be computed.</div><br><blockquote type=3D"cite"><div s=
tyle=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-v=
ariant: normal; font-weight: normal; letter-spacing: normal; line-height: n=
ormal; orphans: auto; text-align: start; text-indent: 0px; text-transform: =
none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-st=
roke-width: 0px;"><div dir=3D"ltr"><div>This is not a non-example, the logi=
c for a unique_ptr&lt;transaction&gt; and that for a shared_ptr&lt;transact=
ion&gt; should be different: they are both perfectly valid, with the former=
 the transaction should behave exactly as if it was created on the stack, a=
nd complete if it goes out of scope normally, but be rolled back if it goes=
 out of scope due to an exception, with the latter the logic needs to be sp=
ecified by the programmer (for example with a custom deleter). How can your=
 suggestion possibly handle both of these cases?</div></div></div></blockqu=
ote><div><br></div><div>How to write such a custom deleter? &ldquo;Leave it=
 to the programmer&rdquo; is not a solution; it&rsquo;s begging the questio=
n.</div><div><br></div><div>My suggestion is essentially to apply serial nu=
mbers to transactions and exceptions. At any point the program may ask whet=
her a given transaction may be completed given the currently active (caught=
 or uncaught) exceptions. This only requires comparing serial numbers: if t=
he transaction is older than the most recent exception, then it cannot curr=
ently be safely completed.</div><div><br></div><div>Serial numbers are comp=
licated by multithreading, hence a small data structure may be required. I =
should review the details to be sure; I might not have considered atomics a=
s I should have.</div><div><br></div><div>Note that this may be done with a=
 library, and doesn&rsquo;t require a core language change, except for the =
distinction between constructing an exception object and actually throwing =
it.</div><br><blockquote type=3D"cite"><div style=3D"font-family: Helvetica=
; font-size: 12px; font-style: normal; font-variant: normal; font-weight: n=
ormal; letter-spacing: normal; line-height: normal; orphans: auto; text-ali=
gn: start; text-indent: 0px; text-transform: none; white-space: normal; wid=
ows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div dir=3D"=
ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; =
border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-=
style: solid; padding-left: 1ex; position: static; z-index: auto;"><div sty=
le=3D"word-wrap: break-word;"><div><div></div><blockquote type=3D"cite"><di=
v dir=3D"ltr">Anyway, without cooperation from shared_ptr and unique_ptr, t=
his shows that it's completely impossible to determine the correct behaviou=
r of the destructor for a transaction object held by one of them.<br></div>=
</blockquote><div><br></div><div>Exception-handling utilities should be par=
t of<span class=3D"Apple-converted-space">&nbsp;</span><font face=3D"Courie=
r">&lt;exception&gt;</font><span class=3D"Apple-converted-space">&nbsp;</sp=
an>in the language support library. They should be orthogonal to memory man=
agement.</div></div></div></blockquote><div><br>Smart pointers are not just=
 about memory management, they control the lifetime of objects, and that is=
 definitely not orthogonal to exception-handling. Exceptions cause objects'=
 lifetimes to end early, and it's precisely this case that we're talking ab=
out.<br></div></div></div></blockquote><div><br></div><div>The lifetime of =
an object may be controlled without smart pointers. The point is that smart=
 pointers (and all memory management) should be user-implementable and shou=
ld not be compiler hooks.</div></div><br></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_8D219CDE-F474-4EA5-979E-7CB24B816489--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 10:59:15 -0700 (PDT)
Raw View
------=_Part_231_24003038.1401818356110
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable



On Tuesday, 3 June 2014 03:45:07 UTC+1, David Krauss wrote:
>
>
> On 2014=E2=80=9306=E2=80=9302, at 9:08 PM, Diggory Blake <dig...@googlema=
il.com=20
> <javascript:>> wrote:
>
> In the first post of the first thread you linked to:=20
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9X=
Lh3us
>
> It is suggesting the use of a special complete function.
>
>
> Well, in the second post of that thread I point out that the special=20
> complete function is equivalent to the Boolean optional argument to the=
=20
> destructor. So let us refer to that instead, since it has been formally=
=20
> proposed. (Redundancy with an existing proposal would be the reason for=
=20
> =E2=80=9Crejecting" the std-proposals post.)
>
> Note that there=E2=80=99s another thread and formal proposal linked from =
that=20
> message. It=E2=80=99s worth reading and reviewing.
>

I've seen that proposal, and while I think there are a number of advantages=
=20
of a complete function (is pre-destructor less ambiguous?) over a=20
destructor with a boolean argument, l'll write in terms of the latter.
=20

>
> If transaction uses 'uncaught_exception' to determine whether to commit o=
r=20
> roll-back the changes, the inner transaction will be rolled back, and=20
> that's the problem that needs to be solved. If instead transaction is a=
=20
> completable object, it will be completed (because it goes out of scope=20
> normally, despite there being an exception in flight). In addition, it's=
=20
> perfectly safe for the complete function to throw an exception, as long a=
s=20
> the try ... catch statement can handle it correctly.
>
>
> The question is how to implement =E2=80=9Ccompletable objects.=E2=80=9D L=
et us please not=20
> use that terminology, though, since it already has two names.  The propos=
ed=20
> version used a Boolean argument to the destructor, with true =3D> commitm=
ent=20
> and false =3D> rollback.
>
> We can all agree that the programmer should easily be able to obtain two=
=20
> code paths for these different cases. The question is how. With a Boolean=
=20
> passed to the destructor, it is responsible for passing that information =
to=20
> any functions that might need it. With a commit() or complete() function,=
=20
> if it is called before the destructor, then it must leave the object in a=
=20
> state where rollback is a no-op, and the destructor still rolls back by=
=20
> default.
>
> Making the information available only at the end-of-life of an object=20
> requires that it be obtained specifically by a destructor, not by a delet=
er=20
> as you mention below, unless the Deleter concept is extended likewise wit=
h=20
> an optional parameter, and every path from a destructor to the deleter=20
> scrupulously maintains that flag.
>

In my example, the deleter would be in charge of determining the value of=
=20
the flag to pass to the destructor. Deleters are used when the calling code=
=20
would otherwise not know how to destroy the object, that includes in some=
=20
cases (eg. shared_ptr) not knowing whether the destruction should commit or=
=20
rollback. I'm not sure what you mean by "every path from the destructor to=
=20
the deleter" - the deleter destructs the object, not the other way around.=
=20
If you mean when ~unique_ptr calls the deleter to delete its target, then=
=20
yes, it would pass the flag through.

default_deleter<T> would accept a boolean to its call operator iff ~T=20
accepts a boolean, ~unique_ptr<T> would also accept a boolean iff ~T=20
accepts a boolean and pass that through to the deleter, ~shared_ptr<T>=20
would not pass through a boolean, as it does not represent ownership: it=20
expects a deleter without a boolean parameter, and that deleter is in=20
charge of determining the value of the flag to pass to the object's=20
destructor.
=20

>
> And, what about nested destructor calls where the outer one is unwinding=
=20
> and the inner one is going out of scope normally? The flag cannot be=20
> computed.
>

Do you mean like this:

struct C {
    ~C(bool commit) {
        cout << (commit ? "COMMITTED" : "ROLLED BACK") << endl;
    }
};
struct D {
    ~D(bool commit) {
        C c;
    }
};

void test() {
    D d;
    throw "Error";
}

If you do then what's the problem? The program passes "false" to ~D()=20
because the scope of the variable 'd' was exited abnormally, but passes=20
"true" to ~C because the scope of 'c' is exited normally. This information=
=20
is known because exiting a scope abnormally is a different execution path:=
=20
the compiler generates a call to ~D(true) on the normal execution path and=
=20
to ~D(false) on any exceptional paths.

=20

>
> This is not a non-example, the logic for a unique_ptr<transaction> and=20
> that for a shared_ptr<transaction> should be different: they are both=20
> perfectly valid, with the former the transaction should behave exactly as=
=20
> if it was created on the stack, and complete if it goes out of scope=20
> normally, but be rolled back if it goes out of scope due to an exception,=
=20
> with the latter the logic needs to be specified by the programmer (for=20
> example with a custom deleter). How can your suggestion possibly handle=
=20
> both of these cases?
>
>
> How to write such a custom deleter? =E2=80=9CLeave it to the programmer=
=E2=80=9D is not a=20
> solution; it=E2=80=99s begging the question.
>

Easy - the programmer knows which operations are essential for the=20
transaction to be committed. For lack of a better example, let's say you=20
have several threads adding operations to a transaction (synchronised=20
properly of course). If any thread fails during this process, it sets a=20
flag which is accessible to the deleter (for example, just a field on the=
=20
deleter object). The deleter can then see that and pass the correct value=
=20
to the destructor of the transaction.
=20

>
> My suggestion is essentially to apply serial numbers to transactions and=
=20
> exceptions. At any point the program may ask whether a given transaction=
=20
> may be completed given the currently active (caught or uncaught)=20
> exceptions. This only requires comparing serial numbers: if the transacti=
on=20
> is older than the most recent exception, then it cannot currently be safe=
ly=20
> completed.
>
> Serial numbers are complicated by multithreading, hence a small data=20
> structure may be required. I should review the details to be sure; I migh=
t=20
> not have considered atomics as I should have.
>
> Note that this may be done with a library, and doesn=E2=80=99t require a =
core=20
> language change, except for the distinction between constructing an=20
> exception object and actually throwing it.
>

I'd hardly call that simple. It's also not true that whether a transaction=
=20
can be completed depends upon when it was constructed. The question is=20
"have their been any exceptions which caused the stack to unwind past the=
=20
owning scope of the transaction", and the problem is that sometimes there=
=20
is no definite "owner". For example:

1) You construct a transaction on thread A
2) Thread B throws an exception
3) While thread B's stack is unwinding, a destructor is executed
4) The destructor transfers ownership of the transaction from thread A (say=
=20
with move semantics of unique_ptr, so it's not even the case that=20
transaction's move constructor was called)
5) The destructor exits normally (and so the transaction it owns goes out=
=20
of scope normally)

The transaction SHOULD be committed, no exception was thrown during any=20
part of its operation, but according to your scheme of assigning sequence=
=20
numbers, the exception was thrown during the transaction's lifetime, and=20
was not caught by the time the destructor was called, and so the operation=
=20
will be rolled back.

I'll admit these are fairly exceptional circumstances (no pun intended) but=
=20
99% of the time this is going to be used for RAII with the objects existing=
=20
on the stack, so any multithreading example is going to be somewhat=20
exceptional. It's also the case that your suggestion is fairly expensive -=
=20
an additional sequence number for every object of this type and every=20
exception, plus the necessity to be thread-safe even if that's not actually=
=20
required.
=20

>
> Anyway, without cooperation from shared_ptr and unique_ptr, this shows=20
>> that it's completely impossible to determine the correct behaviour of th=
e=20
>> destructor for a transaction object held by one of them.
>>
>>
>> Exception-handling utilities should be part of <exception> in the=20
>> language support library. They should be orthogonal to memory management=
..
>>
>
> Smart pointers are not just about memory management, they control the=20
> lifetime of objects, and that is definitely not orthogonal to=20
> exception-handling. Exceptions cause objects' lifetimes to end early, and=
=20
> it's precisely this case that we're talking about.
>
>
> The lifetime of an object may be controlled without smart pointers. The=
=20
> point is that smart pointers (and all memory management) should be=20
> user-implementable and should not be compiler hooks.
>
>
Nothing I mentioned would require compiler hooks specifically for smart=20
pointers. The only changes to the language necessary are the extra=20
parameter to the destructor, and having the compiler automatically pass in=
=20
"true" for normal destruction and "false" for abnormal destruction.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_231_24003038.1401818356110
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 3 June 2014 03:45:07 UTC+1, David Krau=
ss  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-w=
rap:break-word"><br><div><div>On 2014=E2=80=9306=E2=80=9302, at 9:08 PM, Di=
ggory Blake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-ma=
ilto=3D"9W6VfH6qohEJ" onmousedown=3D"this.href=3D'javascript:';return true;=
" onclick=3D"this.href=3D'javascript:';return true;">dig...@googlemail.com<=
/a>&gt; wrote:</div><br><blockquote type=3D"cite"><div style=3D"font-family=
:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight=
:normal;letter-spacing:normal;line-height:normal;text-align:start;text-inde=
nt:0px;text-transform:none;white-space:normal;word-spacing:0px"><div dir=3D=
"ltr"><div>In the first post of the first thread you linked to:<span>&nbsp;=
</span><a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-=
proposals/DZ7f9XLh3us" target=3D"_blank" onmousedown=3D"this.href=3D'https:=
//groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/DZ7f9XLh3us';r=
eturn true;" onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.org=
/forum/#!topic/std-proposals/DZ7f9XLh3us';return true;">https://groups.goog=
le.com/<wbr>a/isocpp.org/forum/#!topic/<wbr>std-proposals/DZ7f9XLh3us</a><b=
r><br>It is suggesting the use of a special complete function.<br></div></d=
iv></div></blockquote><div><br></div><div>Well, in the second post of that =
thread I point out that the special complete function is equivalent to the =
Boolean optional argument to the destructor. So let us refer to that instea=
d, since it has been formally proposed. (Redundancy with an existing propos=
al would be the reason for =E2=80=9Crejecting" the std-proposals post.)</di=
v><div><br></div><div>Note that there=E2=80=99s another thread and formal p=
roposal linked from that message. It=E2=80=99s worth reading and reviewing.=
</div></div></div></blockquote><div><br>I've seen that proposal, and while =
I think there are a number of advantages of a complete function (is pre-des=
tructor less ambiguous?) over a destructor with a boolean argument, l'll wr=
ite in terms of the latter.<br>&nbsp;</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div style=3D"word-wrap:break-word"><div><br><blockquote type=
=3D"cite"><div style=3D"font-family:Helvetica;font-size:12px;font-style:nor=
mal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-heigh=
t:normal;text-align:start;text-indent:0px;text-transform:none;white-space:n=
ormal;word-spacing:0px"><div dir=3D"ltr"><div>If transaction uses 'uncaught=
_exception' to determine whether to commit or roll-back the changes, the in=
ner transaction will be rolled back, and that's the problem that needs to b=
e solved. If instead transaction is a completable object, it will be comple=
ted (because it goes out of scope normally, despite there being an exceptio=
n in flight). In addition, it's perfectly safe for the complete function to=
 throw an exception, as long as the try ... catch statement can handle it c=
orrectly.<br></div></div></div></blockquote><div><br></div><div>The questio=
n is how to implement =E2=80=9Ccompletable objects.=E2=80=9D Let us please =
not use that terminology, though, since it already has two names. &nbsp;The=
 proposed version used a Boolean argument to the destructor, with true =3D&=
gt; commitment and false =3D&gt; rollback.</div><div><br></div><div>We can =
all agree that the programmer should easily be able to obtain two code path=
s for these different cases. The question is how. With a Boolean passed to =
the destructor, it is responsible for passing that information to any funct=
ions that might need it. With a commit() or complete() function, if it is c=
alled before the destructor, then it must leave the object in a state where=
 rollback is a no-op, and the destructor still rolls back by default.</div>=
<div><br></div><div>Making the information available only at the end-of-lif=
e of an object requires that it be obtained specifically by a destructor, n=
ot by a deleter as you mention below, unless the Deleter concept is extende=
d likewise with an optional parameter, and every path from a destructor to =
the deleter scrupulously maintains that flag.</div></div></div></blockquote=
><div><br>In my example, the deleter would be in charge of determining the =
value of the flag to pass to the destructor. Deleters are used when the cal=
ling code would otherwise not know how to destroy the object, that includes=
 in some cases (eg. shared_ptr) not knowing whether the destruction should =
commit or rollback. I'm not sure what you mean by "every path from the dest=
ructor to the deleter" - the deleter destructs the object, not the other wa=
y around. If you mean when ~unique_ptr calls the deleter to delete its targ=
et, then yes, it would pass the flag through.<br><br>default_deleter&lt;T&g=
t; would accept a boolean to its call operator iff ~T accepts a boolean, ~u=
nique_ptr&lt;T&gt; would also accept a boolean iff ~T accepts a boolean and=
 pass that through to the deleter, ~shared_ptr&lt;T&gt; would not pass thro=
ugh a boolean, as it does not represent ownership: it expects a deleter wit=
hout a boolean parameter, and that deleter is in charge of determining the =
value of the flag to pass to the object's destructor.<br>&nbsp;</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word">=
<div><div><br></div><div>And, what about nested destructor calls where the =
outer one is unwinding and the inner one is going out of scope normally? Th=
e flag cannot be computed.</div></div></div></blockquote><div><br>Do you me=
an like this:<br><br><div class=3D"prettyprint" style=3D"background-color: =
rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; =
border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div=
 class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> C </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; =
&nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">~</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">C</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> commit</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; cout </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">commit </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">?</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">"CO=
MMITTED"</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #080;" class=3D"styled-by-prettify">"ROLLED BACK"</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> endl</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">struc=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> D </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">~</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">D</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> commit</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>&nbsp; &nbsp; &nbsp; &nbsp; C c</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">v=
oid</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> test</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; D d</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">throw</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
80;" class=3D"styled-by-prettify">"Error"</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>If you do then what's the proble=
m? The program passes "false" to ~D() because the scope of the variable 'd'=
 was exited abnormally, but passes "true" to ~C because the scope of 'c' is=
 exited normally. This information is known because exiting a scope abnorma=
lly is a different execution path: the compiler generates a call to ~D(true=
) on the normal execution path and to ~D(false) on any exceptional paths.<b=
r><br>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=
=3D"word-wrap:break-word"><div><br><blockquote type=3D"cite"><div style=3D"=
font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;=
font-weight:normal;letter-spacing:normal;line-height:normal;text-align:star=
t;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">=
<div dir=3D"ltr"><div>This is not a non-example, the logic for a unique_ptr=
&lt;transaction&gt; and that for a shared_ptr&lt;transaction&gt; should be =
different: they are both perfectly valid, with the former the transaction s=
hould behave exactly as if it was created on the stack, and complete if it =
goes out of scope normally, but be rolled back if it goes out of scope due =
to an exception, with the latter the logic needs to be specified by the pro=
grammer (for example with a custom deleter). How can your suggestion possib=
ly handle both of these cases?</div></div></div></blockquote><div><br></div=
><div>How to write such a custom deleter? =E2=80=9CLeave it to the programm=
er=E2=80=9D is not a solution; it=E2=80=99s begging the question.</div></di=
v></div></blockquote><div><br>Easy - the programmer knows which operations =
are essential for the transaction to be committed. For lack of a better exa=
mple, let's say you have several threads adding operations to a transaction=
 (synchronised properly of course). If any thread fails during this process=
, it sets a flag which is accessible to the deleter (for example, just a fi=
eld on the deleter object). The deleter can then see that and pass the corr=
ect value to the destructor of the transaction.<br>&nbsp;</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><=
div><br></div><div>My suggestion is essentially to apply serial numbers to =
transactions and exceptions. At any point the program may ask whether a giv=
en transaction may be completed given the currently active (caught or uncau=
ght) exceptions. This only requires comparing serial numbers: if the transa=
ction is older than the most recent exception, then it cannot currently be =
safely completed.</div><div><br></div><div>Serial numbers are complicated b=
y multithreading, hence a small data structure may be required. I should re=
view the details to be sure; I might not have considered atomics as I shoul=
d have.</div><div><br></div><div>Note that this may be done with a library,=
 and doesn=E2=80=99t require a core language change, except for the distinc=
tion between constructing an exception object and actually throwing it.</di=
v></div></div></blockquote><div><br>I'd hardly call that simple. It's also =
not true that whether a transaction can be completed depends upon when it w=
as constructed. The question is "have their been any exceptions which cause=
d the stack to unwind past the owning scope of the transaction", and the pr=
oblem is that sometimes there is no definite "owner". For example:<br><br>1=
) You construct a transaction on thread A<br>2) Thread B throws an exceptio=
n<br>3) While thread B's stack is unwinding, a destructor is executed<br>4)=
 The destructor transfers ownership of the transaction from thread A (say w=
ith move semantics of unique_ptr, so it's not even the case that transactio=
n's move constructor was called)<br>5) The destructor exits normally (and s=
o the transaction it owns goes out of scope normally)<br><br>The transactio=
n SHOULD be committed, no exception was thrown during any part of its opera=
tion, but according to your scheme of assigning sequence numbers, the excep=
tion was thrown during the transaction's lifetime, and was not caught by th=
e time the destructor was called, and so the operation will be rolled back.=
<br><br>I'll admit these are fairly exceptional circumstances (no pun inten=
ded) but 99% of the time this is going to be used for RAII with the objects=
 existing on the stack, so any multithreading example is going to be somewh=
at exceptional. It's also the case that your suggestion is fairly expensive=
 - an additional sequence number for every object of this type and every ex=
ception, plus the necessity to be thread-safe even if that's not actually r=
equired.<br>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div s=
tyle=3D"word-wrap:break-word"><div><br><blockquote type=3D"cite"><div style=
=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-variant:nor=
mal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:=
start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0=
px"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><=
div><div></div><blockquote type=3D"cite"><div dir=3D"ltr">Anyway, without c=
ooperation from shared_ptr and unique_ptr, this shows that it's completely =
impossible to determine the correct behaviour of the destructor for a trans=
action object held by one of them.<br></div></blockquote><div><br></div><di=
v>Exception-handling utilities should be part of<span>&nbsp;</span><font fa=
ce=3D"Courier">&lt;exception&gt;</font><span>&nbsp;</span>in the language s=
upport library. They should be orthogonal to memory management.</div></div>=
</div></blockquote><div><br>Smart pointers are not just about memory manage=
ment, they control the lifetime of objects, and that is definitely not orth=
ogonal to exception-handling. Exceptions cause objects' lifetimes to end ea=
rly, and it's precisely this case that we're talking about.<br></div></div>=
</div></blockquote><div><br></div><div>The lifetime of an object may be con=
trolled without smart pointers. The point is that smart pointers (and all m=
emory management) should be user-implementable and should not be compiler h=
ooks.</div></div><br></div></blockquote><div><br>Nothing I mentioned would =
require compiler hooks specifically for smart pointers. The only changes to=
 the language necessary are the extra parameter to the destructor, and havi=
ng the compiler automatically pass in "true" for normal destruction and "fa=
lse" for abnormal destruction.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_231_24003038.1401818356110--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 3 Jun 2014 21:27:55 +0300
Raw View
On 3 June 2014 20:59, Diggory Blake <diggsey@googlemail.com> wrote:
> Nothing I mentioned would require compiler hooks specifically for smart
> pointers. The only changes to the language necessary are the extra parameter
> to the destructor, and having the compiler automatically pass in "true" for
> normal destruction and "false" for abnormal destruction.


No, no, no and no. There's existing practice that allows getting an
integral exception
count, and that existing practice works with msvc and also gnu libsup++.
We do not need and I do not want multiple destructors. What we should
explore is ways to get a "ticket" (a hash or something like that) of
the exception
chain so that the cases where an integral count can be fooled are covered.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 11:55:14 -0700 (PDT)
Raw View
------=_Part_248_19544572.1401821714231
Content-Type: text/plain; charset=UTF-8

Which is one why I suggested the special "complete" function instead, it's
much less intrusive... The exception count doesn't work, a ticket doesn't
work either, the language simply doesn't give enough information for a
library only solution to work unless you require the programmer to
explicitly call commit before the transaction goes out of scope, which is
the case currently.

If a transaction is on the stack, then the compiler knows whether to commit
it or not.
If the transaction is not on the stack, then the compiler cannot possibly
know.

You can explore solutions with tickets all you want but the compiler can
never know in the second case - the correct behaviour in one case is
incorrect in another where the two cases are indistinguishable from the
compiler or library function's point of view, only the programmer can know
what their intentions are. The best you can do is have the compiler cover
the common case that it knows (transaction on the stack), have the library
cover the cases that it knows (unique_ptr<transaction>) and require that
the programmer specify their intent for the remaining cases for which there
is no "correct" solution.

On Tuesday, 3 June 2014 19:27:56 UTC+1, Ville Voutilainen wrote:
>
> On 3 June 2014 20:59, Diggory Blake <dig...@googlemail.com <javascript:>>
> wrote:
> > Nothing I mentioned would require compiler hooks specifically for smart
> > pointers. The only changes to the language necessary are the extra
> parameter
> > to the destructor, and having the compiler automatically pass in "true"
> for
> > normal destruction and "false" for abnormal destruction.
>
>
> No, no, no and no. There's existing practice that allows getting an
> integral exception
> count, and that existing practice works with msvc and also gnu libsup++.
> We do not need and I do not want multiple destructors. What we should
> explore is ways to get a "ticket" (a hash or something like that) of
> the exception
> chain so that the cases where an integral count can be fooled are covered.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_248_19544572.1401821714231
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Which is one why I suggested the special "complete" functi=
on instead, it's much less intrusive... The exception count doesn't work, a=
 ticket doesn't work either, the language simply doesn't give enough inform=
ation for a library only solution to work unless you require the programmer=
 to explicitly call commit before the transaction goes out of scope, which =
is the case currently.<br><br>If a transaction is on the stack, then the co=
mpiler knows whether to commit it or not.<br>If the transaction is not on t=
he stack, then the compiler cannot possibly know.<br><br>You can explore so=
lutions with tickets all you want but the compiler can never know in the se=
cond case - the correct behaviour in one case is incorrect in another where=
 the two cases are indistinguishable from the compiler or library function'=
s point of view, only the programmer can know what their intentions are. Th=
e best you can do is have the compiler cover the common case that it knows =
(transaction on the stack), have the library cover the cases that it knows =
(unique_ptr&lt;transaction&gt;) and require that the programmer specify the=
ir intent for the remaining cases for which there is no "correct" solution.=
<br><br>On Tuesday, 3 June 2014 19:27:56 UTC+1, Ville Voutilainen  wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">On 3 June 2014 20:59, Diggory Bl=
ake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
KFGhaGt373YJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">dig...@googlemail.com</a>&gt; =
wrote:
<br>&gt; Nothing I mentioned would require compiler hooks specifically for =
smart
<br>&gt; pointers. The only changes to the language necessary are the extra=
 parameter
<br>&gt; to the destructor, and having the compiler automatically pass in "=
true" for
<br>&gt; normal destruction and "false" for abnormal destruction.
<br>
<br>
<br>No, no, no and no. There's existing practice that allows getting an
<br>integral exception
<br>count, and that existing practice works with msvc and also gnu libsup++=
..
<br>We do not need and I do not want multiple destructors. What we should
<br>explore is ways to get a "ticket" (a hash or something like that) of
<br>the exception
<br>chain so that the cases where an integral count can be fooled are cover=
ed.
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_248_19544572.1401821714231--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 3 Jun 2014 22:19:56 +0300
Raw View
On 3 June 2014 21:55, Diggory Blake <diggsey@googlemail.com> wrote:
> Which is one why I suggested the special "complete" function instead, it's
> much less intrusive... The exception count doesn't work, a ticket doesn't

A count doesn't work?

> work either, the language simply doesn't give enough information for a

Why doesn't a ticket work?

> library only solution to work unless you require the programmer to

We're not talking about a "library-only" solution but a function that we would
add to the language support part of the library.

> If a transaction is on the stack, then the compiler knows whether to commit
> it or not.
> If the transaction is not on the stack, then the compiler cannot possibly
> know.

The compiler doesn't need to know anything about your transaction types,
since you can decide yourself whether to commit or not, based on the
information the support library function gives you.

> You can explore solutions with tickets all you want but the compiler can
> never know in the second case - the correct behaviour in one case is
> incorrect in another where the two cases are indistinguishable from the
> compiler or library function's point of view, only the programmer can know
> what their intentions are. The best you can do is have the compiler cover

Good, that's why it's the programmer's decision.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 12:59:08 -0700 (PDT)
Raw View
------=_Part_1242_28191044.1401825548953
Content-Type: text/plain; charset=UTF-8



On Tuesday, 3 June 2014 20:19:57 UTC+1, Ville Voutilainen wrote:
>
> On 3 June 2014 21:55, Diggory Blake <dig...@googlemail.com <javascript:>>
> wrote:
> > Which is one why I suggested the special "complete" function instead,
> it's
> > much less intrusive... The exception count doesn't work, a ticket
> doesn't
>
> A count doesn't work?
>

Even within a single thread, object lifetimes can overlap rather than be
nested. Let's say you record the exception count, A at construction, and
exception count B at destruction. You're saying that "A < B" implies that
the transaction should be rolled back. That's not always the case:

class A {
    unique_ptr<transaction> ptr1;
    A() {
        ptr1 = make_unique<transaction>( ... );
    }
    ~A() {
        unique_ptr<transaction> ptr2 = std::move(ptr1);
    }
};

void test() {
    A a;
    throw "Error!";
}

In this example, A < B, but the transaction is owned by "ptr2", not "ptr1"
at the time of destruction, and "ptr2" leaves scope normally.

With that line in place, the transaction should be committed. Without that
line in place the transaction should be rolled back. How can any
library-only solution tell the difference?



>
> > work either, the language simply doesn't give enough information for a
>
> Why doesn't a ticket work?
>

No library only solution can work, see above.


>
> > library only solution to work unless you require the programmer to
>
> We're not talking about a "library-only" solution but a function that we
> would
> add to the language support part of the library.
>

By "library-only" I mean one that doesn't require changes to the language,
ie. the changes are to the "library-only".


>
> > If a transaction is on the stack, then the compiler knows whether to
> commit
> > it or not.
> > If the transaction is not on the stack, then the compiler cannot
> possibly
> > know.
>
> The compiler doesn't need to know anything about your transaction types,
> since you can decide yourself whether to commit or not, based on the
> information the support library function gives you.
>

I think we all agree on that, the disagreement is how to find out and
supply that information.


>
> > You can explore solutions with tickets all you want but the compiler can
> > never know in the second case - the correct behaviour in one case is
> > incorrect in another where the two cases are indistinguishable from the
> > compiler or library function's point of view, only the programmer can
> know
> > what their intentions are. The best you can do is have the compiler
> cover
>
> Good, that's why it's the programmer's decision.
>

Well, the current situation is that the programmer would have to call
"commit" explicitly before a transaction is destructed, so it's already the
programmer's decision. The aim is to avoid the programmer having to do that
in the cases where the desired effect is unambiguous. By making the
transaction call a library function to determine whether to commit or not
takes that decision away from the programmer, even in the ambiguous cases,
and that's worse than just making the programmer be explicit all the time.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1242_28191044.1401825548953
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 3 June 2014 20:19:57 UTC+1, Ville Vout=
ilainen  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 3 June 2014 =
21:55, Diggory Blake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"e72f6G8MoDIJ" onmousedown=3D"this.href=3D'javascript:';ret=
urn true;" onclick=3D"this.href=3D'javascript:';return true;">dig...@google=
mail.com</a>&gt; wrote:
<br>&gt; Which is one why I suggested the special "complete" function inste=
ad, it's
<br>&gt; much less intrusive... The exception count doesn't work, a ticket =
doesn't
<br>
<br>A count doesn't work?
<br></blockquote><div><br>Even within a single thread, object lifetimes can=
 overlap rather than be nested. Let's say you record the exception count, A=
 at construction, and exception count B at destruction. You're saying that =
"A &lt; B" implies that the transaction should be rolled back. That's not a=
lways the case:<br><br><div class=3D"prettyprint" style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> A </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp;=
 &nbsp; unique_ptr</span><span style=3D"color: #080;" class=3D"styled-by-pr=
ettify">&lt;transaction&gt;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> ptr1</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>&nbsp; &nbsp; A</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nb=
sp; &nbsp; &nbsp; ptr1 </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> make_unique</span><span style=3D"color: #080;" class=3D"styled-by-pr=
ettify">&lt;transaction&gt;</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">.=
...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">~</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">A</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; unique_ptr</span><span style=
=3D"color: #080;" class=3D"styled-by-prettify">&lt;transaction&gt;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> ptr2 </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">move</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">ptr1</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> test</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>&nbsp; &nbsp; A a</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">throw</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=3D=
"styled-by-prettify">"Error!"</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span></div></code></div><br>In this example, A &lt; B, but the transaction=
 is owned by "ptr2", not "ptr1" at the time of destruction, and "ptr2" leav=
es scope normally.<br><br>With that line in place, the transaction should b=
e committed. Without that line in place the transaction should be rolled ba=
ck. How can any library-only solution tell the difference?<br><br>&nbsp;</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt; work either, the language simply doesn't give enough information f=
or a
<br>
<br>Why doesn't a ticket work?
<br></blockquote><div><br>No library only solution can work, see above.<br>=
&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt; library only solution to work unless you require the programmer to
<br>
<br>We're not talking about a "library-only" solution but a function that w=
e would
<br>add to the language support part of the library.
<br></blockquote><div><br>By "library-only" I mean one that doesn't require=
 changes to the language, ie. the changes are to the "library-only".<br>&nb=
sp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt; If a transaction is on the stack, then the compiler knows whether =
to commit
<br>&gt; it or not.
<br>&gt; If the transaction is not on the stack, then the compiler cannot p=
ossibly
<br>&gt; know.
<br>
<br>The compiler doesn't need to know anything about your transaction types=
,
<br>since you can decide yourself whether to commit or not, based on the
<br>information the support library function gives you.
<br></blockquote><div><br>I think we all agree on that, the disagreement is=
 how to find out and supply that information.<br>&nbsp;</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">
<br>&gt; You can explore solutions with tickets all you want but the compil=
er can
<br>&gt; never know in the second case - the correct behaviour in one case =
is
<br>&gt; incorrect in another where the two cases are indistinguishable fro=
m the
<br>&gt; compiler or library function's point of view, only the programmer =
can know
<br>&gt; what their intentions are. The best you can do is have the compile=
r cover
<br>
<br>Good, that's why it's the programmer's decision.
<br></blockquote><div><br>Well, the current situation is that the programme=
r would have to call "commit" explicitly before a transaction is destructed=
, so it's already the programmer's decision. The aim is to avoid the progra=
mmer having to do that in the cases where the desired effect is unambiguous=
.. By making the transaction call a library function to determine whether to=
 commit or not takes that decision away from the programmer, even in the am=
biguous cases, and that's worse than just making the programmer be explicit=
 all the time.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1242_28191044.1401825548953--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 3 Jun 2014 23:58:25 +0300
Raw View
On 3 June 2014 22:59, Diggory Blake <diggsey@googlemail.com> wrote:
>> A count doesn't work?
> Even within a single thread, object lifetimes can overlap rather than be
> nested. Let's say you record the exception count, A at construction, and
> exception count B at destruction. You're saying that "A < B" implies that
> the transaction should be rolled back. That's not always the case:
>
> class A {
>     unique_ptr<transaction> ptr1;
>     A() {
>         ptr1 = make_unique<transaction>( ... );
>     }
>     ~A() {
>         unique_ptr<transaction> ptr2 = std::move(ptr1);
>     }
> };
>
> void test() {
>     A a;
>     throw "Error!";
> }
>
> In this example, A < B, but the transaction is owned by "ptr2", not "ptr1"
> at the time of destruction, and "ptr2" leaves scope normally.
> With that line in place, the transaction should be committed. Without that
> line in place the transaction should be rolled back. How can any
> library-only solution tell the difference?

Yes, such examples have been suggested as cases that allegedly break
the use of a count. People posting such examples have said that their
examples are contrived. So, here's a question: if you _move_ an element
of a transaction to a different transaction context, why aren't you resetting
the transaction context of that element?

In other words, one way to solve these alleged problems is to state that
the facility doesn't even try to magick a solution for them, and solving such
cases is the responsibility of the programmer. When you do the move,
reset the exception count into your object, and we are back in a situation
where we detect a mismatch of the exception state between the destructor
and something-before-that.

>> > work either, the language simply doesn't give enough information for a
>> Why doesn't a ticket work?
> No library only solution can work, see above.

The above does not demonstrate how "no library only solution can work".
Nor does it demonstrate how a language solution helps with any of these
problems.

>> The compiler doesn't need to know anything about your transaction types,
>> since you can decide yourself whether to commit or not, based on the
>> information the support library function gives you.
> I think we all agree on that, the disagreement is how to find out and supply
> that information.

Well, feel free to rule out a solution where there are multiple destructors.
If that's what we end up having as a proposal, I'll kill this
facility, and we'll
live what we currently have. Having a single destructor is fundamental.

>> > You can explore solutions with tickets all you want but the compiler can
>> > never know in the second case - the correct behaviour in one case is
>> > incorrect in another where the two cases are indistinguishable from the
>> > compiler or library function's point of view, only the programmer can
>> > know
>> > what their intentions are. The best you can do is have the compiler
>> > cover
>> Good, that's why it's the programmer's decision.
> Well, the current situation is that the programmer would have to call
> "commit" explicitly before a transaction is destructed, so it's already the
> programmer's decision. The aim is to avoid the programmer having to do that

The idea of a support library query function is that you can check whether
rollback conditions are met, and decide to rollback instead of committing. Or,
if you program your transaction types inversely, the other way around.

> in the cases where the desired effect is unambiguous. By making the
> transaction call a library function to determine whether to commit or not
> takes that decision away from the programmer, even in the ambiguous cases,
> and that's worse than just making the programmer be explicit all the time.

I think you may misunderstand the idea of what the purported library
function does.
It doesn't commit-or-not for you. It gives you contextual information about
what exceptions are in flight, and you can choose to compare that to any
stored information you have, and decide whether to commit or not. The
decision is the programmer's, and the programmer's alone. You can still
build your logic so that if you don't explicitly rollback, commit
happens automatically.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 14:27:08 -0700 (PDT)
Raw View
------=_Part_1905_6435983.1401830829021
Content-Type: text/plain; charset=UTF-8



On Tuesday, 3 June 2014 21:58:26 UTC+1, Ville Voutilainen wrote:
>
> On 3 June 2014 22:59, Diggory Blake <dig...@googlemail.com <javascript:>>
> wrote:
> >> A count doesn't work?
> > Even within a single thread, object lifetimes can overlap rather than be
> > nested. Let's say you record the exception count, A at construction, and
> > exception count B at destruction. You're saying that "A < B" implies
> that
> > the transaction should be rolled back. That's not always the case:
> >
> > class A {
> >     unique_ptr<transaction> ptr1;
> >     A() {
> >         ptr1 = make_unique<transaction>( ... );
> >     }
> >     ~A() {
> >         unique_ptr<transaction> ptr2 = std::move(ptr1);
> >     }
> > };
> >
> > void test() {
> >     A a;
> >     throw "Error!";
> > }
> >
> > In this example, A < B, but the transaction is owned by "ptr2", not
> "ptr1"
> > at the time of destruction, and "ptr2" leaves scope normally.
> > With that line in place, the transaction should be committed. Without
> that
> > line in place the transaction should be rolled back. How can any
> > library-only solution tell the difference?
>
> Yes, such examples have been suggested as cases that allegedly break
> the use of a count. People posting such examples have said that their
> examples are contrived. So, here's a question: if you _move_ an element
> of a transaction to a different transaction context, why aren't you
> resetting
> the transaction context of that element?
>

Well I'm not moving the transaction itself, I'm just moving ownership of
the same transaction from one scope to another. It seems counter-intuitive
that I'd then have to perform some action on the transaction itself, when I
haven't touched it. Remember, the transaction could be hidden several
layers deep as part of some other object which my unique_ptr happens to be
pointing too. I might not even have access to it! How am I supposed to know
to reset the transaction context, and if I did know how would I even do it?


>
> In other words, one way to solve these alleged problems is to state that
> the facility doesn't even try to magick a solution for them, and solving
> such
> cases is the responsibility of the programmer. When you do the move,
> reset the exception count into your object, and we are back in a situation
> where we detect a mismatch of the exception state between the destructor
> and something-before-that.
>

While that would work albeit with the caveats I mentioned above, it does
require that authors of those classes remember to provide a public reset
method.


>
> >> > work either, the language simply doesn't give enough information for
> a
> >> Why doesn't a ticket work?
> > No library only solution can work, see above.
>
> The above does not demonstrate how "no library only solution can work".
> Nor does it demonstrate how a language solution helps with any of these
> problems.
>

Well the solution I was arguing for solves all of the problems I've
mentioned, and so far the only criticism has been that it requires a change
to the language. If there's a better way to do it without changing the
language then great, but I don't think there is.


>
> >> The compiler doesn't need to know anything about your transaction
> types,
> >> since you can decide yourself whether to commit or not, based on the
> >> information the support library function gives you.
> > I think we all agree on that, the disagreement is how to find out and
> supply
> > that information.
>
> Well, feel free to rule out a solution where there are multiple
> destructors.
> If that's what we end up having as a proposal, I'll kill this
> facility, and we'll
> live what we currently have. Having a single destructor is fundamental.
>
> >> > You can explore solutions with tickets all you want but the compiler
> can
> >> > never know in the second case - the correct behaviour in one case is
> >> > incorrect in another where the two cases are indistinguishable from
> the
> >> > compiler or library function's point of view, only the programmer can
> >> > know
> >> > what their intentions are. The best you can do is have the compiler
> >> > cover
> >> Good, that's why it's the programmer's decision.
> > Well, the current situation is that the programmer would have to call
> > "commit" explicitly before a transaction is destructed, so it's already
> the
> > programmer's decision. The aim is to avoid the programmer having to do
> that
>
> The idea of a support library query function is that you can check whether
> rollback conditions are met, and decide to rollback instead of committing.
> Or,
> if you program your transaction types inversely, the other way around.
>
> in the cases where the desired effect is unambiguous. By making the
> > transaction call a library function to determine whether to commit or
> not
> > takes that decision away from the programmer, even in the ambiguous
> cases,
> > and that's worse than just making the programmer be explicit all the
> time.
>
> I think you may misunderstand the idea of what the purported library
> function does.
> It doesn't commit-or-not for you. It gives you contextual information
> about
> what exceptions are in flight, and you can choose to compare that to any
> stored information you have, and decide whether to commit or not. The
> decision is the programmer's, and the programmer's alone. You can still
> build your logic so that if you don't explicitly rollback, commit
> happens automatically.
>


I was talking about the person using the transaction object. They have no
control over whether the transaction gets committed or not, as the
transaction object will decide based on the results of the library
function. There should be a way for the programmer to override that in
cases where the library function gets it wrong.



--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1905_6435983.1401830829021
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 3 June 2014 21:58:26 UTC+1, Ville Vout=
ilainen  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 3 June 2014 =
22:59, Diggory Blake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"bteedmXS7wUJ" onmousedown=3D"this.href=3D'javascript:';ret=
urn true;" onclick=3D"this.href=3D'javascript:';return true;">dig...@google=
mail.com</a>&gt; wrote:
<br>&gt;&gt; A count doesn't work?
<br>&gt; Even within a single thread, object lifetimes can overlap rather t=
han be
<br>&gt; nested. Let's say you record the exception count, A at constructio=
n, and
<br>&gt; exception count B at destruction. You're saying that "A &lt; B" im=
plies that
<br>&gt; the transaction should be rolled back. That's not always the case:
<br>&gt;
<br>&gt; class A {
<br>&gt; &nbsp; &nbsp; unique_ptr&lt;transaction&gt; ptr1;
<br>&gt; &nbsp; &nbsp; A() {
<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp; ptr1 =3D make_unique&lt;transaction&gt=
;( ... );
<br>&gt; &nbsp; &nbsp; }
<br>&gt; &nbsp; &nbsp; ~A() {
<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp; unique_ptr&lt;transaction&gt; ptr2 =3D=
 std::move(ptr1);
<br>&gt; &nbsp; &nbsp; }
<br>&gt; };
<br>&gt;
<br>&gt; void test() {
<br>&gt; &nbsp; &nbsp; A a;
<br>&gt; &nbsp; &nbsp; throw "Error!";
<br>&gt; }
<br>&gt;
<br>&gt; In this example, A &lt; B, but the transaction is owned by "ptr2",=
 not "ptr1"
<br>&gt; at the time of destruction, and "ptr2" leaves scope normally.
<br>&gt; With that line in place, the transaction should be committed. With=
out that
<br>&gt; line in place the transaction should be rolled back. How can any
<br>&gt; library-only solution tell the difference?
<br>
<br>Yes, such examples have been suggested as cases that allegedly break
<br>the use of a count. People posting such examples have said that their
<br>examples are contrived. So, here's a question: if you _move_ an element
<br>of a transaction to a different transaction context, why aren't you res=
etting
<br>the transaction context of that element?
<br></blockquote><div><br>Well I'm not moving the transaction itself, I'm j=
ust moving ownership of the same transaction from one scope to another. It =
seems counter-intuitive that I'd then have to perform some action on the tr=
ansaction itself, when I haven't touched it. Remember, the transaction coul=
d be hidden several layers deep as part of some other object which my uniqu=
e_ptr happens to be pointing too. I might not even have access to it! How a=
m I supposed to know to reset the transaction context, and if I did know ho=
w would I even do it?<br>&nbsp;</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
 1ex;">
<br>In other words, one way to solve these alleged problems is to state tha=
t
<br>the facility doesn't even try to magick a solution for them, and solvin=
g such
<br>cases is the responsibility of the programmer. When you do the move,
<br>reset the exception count into your object, and we are back in a situat=
ion
<br>where we detect a mismatch of the exception state between the destructo=
r
<br>and something-before-that.
<br></blockquote><div><br>While that would work albeit with the caveats I m=
entioned above, it does require that authors of those classes remember to p=
rovide a public reset method.<br>&nbsp;</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;">
<br>&gt;&gt; &gt; work either, the language simply doesn't give enough info=
rmation for a
<br>&gt;&gt; Why doesn't a ticket work?
<br>&gt; No library only solution can work, see above.
<br>
<br>The above does not demonstrate how "no library only solution can work".
<br>Nor does it demonstrate how a language solution helps with any of these
<br>problems.
<br></blockquote><div><br>Well the solution I was arguing for solves all of=
 the problems I've mentioned, and so far the only criticism has been that i=
t requires a change to the language. If there's a better way to do it witho=
ut changing the language then great, but I don't think there is.<br>&nbsp;<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt;&gt; The compiler doesn't need to know anything about your transact=
ion types,
<br>&gt;&gt; since you can decide yourself whether to commit or not, based =
on the
<br>&gt;&gt; information the support library function gives you.
<br>&gt; I think we all agree on that, the disagreement is how to find out =
and supply
<br>&gt; that information.
<br>
<br>Well, feel free to rule out a solution where there are multiple destruc=
tors.
<br>If that's what we end up having as a proposal, I'll kill this
<br>facility, and we'll
<br>live what we currently have. Having a single destructor is fundamental.
<br>
<br>&gt;&gt; &gt; You can explore solutions with tickets all you want but t=
he compiler can
<br>&gt;&gt; &gt; never know in the second case - the correct behaviour in =
one case is
<br>&gt;&gt; &gt; incorrect in another where the two cases are indistinguis=
hable from the
<br>&gt;&gt; &gt; compiler or library function's point of view, only the pr=
ogrammer can
<br>&gt;&gt; &gt; know
<br>&gt;&gt; &gt; what their intentions are. The best you can do is have th=
e compiler
<br>&gt;&gt; &gt; cover
<br>&gt;&gt; Good, that's why it's the programmer's decision.
<br>&gt; Well, the current situation is that the programmer would have to c=
all
<br>&gt; "commit" explicitly before a transaction is destructed, so it's al=
ready the
<br>&gt; programmer's decision. The aim is to avoid the programmer having t=
o do that
<br>
<br>The idea of a support library query function is that you can check whet=
her
<br>rollback conditions are met, and decide to rollback instead of committi=
ng. Or,
<br>if you program your transaction types inversely, the other way around.
<br></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">&gt; in the c=
ases where the desired effect is unambiguous. By making the
<br>&gt; transaction call a library function to determine whether to commit=
 or not
<br>&gt; takes that decision away from the programmer, even in the ambiguou=
s cases,
<br>&gt; and that's worse than just making the programmer be explicit all t=
he time.
<br>
<br>I think you may misunderstand the idea of what the purported library
<br>function does.
<br>It doesn't commit-or-not for you. It gives you contextual information a=
bout
<br>what exceptions are in flight, and you can choose to compare that to an=
y
<br>stored information you have, and decide whether to commit or not. The
<br>decision is the programmer's, and the programmer's alone. You can still
<br>build your logic so that if you don't explicitly rollback, commit
<br>happens automatically.
<br></blockquote><div><br><div><br>I was talking about the person using the=
 transaction object. They have no control over whether the transaction gets=
 committed or not, as the transaction object will decide based on the resul=
ts of the library function. There should be a way for the programmer to ove=
rride that in cases where the library function gets it wrong.<br>&nbsp;</di=
v>&nbsp;
<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1905_6435983.1401830829021--

.


Author: inkwizytoryankes@gmail.com
Date: Tue, 3 Jun 2014 14:27:36 -0700 (PDT)
Raw View
------=_Part_217_13706095.1401830856273
Content-Type: text/plain; charset=UTF-8

What if that same data was send through helper function, not by new version
of destructor?
Something like that:
struct A
{
    ~A() { if(is_unwinding(this)) rollback(); else commit(); }
}



On Tuesday, June 3, 2014 10:58:26 PM UTC+2, Ville Voutilainen wrote:

> >> The compiler doesn't need to know anything about your transaction
> types,
> >> since you can decide yourself whether to commit or not, based on the
> >> information the support library function gives you.
> > I think we all agree on that, the disagreement is how to find out and
> supply
> > that information.
>
> Well, feel free to rule out a solution where there are multiple
> destructors.
> If that's what we end up having as a proposal, I'll kill this
> facility, and we'll
> live what we currently have. Having a single destructor is fundamental.
>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_217_13706095.1401830856273
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">What if that same data was send through helper function, n=
ot by new version of destructor?<br>Something like that:<br><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> A<br></span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">~</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">A</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">is_unwinding</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">))</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> rollback</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">else</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> commit</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span></div></code></div><br><br><br=
>On Tuesday, June 3, 2014 10:58:26 PM UTC+2, Ville Voutilainen wrote:<br><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">&gt;&gt; The compiler doesn't ne=
ed to know anything about your transaction types,
<br>&gt;&gt; since you can decide yourself whether to commit or not, based =
on the
<br>&gt;&gt; information the support library function gives you.
<br>&gt; I think we all agree on that, the disagreement is how to find out =
and supply
<br>&gt; that information.
<br>
<br>Well, feel free to rule out a solution where there are multiple destruc=
tors.
<br>If that's what we end up having as a proposal, I'll kill this
<br>facility, and we'll
<br>live what we currently have. Having a single destructor is fundamental.
<br>
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_217_13706095.1401830856273--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 00:34:04 +0300
Raw View
On 4 June 2014 00:27,  <inkwizytoryankes@gmail.com> wrote:
> What if that same data was send through helper function, not by new version
> of destructor?
> Something like that:
> struct A
> {
>     ~A() { if(is_unwinding(this)) rollback(); else commit(); }
> }


That is close to what I'm talking about. It's not quite so simple that
you can use a bool for it,
since that would cause rollbacks in places where they are not needed
or intended.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 14:39:32 -0700 (PDT)
Raw View
------=_Part_69_22536218.1401831572531
Content-Type: text/plain; charset=UTF-8



On Tuesday, 3 June 2014 22:27:36 UTC+1, inkwizyt...@gmail.com wrote:
>
> What if that same data was send through helper function, not by new
> version of destructor?
> Something like that:
> struct A
> {
>     ~A() { if(is_unwinding(this)) rollback(); else commit(); }
> }
>
>
>
 That would be very nice, although I think it's necessary for the compiler
to be able to see whether a class makes use of this feature without needing
to see the destructor definition, otherwise it would result in unnecessary
overhead for classes not using it. Maybe something like this:

struct A : std::unwind_detector { // Bad name I know
    ~A() { if (this->is_unwinding()) rollback(); else commit(); }
};

Then a trait "std::is_unwind_detector<T>" which is true if the class
inherits std::unwind_detector, or if "std::is_unwind_detector<T>"  is true
for any of its fields.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_69_22536218.1401831572531
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 3 June 2014 22:27:36 UTC+1, inkwizyt..=
..@gmail.com  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">What if that same data was send through helper function, not by new v=
ersion of destructor?<br>Something like that:<br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">st=
ruct</span><span style=3D"color:#000"> A<br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=
=3D"color:#660">~</span><span style=3D"color:#000">A</span><span style=3D"c=
olor:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">if</span><span style=3D"color:#660">(</span><span style=3D"color:#000">is=
_unwinding</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">this</span><span style=3D"color:#660">))</span><span style=3D"color:#00=
0"> rollback</span><span style=3D"color:#660">();</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">else</span><span style=3D"color:=
#000"> commit</span><span style=3D"color:#660">();</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br></span><span style=3D"color:#660">}</span><span style=3D"color:#000=
"><br></span></div></code></div><br><br></div></blockquote><div><br>&nbsp;T=
hat would be very nice, although I think it's necessary for the compiler to=
 be able to see whether a class makes use of this feature without needing t=
o see the destructor definition, otherwise it would result in unnecessary o=
verhead for classes not using it. Maybe something like this:<br><br><div cl=
ass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-c=
olor: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap=
: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> A </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">unwind_detector </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-b=
y-prettify">// Bad name I know</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">~</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">A</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">is_unwinding</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">())</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> rollback</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">else</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> commit</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span></div></code></div><br>Then a trait "std::is_u=
nwind_detector&lt;T&gt;" which is true if the class inherits std::unwind_de=
tector, or if "std::is_unwind_detector&lt;T&gt;"&nbsp; is true for any of i=
ts fields.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_69_22536218.1401831572531--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 00:39:48 +0300
Raw View
On 4 June 2014 00:27, Diggory Blake <diggsey@googlemail.com> wrote:
>> Yes, such examples have been suggested as cases that allegedly break
>> the use of a count. People posting such examples have said that their
>> examples are contrived. So, here's a question: if you _move_ an element
>> of a transaction to a different transaction context, why aren't you
>> resetting
>> the transaction context of that element?
> Well I'm not moving the transaction itself, I'm just moving ownership of the
> same transaction from one scope to another. It seems counter-intuitive that

That of course depends on what you consider the transaction to be. :)

>> In other words, one way to solve these alleged problems is to state that
>> the facility doesn't even try to magick a solution for them, and solving
>> such
>> cases is the responsibility of the programmer. When you do the move,
>> reset the exception count into your object, and we are back in a situation
>> where we detect a mismatch of the exception state between the destructor
>> and something-before-that.
> While that would work albeit with the caveats I mentioned above, it does
> require that authors of those classes remember to provide a public reset
> method.

Sure, it requires that.

>> The above does not demonstrate how "no library only solution can work".
>> Nor does it demonstrate how a language solution helps with any of these
>> problems.
> Well the solution I was arguing for solves all of the problems I've
> mentioned, and so far the only criticism has been that it requires a change
> to the language. If there's a better way to do it without changing the
> language then great, but I don't think there is.

What solution? A destructor with a flag? I wrote "Having a single
destructor is fundamental.",
see below:

>> Well, feel free to rule out a solution where there are multiple
>> destructors.
>> If that's what we end up having as a proposal, I'll kill this
>> facility, and we'll
>> live what we currently have. Having a single destructor is fundamental.

>> I think you may misunderstand the idea of what the purported library
>> function does.
>> It doesn't commit-or-not for you. It gives you contextual information
>> about
>> what exceptions are in flight, and you can choose to compare that to any
>> stored information you have, and decide whether to commit or not. The
>> decision is the programmer's, and the programmer's alone. You can still
>> build your logic so that if you don't explicitly rollback, commit
>> happens automatically.
> I was talking about the person using the transaction object. They have no
> control over whether the transaction gets committed or not, as the
> transaction object will decide based on the results of the library function.
> There should be a way for the programmer to override that in cases where the
> library function gets it wrong.


By all means, the programmer can explicitly tell the transaction type
what to do.
That of course requires a certain amount of class api design to be
able to do so,
but that is again under the control of the provider of these
"transactional" types.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 00:44:38 +0300
Raw View
On 4 June 2014 00:39, Diggory Blake <diggsey@googlemail.com> wrote:
>
>
> On Tuesday, 3 June 2014 22:27:36 UTC+1, inkwizyt...@gmail.com wrote:
>>
>> What if that same data was send through helper function, not by new
>> version of destructor?
>> Something like that:
>> struct A
>> {
>>     ~A() { if(is_unwinding(this)) rollback(); else commit(); }
>> }
>>
>>
>
>  That would be very nice, although I think it's necessary for the compiler
> to be able to see whether a class makes use of this feature without needing
> to see the destructor definition, otherwise it would result in unnecessary
> overhead for classes not using it. Maybe something like this:
>
> struct A : std::unwind_detector { // Bad name I know
>     ~A() { if (this->is_unwinding()) rollback(); else commit(); }
> };
>
> Then a trait "std::is_unwind_detector<T>" which is true if the class
> inherits std::unwind_detector, or if "std::is_unwind_detector<T>"  is true
> for any of its fields.


It would be interesting to know how you're going to implement these ideas.
Accessing a chain of current exceptions that are in-flight is already existing
practice; this idea is not.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 14:46:44 -0700 (PDT)
Raw View
------=_Part_290_3568173.1401832005441
Content-Type: text/plain; charset=UTF-8

You still haven't addressed the issue about when a transaction is buried
within another object, and it's that object whose ownership is being moved.

What solution? A destructor with a flag? I wrote "Having a single
> destructor is fundamental.",
> see below:
>
>
No, having a special "commit/pre-destructor" method, which the compiler
calls automatically just before the destructor if the object is stack
allocated and the object goes out of scope normally. In the case where the
object is heap allocated, then the method must be called explicitly.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_290_3568173.1401832005441
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">You still haven't addressed the issue about when a transac=
tion is buried within another object, and it's that object whose ownership =
is being moved.<br><br><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">What so=
lution? A destructor with a flag? I wrote "Having a single
<br>destructor is fundamental.",
<br>see below:
<br>
<br></blockquote><div>&nbsp;<br>No, having a special "commit/pre-destructor=
" method, which the compiler calls automatically just before the destructor=
 if the object is stack allocated and the object goes out of scope normally=
.. In the case where the object is heap allocated, then the method must be c=
alled explicitly.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_290_3568173.1401832005441--

.


Author: inkwizytoryankes@gmail.com
Date: Tue, 3 Jun 2014 15:06:32 -0700 (PDT)
Raw View
------=_Part_4035_23682472.1401833192974
Content-Type: text/plain; charset=UTF-8

This simples version without any "forwarding" require only 2 pointers in
exception handler. they will made range of memory that is now deleted by
this exception.
This function will loop through exception in current thread to test if
current object is in this range.  This will be O(n) but I doubt that will
have n > 20 in any normal application.
Destructor dont need know anything about this.

On Tuesday, June 3, 2014 11:44:39 PM UTC+2, Ville Voutilainen wrote:
>
> On 4 June 2014 00:39, Diggory Blake <dig...@googlemail.com <javascript:>>
> wrote:
> >
> >
> > On Tuesday, 3 June 2014 22:27:36 UTC+1, inkwizyt...@gmail.com wrote:
> >>
> >> What if that same data was send through helper function, not by new
> >> version of destructor?
> >> Something like that:
> >> struct A
> >> {
> >>     ~A() { if(is_unwinding(this)) rollback(); else commit(); }
> >> }
> >>
> >>
> >
> >  That would be very nice, although I think it's necessary for the
> compiler
> > to be able to see whether a class makes use of this feature without
> needing
> > to see the destructor definition, otherwise it would result in
> unnecessary
> > overhead for classes not using it. Maybe something like this:
> >
> > struct A : std::unwind_detector { // Bad name I know
> >     ~A() { if (this->is_unwinding()) rollback(); else commit(); }
> > };
> >
> > Then a trait "std::is_unwind_detector<T>" which is true if the class
> > inherits std::unwind_detector, or if "std::is_unwind_detector<T>"  is
> true
> > for any of its fields.
>
>
> It would be interesting to know how you're going to implement these ideas.
> Accessing a chain of current exceptions that are in-flight is already
> existing
> practice; this idea is not.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_4035_23682472.1401833192974
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">This simples version without any "forwarding" require only=
 2 pointers in exception handler. they will made range of memory that is no=
w deleted by this exception.<br>This function will loop through exception i=
n current thread to test if current object is in this range.&nbsp; This wil=
l be O(n) but I doubt that will have n &gt; 20 in any normal application.<b=
r>Destructor dont need know anything about this.<br><br>On Tuesday, June 3,=
 2014 11:44:39 PM UTC+2, Ville Voutilainen wrote:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;">On 4 June 2014 00:39, Diggory Blake &lt;<a href=3D"javas=
cript:" target=3D"_blank" gdf-obfuscated-mailto=3D"0LRjcCIEwhkJ" onmousedow=
n=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'javasc=
ript:';return true;">dig...@googlemail.com</a>&gt; wrote:
<br>&gt;
<br>&gt;
<br>&gt; On Tuesday, 3 June 2014 22:27:36 UTC+1, <a>inkwizyt...@gmail.com</=
a> wrote:
<br>&gt;&gt;
<br>&gt;&gt; What if that same data was send through helper function, not b=
y new
<br>&gt;&gt; version of destructor?
<br>&gt;&gt; Something like that:
<br>&gt;&gt; struct A
<br>&gt;&gt; {
<br>&gt;&gt; &nbsp; &nbsp; ~A() { if(is_unwinding(this)) rollback(); else c=
ommit(); }
<br>&gt;&gt; }
<br>&gt;&gt;
<br>&gt;&gt;
<br>&gt;
<br>&gt; &nbsp;That would be very nice, although I think it's necessary for=
 the compiler
<br>&gt; to be able to see whether a class makes use of this feature withou=
t needing
<br>&gt; to see the destructor definition, otherwise it would result in unn=
ecessary
<br>&gt; overhead for classes not using it. Maybe something like this:
<br>&gt;
<br>&gt; struct A : std::unwind_detector { // Bad name I know
<br>&gt; &nbsp; &nbsp; ~A() { if (this-&gt;is_unwinding()) rollback(); else=
 commit(); }
<br>&gt; };
<br>&gt;
<br>&gt; Then a trait "std::is_unwind_detector&lt;T&gt;" which is true if t=
he class
<br>&gt; inherits std::unwind_detector, or if "std::is_unwind_detector&lt;T=
&gt;" &nbsp;is true
<br>&gt; for any of its fields.
<br>
<br>
<br>It would be interesting to know how you're going to implement these ide=
as.
<br>Accessing a chain of current exceptions that are in-flight is already e=
xisting
<br>practice; this idea is not.
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_4035_23682472.1401833192974--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 01:19:29 +0300
Raw View
On 4 June 2014 00:46, Diggory Blake <diggsey@googlemail.com> wrote:
> You still haven't addressed the issue about when a transaction is buried
> within another object, and it's that object whose ownership is being moved.

Well, if you have to externally reset the "context", that resetting
needs to happen
through the full chain of objects. Yes, I know that would be
exceedingly tedious.
Allowing classes to query the context and check for changes is less tedious,
but it can be hard or impossible to know whether to rollback because the
query cannot necessarily give you enough information to know where you were
"moved" inside a wrapper, and whether the nesting level or a chain
being deeper/different
from the original one should mean a rollback or not. So I do see why you say
"it won't work". I'm thinking it doesn't have to work for all
concoctions, and we
could just admit there are some imperfections.

>> What solution? A destructor with a flag? I wrote "Having a single
>> destructor is fundamental.",
>> see below:
> No, having a special "commit/pre-destructor" method, which the compiler
> calls automatically just before the destructor if the object is stack
> allocated and the object goes out of scope normally. In the case where the
> object is heap allocated, then the method must be called explicitly.


Oh, ok. Is this function virtual? Is it always called for every
scope-local object?
I suppose a trait-like facility could be used to make that decision at
code-generation
time, sure. Alternatively, we could just as well put a keyword in the class-head
of such classes, and refuse the declarations of this special function if the
class doesn't have the right keyword.

The motivation of this facility surely isn't high enough to me that we should
impose a cost for cases that don't care about this facility.

About the keyword, something like this:

struct foo unwind_aware {
    /*virtual, if  you want */ void unwind_state(bool); // ok. But we
need to figure a better-obfuscated name..
};

struct bar  {
    void unwind_state(bool); // ill-formed, the class is not unwind_aware
};


And no, I don't think we should name those functions ~foo(bool) and ~bar(bool).

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 01:22:20 +0300
Raw View
On 4 June 2014 01:06,  <inkwizytoryankes@gmail.com> wrote:
> This simples version without any "forwarding" require only 2 pointers in
> exception handler. they will made range of memory that is now deleted by
> this exception.

Once you get to the handler, that memory is long gone, as far as I understand,
and the destructors of the objects that were destroyed have already run.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: inkwizytoryankes@gmail.com
Date: Tue, 3 Jun 2014 15:27:09 -0700 (PDT)
Raw View
------=_Part_707_25425890.1401834430431
Content-Type: text/plain; charset=UTF-8

Sorry, wrong word. As "exception handler" I mean struct that is handling
unwinding and storing current exception.
This pointers are set before destructor call.

On Wednesday, June 4, 2014 12:22:21 AM UTC+2, Ville Voutilainen wrote:
>
> On 4 June 2014 01:06,  <inkwizyt...@gmail.com <javascript:>> wrote:
> > This simples version without any "forwarding" require only 2 pointers in
> > exception handler. they will made range of memory that is now deleted by
> > this exception.
>
> Once you get to the handler, that memory is long gone, as far as I
> understand,
> and the destructors of the objects that were destroyed have already run.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_707_25425890.1401834430431
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Sorry, wrong word. As "exception handler" I mean struct th=
at is handling unwinding and storing current exception.<br>This pointers ar=
e set before destructor call.<br><br>On Wednesday, June 4, 2014 12:22:21 AM=
 UTC+2, Ville Voutilainen wrote:<blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
">On 4 June 2014 01:06, &nbsp;&lt;<a href=3D"javascript:" target=3D"_blank"=
 gdf-obfuscated-mailto=3D"djjI2wvPowsJ" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return true;">inkw=
izyt...@gmail.com</a>&gt; wrote:
<br>&gt; This simples version without any "forwarding" require only 2 point=
ers in
<br>&gt; exception handler. they will made range of memory that is now dele=
ted by
<br>&gt; this exception.
<br>
<br>Once you get to the handler, that memory is long gone, as far as I unde=
rstand,
<br>and the destructors of the objects that were destroyed have already run=
..
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_707_25425890.1401834430431--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 01:28:08 +0300
Raw View
On 4 June 2014 01:19, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> "it won't work". I'm thinking it doesn't have to work for all
> concoctions, and we
> could just admit there are some imperfections.

> Oh, ok. Is this function virtual? Is it always called for every
> scope-local object?
> I suppose a trait-like facility could be used to make that decision at
> code-generation
> time, sure. Alternatively, we could just as well put a keyword in the class-head
> of such classes, and refuse the declarations of this special function if the
> class doesn't have the right keyword.


I should mention that having all these concerns and figuring out a
solution for them makes me gravitate
towards even an imperfect support library solution, since it's FAR
less intrusive.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 01:35:17 +0300
Raw View
On 4 June 2014 01:27,  <inkwizytoryankes@gmail.com> wrote:
> Sorry, wrong word. As "exception handler" I mean struct that is handling
> unwinding and storing current exception.
> This pointers are set before destructor call.

Ok, and then classes that care about this information can query whether
'this' is in that range delimited by those pointers. This solution will not
work with objects that are allocated dynamically but are wrapped in a
scope-local
handle, so the handle will need to tell the dynamic object it's holding what
the unwind state is.

Regarding having to invoke such a special function dynamically, we would be
facing a need to change massive amounts of code so that various resource
handles will perform that dynamic invocation. That is more or less an impossible
change.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 15:39:36 -0700 (PDT)
Raw View
------=_Part_676_4177652.1401835176543
Content-Type: text/plain; charset=UTF-8

Whether it's virtual would be up to the class (similar to destructors -
virtual would be strongly recommended if your class it to be used as a base)

For stack variables, it's always called immediately before the destructor,
but only if the destructor is being executed normally - it's not a
guarantee to the transaction class that it will be called, it must be valid
to destruct the transaction object without calling this function.

I was assuming some sort of trait would exist to detect classes with this
special function, this would allow container classes and smart pointers to
forward on the call where needed, while not imposing an extra cost when not
needed, but the exact mechanics are not hugely important as long as
detection is possible at compile time.


On Tuesday, 3 June 2014 23:28:09 UTC+1, Ville Voutilainen wrote:
>
> On 4 June 2014 01:19, Ville Voutilainen <ville.vo...@gmail.com
> <javascript:>> wrote:
> > "it won't work". I'm thinking it doesn't have to work for all
> > concoctions, and we
> > could just admit there are some imperfections.
>
> > Oh, ok. Is this function virtual? Is it always called for every
> > scope-local object?
> > I suppose a trait-like facility could be used to make that decision at
> > code-generation
> > time, sure. Alternatively, we could just as well put a keyword in the
> class-head
> > of such classes, and refuse the declarations of this special function if
> the
> > class doesn't have the right keyword.
>
>
> I should mention that having all these concerns and figuring out a
> solution for them makes me gravitate
> towards even an imperfect support library solution, since it's FAR
> less intrusive.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_676_4177652.1401835176543
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Whether it's virtual would be up to the class (similar to =
destructors - virtual would be strongly recommended if your class it to be =
used as a base)<br><br>For stack variables, it's always called immediately =
before the destructor, but only if the destructor is being executed normall=
y - it's not a guarantee to the transaction class that it will be called, i=
t must be valid to destruct the transaction object without calling this fun=
ction.<br><br>I was assuming some sort of trait would exist to detect class=
es with this special function, this would allow container classes and smart=
 pointers to forward on the call where needed, while not imposing an extra =
cost when not needed, but the exact mechanics are not hugely important as l=
ong as detection is possible at compile time.<br><br><br>On Tuesday, 3 June=
 2014 23:28:09 UTC+1, Ville Voutilainen  wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;">On 4 June 2014 01:19, Ville Voutilainen &lt;<a href=3D"jav=
ascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"_DP0f7NDM4sJ" onmoused=
own=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'java=
script:';return true;">ville.vo...@gmail.com</a>&gt; wrote:
<br>&gt; "it won't work". I'm thinking it doesn't have to work for all
<br>&gt; concoctions, and we
<br>&gt; could just admit there are some imperfections.
<br>
<br>&gt; Oh, ok. Is this function virtual? Is it always called for every
<br>&gt; scope-local object?
<br>&gt; I suppose a trait-like facility could be used to make that decisio=
n at
<br>&gt; code-generation
<br>&gt; time, sure. Alternatively, we could just as well put a keyword in =
the class-head
<br>&gt; of such classes, and refuse the declarations of this special funct=
ion if the
<br>&gt; class doesn't have the right keyword.
<br>
<br>
<br>I should mention that having all these concerns and figuring out a
<br>solution for them makes me gravitate
<br>towards even an imperfect support library solution, since it's FAR
<br>less intrusive.
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_676_4177652.1401835176543--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 4 Jun 2014 01:43:02 +0300
Raw View
On 4 June 2014 01:39, Diggory Blake <diggsey@googlemail.com> wrote:
> Whether it's virtual would be up to the class (similar to destructors -
> virtual would be strongly recommended if your class it to be used as a base)

Right.

> For stack variables, it's always called immediately before the destructor,
> but only if the destructor is being executed normally - it's not a guarantee
> to the transaction class that it will be called, it must be valid to
> destruct the transaction object without calling this function.

Normally, as in non-unwinding cases? Why not the other way around?

> I was assuming some sort of trait would exist to detect classes with this
> special function, this would allow container classes and smart pointers to
> forward on the call where needed, while not imposing an extra cost when not
> needed, but the exact mechanics are not hugely important as long as
> detection is possible at compile time.

I do not think the motivation of this facility will be sufficient to convince
existing containers and smart pointers to start using such a special function.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 3 Jun 2014 16:05:15 -0700 (PDT)
Raw View
------=_Part_652_979906.1401836715636
Content-Type: text/plain; charset=UTF-8



On Tuesday, 3 June 2014 23:43:03 UTC+1, Ville Voutilainen wrote:
>
> On 4 June 2014 01:39, Diggory Blake <dig...@googlemail.com <javascript:>>
> wrote:
> > Whether it's virtual would be up to the class (similar to destructors -
> > virtual would be strongly recommended if your class it to be used as a
> base)
>
> Right.
>
> > For stack variables, it's always called immediately before the
> destructor,
> > but only if the destructor is being executed normally - it's not a
> guarantee
> > to the transaction class that it will be called, it must be valid to
> > destruct the transaction object without calling this function.
>
> Normally, as in non-unwinding cases? Why not the other way around?
>

Yeah, I could have phrased that better: if an object is destructed as the
result of it's scope being left normally, and not through unwinding.

Having it this way around means that this special function can safely throw
exceptions, which I think will be very useful. For example, the transaction
object would be able to throw an exception if the implicit commit failed.
Roll-back should always be noexcept, so it fits neatly to have that as the
default in the destructor if the transaction hasn't already been committed.


>
> > I was assuming some sort of trait would exist to detect classes with
> this
> > special function, this would allow container classes and smart pointers
> to
> > forward on the call where needed, while not imposing an extra cost when
> not
> > needed, but the exact mechanics are not hugely important as long as
> > detection is possible at compile time.
>
> I do not think the motivation of this facility will be sufficient to
> convince
> existing containers and smart pointers to start using such a special
> function.
>

Perhaps not, although I think at the very least unique_ptr ought to have
support for it. In any case, it would at least be there for people to use
in their own code if they need it. Plus you don't lose anything over the
current system - you can always go through and call "commit" or whatever
it's called explicitly, and in the 90% of cases where the transaction is on
the stack, everything will just work.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_652_979906.1401836715636
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 3 June 2014 23:43:03 UTC+1, Ville Vout=
ilainen  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 4 June 2014 =
01:39, Diggory Blake &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"yb-PbhVu_OUJ" onmousedown=3D"this.href=3D'javascript:';ret=
urn true;" onclick=3D"this.href=3D'javascript:';return true;">dig...@google=
mail.com</a>&gt; wrote:
<br>&gt; Whether it's virtual would be up to the class (similar to destruct=
ors -
<br>&gt; virtual would be strongly recommended if your class it to be used =
as a base)
<br>
<br>Right.
<br>
<br>&gt; For stack variables, it's always called immediately before the des=
tructor,
<br>&gt; but only if the destructor is being executed normally - it's not a=
 guarantee
<br>&gt; to the transaction class that it will be called, it must be valid =
to
<br>&gt; destruct the transaction object without calling this function.
<br>
<br>Normally, as in non-unwinding cases? Why not the other way around?
<br></blockquote><div><br>Yeah, I could have phrased that better: if an obj=
ect is destructed as the result of it's scope being left normally, and not =
through unwinding.<br><br>Having it this way around means that this special=
 function can safely throw exceptions, which I think will be very useful. F=
or example, the transaction object would be able to throw an exception if t=
he implicit commit failed. Roll-back should always be noexcept, so it fits =
neatly to have that as the default in the destructor if the transaction has=
n't already been committed.<br>&nbsp;</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;">
<br>&gt; I was assuming some sort of trait would exist to detect classes wi=
th this
<br>&gt; special function, this would allow container classes and smart poi=
nters to
<br>&gt; forward on the call where needed, while not imposing an extra cost=
 when not
<br>&gt; needed, but the exact mechanics are not hugely important as long a=
s
<br>&gt; detection is possible at compile time.
<br>
<br>I do not think the motivation of this facility will be sufficient to co=
nvince
<br>existing containers and smart pointers to start using such a special fu=
nction.
<br></blockquote><div><br>Perhaps not, although I think at the very least u=
nique_ptr ought to have support for it. In any case, it would at least be t=
here for people to use in their own code if they need it. Plus you don't lo=
se anything over the current system - you can always go through and call "c=
ommit" or whatever it's called explicitly, and in the 90% of cases where th=
e transaction is on the stack, everything will just work.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_652_979906.1401836715636--

.


Author: David Krauss <potswa@gmail.com>
Date: Wed, 4 Jun 2014 11:52:42 +0800
Raw View
--Apple-Mail=_C6156395-5F57-4276-BC6A-C6EE395C9B14
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-06-04, at 5:27 AM, inkwizytoryankes@gmail.com wrote:

> What if that same data was send through helper function, not by new versi=
on of destructor?
> Something like that:
> struct A
> {
>     ~A() { if(is_unwinding(this)) rollback(); else commit(); }
> }

Yep, this is essentially what my idea does. The function would compare the =
ticket ID of this to the ticket ID of the innermost exception. Except, I fo=
resee that caught exceptions should prevent commitment too; we just don't s=
ee the distinction currently because uncaught_exception has a narrower use-=
case. An exception ticket is in-flight until the exception object is destro=
yed.

It works as a library-only solution by also saying that an exception-ticket=
 is in-flight from the time it is created, because this is approximately eq=
ual to the time it is thrown. The only core language support is a special m=
ember function that gets called when an object is thrown. Perhaps call it o=
perator throw().

But, the system needs to be tested and I'm not sure how to generate test re=
sults that will be suitably convincing. I need to attend a conference and a=
sk committee members in person to get a feel for that.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_C6156395-5F57-4276-BC6A-C6EE395C9B14
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;06&ndash;04, at 5:27 AM, <a href=3D"mailto:inkwizytoryankes@gmail.com=
">inkwizytoryankes@gmail.com</a> wrote:</div><br class=3D"Apple-interchange=
-newline"><blockquote type=3D"cite"><div dir=3D"ltr">What if that same data=
 was send through helper function, not by new version of destructor?<br>Som=
ething like that:<br><div class=3D"prettyprint" style=3D"background-color: =
rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; =
border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">struct</span> A<br><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><br>&nbsp; =
&nbsp; <span style=3D"color: #660;" class=3D"styled-by-prettify">~</span>A<=
span style=3D"color: #660;" class=3D"styled-by-prettify">()</span> <span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span> <span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span>is_unwinding<span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">))</span> rollback<span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">();</span> <span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">else</span> commit<span style=3D"color: #660;" class=3D"=
styled-by-prettify">();</span> <span style=3D"color: #660;" class=3D"styled=
-by-prettify">}</span><br><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}</span><br></code></div></div></blockquote></div><br><div>Yep, th=
is is essentially what my idea does. The function would compare the ticket =
ID of <font face=3D"Courier">this</font> to the ticket ID of the innermost =
exception. Except, I foresee that caught exceptions should prevent commitme=
nt too; we just don&rsquo;t see the distinction currently because <font fac=
e=3D"Courier">uncaught_exception</font> has a narrower use-case. An excepti=
on ticket is in-flight until the exception object is destroyed.</div><div><=
br></div><div>It works as a library-only solution by also saying that an ex=
ception-ticket is in-flight from the time it is created, because this is ap=
proximately equal to the time it is thrown. The only core language support =
is a special member function that gets called when an object is thrown. Per=
haps call it&nbsp;<font face=3D"Courier">operator throw()</font>.</div><div=
><br></div><div>But, the system needs to be tested and I&rsquo;m not sure h=
ow to generate test results that will be suitably convincing. I need to att=
end a conference and ask committee members in person to get a feel for that=
..</div><div><br></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_C6156395-5F57-4276-BC6A-C6EE395C9B14--

.


Author: inkwizytoryankes@gmail.com
Date: Wed, 4 Jun 2014 11:29:39 -0700 (PDT)
Raw View
------=_Part_446_9076266.1401906580409
Content-Type: text/plain; charset=UTF-8

In case of object that will be deleted by operator `delete` could be
replaced by function that do same and forwarding unwind state:
struct A
{
    A* a;
    ~A()
    {
        //delete a;
        unwinding_forward_delete(this, a);// or
unwinding_forward_destructor to call only ~A(), useful for allocator
    }
}
This will require some `map` like data struct to store all memory ranges of
all objects under destruction (in some cases would be better store it in
big array because of cache misses).
However this will not require any dynamic memory allocation, because all
new data can be stored as local variables in that function.
Only drawback is O(log n) cost of every call (where n is number of nested
calls).

I think this approach will work well with scoped guard objects like
`unique_ptr`.


On Wednesday, June 4, 2014 12:35:18 AM UTC+2, Ville Voutilainen wrote:
>
> On 4 June 2014 01:27,  <inkwizyt...@gmail.com <javascript:>> wrote:
> > Sorry, wrong word. As "exception handler" I mean struct that is handling
> > unwinding and storing current exception.
> > This pointers are set before destructor call.
>
> Ok, and then classes that care about this information can query whether
> 'this' is in that range delimited by those pointers. This solution will
> not
> work with objects that are allocated dynamically but are wrapped in a
> scope-local
> handle, so the handle will need to tell the dynamic object it's holding
> what
> the unwind state is.
>
> Regarding having to invoke such a special function dynamically, we would
> be
> facing a need to change massive amounts of code so that various resource
> handles will perform that dynamic invocation. That is more or less an
> impossible
> change.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_446_9076266.1401906580409
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">In case of object that will be deleted by operator `delete=
` could be replaced by function that do same and forwarding unwind state:<b=
r><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250);=
 border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> A<br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp;&nbsp;&nbsp; A* a=
;<br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">~</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp;=
 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><=
br><span style=3D"color: #000;" class=3D"styled-by-prettify"><code class=3D=
"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style=3D"color: #800;"=
 class=3D"styled-by-prettify">//delete a;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs=
p; unwinding_forward_delete(this, a);</span></code></span><code class=3D"pr=
ettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify"><code =
class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"></span><span style=3D"color: #800;" class=3D"styled-by-prettify">// or=
 unwinding_forward_destructor to call only ~A(), useful for allocator<br></=
span></code></span></code><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
</div></code></div>This will require some `map` like data struct to store a=
ll memory ranges of all objects under destruction (in some cases would be b=
etter store it in big array because of cache misses).<br>However this will =
not require any dynamic memory allocation, because all new data can be stor=
ed as local variables in that function.<br>Only drawback is O(log n) cost o=
f every call (where n is number of nested calls).<br><br>I think this appro=
ach will work well with scoped guard objects like `unique_ptr`.<br><br><br>=
On Wednesday, June 4, 2014 12:35:18 AM UTC+2, Ville Voutilainen wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On 4 June 2014 01:27, &nbsp;&lt;<a =
href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"lz-tTB22jWg=
J" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.h=
ref=3D'javascript:';return true;">inkwizyt...@gmail.com</a>&gt; wrote:
<br>&gt; Sorry, wrong word. As "exception handler" I mean struct that is ha=
ndling
<br>&gt; unwinding and storing current exception.
<br>&gt; This pointers are set before destructor call.
<br>
<br>Ok, and then classes that care about this information can query whether
<br>'this' is in that range delimited by those pointers. This solution will=
 not
<br>work with objects that are allocated dynamically but are wrapped in a
<br>scope-local
<br>handle, so the handle will need to tell the dynamic object it's holding=
 what
<br>the unwind state is.
<br>
<br>Regarding having to invoke such a special function dynamically, we woul=
d be
<br>facing a need to change massive amounts of code so that various resourc=
e
<br>handles will perform that dynamic invocation. That is more or less an i=
mpossible
<br>change.
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_446_9076266.1401906580409--

.