View mode: basic / threaded / horizontal-split · Log in · Help
March 01, 2006
Re: DMD 0.148 - scope guard
In article <dtsgcf$1i3q$1@digitaldaemon.com>, Hasan Aljudy says...
>
>Thomas Kuehne wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>> 
>> bobef schrieb am 2006-02-26:
>> 
>>>Knud S�rensen wrote:
>>>
>>>
>>>>Freshmeat is the slashdot equivalent for software.
>>>
>>>Forgive my ignorance, but what is slashdot?
>> 
>> 
>> http://slashdot.org
>> 
>> Thomas
>> 
>> 
>> -----BEGIN PGP SIGNATURE-----
>> 
>> iD8DBQFEAX4/3w+/yD4P9tIRAjvuAJwPvtROSVZvxhiVZkzrJK+5zq2hDQCeI3Bt
>> ThkzHvadOtJAdWlCXR6c6zc=
>> =sWOz
>> -----END PGP SIGNATURE-----
>
>Still, what is it? I've been there before .. didn't quite get it. Why is 
>it so popular?!

It's technology and scientific news and covers a lot of 'nerd' interest stuff;
it's highly configurable if you have an account.

Every article has free-form user comments and discussion, which means you not
only see the news article, but can pick up dozens of links to related info, get
opinions on both sides, etc.  (Many of the participants are highly uninformed,
but that is hard to avoid on the web...)

It's news, discussion, conversation, and a sort of "commonwealth" community, and
each discussion is anchored off of a "real" news article, book review, or
writeup, usually somewhere else.  In this way its like a mixture of newsgroup
discussions, journalism, and wiki-like community authoring.

Like almost all human communities, the appeal is determined mostly by the types
of people that exist there (i.e. prisons versus country clubs versus rock
concerts).  So its probably very grating if you don't like techie/trekkie/IT
types.

[But it's starting to look commonplace now because everyone copied them.  Every
revolution is unthinkable beforehand and obvious afterwards...]

Kevin
March 01, 2006
Re: Negative
Walter Bright wrote:
> I hope that these buggy examples show just how hard it is to get 
> try-catch-finally to be correct, and how easy it is to get the on_scope 
> correct. This leads me to believe that try-catch-finally is just 
> conceptually wrong, as it does not match up with how we think despite being 
> in common use for over a decade. 

This is very interesting. Seems to me that these on_scope_xxx are kind 
of "naked destructors". If you consider them to be the low-level 
construct, then putting a destructor into a class means: when the 
constructor is called, insert "on_scope_exit ~this()" at the same time.

Is the convoluted nature of the RAII solution simply because
the same destructor is executed regardless of whether the function was 
exited normally, or whether an exception occurred? And because there's 
no easy way of determining if you are inside an exception handler. So 
you only have "finally", without "catch".
I wonder if destructors could be jazzed up, so that they can insert an 
"on_scope_failure" as well as "on_scope_exit"?
Maybe called ~catch()?

class Foo
{
~catch() {
unwind_foo();
}
}

class Bar
{
  ~this() { // destroy bar
   }
  ~catch() {
   unwind_bar();
  //  now we go to ~this(), which behaves like finally.
  }
}

Transaction abc()
{
    Foo f;
    Bar b;
    Def d;

    f = dofoo();
    b = dobar();
    d = dodef();

    return Transaction(f, b, d);
}

Doesn't have the flexibility of on_scope, where you have access to all 
variables -- but on the other hand, it has the RAII benefit that users 
of the class don't need to remember to do it.

Just an idea.
March 01, 2006
Re: Negative
Don Clugston wrote:
<snip>
> Is the convoluted nature of the RAII solution simply because
> the same destructor is executed regardless of whether the function was 
> exited normally, or whether an exception occurred? And because there's 
> no easy way of determining if you are inside an exception handler. So 
> you only have "finally", without "catch".
> I wonder if destructors could be jazzed up, so that they can insert an 
> "on_scope_failure" as well as "on_scope_exit"?
> Maybe called ~catch()?
<snip>

Can you think of a practical use for this idea?  I'm not sure what sense 
it would make, considering that the class knows nothing of what the code 
that failed was doing at the time.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- 
PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
March 01, 2006
Re: Negative
"Andrew Fedoniouk" <news@terrainformatica.com> wrote in message 
news:du2q1c$4tv$1@digitaldaemon.com...
>
> "Walter Bright" <newshound@digitalmars.com> wrote in message
>> The new bug in the above code is that the catch block fails to rethrow o.
> Let's say it was an intention. Pretty common by the way.

Perhaps, but the stated point of the example was to show equivalent 
try-catch code to the on_scope example. It isn't equivalent.

> Well try first to explain what will happen on
> on_scope_success { delete baz; throw foo; }
> on_scope_exit { delete baz; throw foo; }
>
> What "lexical order" will be used here? What scope guards will be invoked 
> and so on.

Throwing from inside an on_scope statement is as bad an idea as throwing 
inside a destructor or inside a finally block. Doing it in an on_scope_exit 
or on_scope_failure will result in a double-fault exception. Doing it in an 
on_scope_success will be like throwing at the } of a scope.

> Having on_scope_*** spread all other the "... lots of code ..."  will 
> create
> code maintainance nightmare as to trace visually what will happen and when 
> will not be a task for human anymore.

I submit that based on what's been posted in this thread, it's easier to get 
on_scope *correct* than try-finally, because most of the try-finally 
examples posted here do not work as intended by the author. Not only that, 
the try-finally examples fail in ways that are difficult to write test cases 
for, so the errors are likely to go unnoticed.

> And as far as I understand main idea of on_scope_exit is a sort of poor 
> man struct destructor...
> I suspect that you are thinking about how to remove 'auto'/RAII, right?

No. RAII is for managing resources, which is different from managing state 
or transactions. try-catch is still needed, as on_scope doesn't catch 
exceptions. It's try-finally that becomes redundant, though it is useful to 
keep it because so many people are used to it.
March 01, 2006
Re: try..catch..pass..finally Was: DMD 0.148 - scope guard
"S. Chancellor" <dnewsgr@mephit.kicks-ass.org> wrote in message 
news:du376e$1fbf$2@digitaldaemon.com...
> Something like this would be equivalent?
>
> Transaction abc()
> {
> Foo f;
>     Bar b;
>     Def d;
> Auto scoped = new Scoper();  //scoped.exit() can be called by the 
> destructor.  We won't add a finally block.
>
> try {
> scoped.failures ~= void delegate () { dofoo_unwind(f); }
>     f = dofoo();
>
> scoped.failures ~= void delegate () { dobar_unwind(b); }
> b = dobar();
>
> scoped.success()
> } catch (Exception o) {
> scoped.failed()
> throw o;
> }
>
> return Transaction(f, b, d);
> }

Should be:
    f = dofoo();
    scoped.failures ~= void delegate () { dofoo_unwind(f); }
etc. Other than that, it looks like it'll work, but it's a lot more code 
than on_scope. You also need to be sure that the delegates don't refer to 
any variables declared inside the try block, as those variables no longer 
exist in the catch block - and the compiler can't catch that error. This 
isn't a problem with on_scope.
March 01, 2006
Re: Negative
Walter Bright wrote:
> "Andrew Fedoniouk" <news@terrainformatica.com> wrote in message 
> news:du2q1c$4tv$1@digitaldaemon.com...
>> "Walter Bright" <newshound@digitalmars.com> wrote in message
>>> The new bug in the above code is that the catch block fails to rethrow o.
>> Let's say it was an intention. Pretty common by the way.
> 
> Perhaps, but the stated point of the example was to show equivalent 
> try-catch code to the on_scope example. It isn't equivalent.

That may have been the point of the original example, but it wasn't the 
point of mine.  But it's water under the bridge, as you answered my 
question either way :-)

>> Having on_scope_*** spread all other the "... lots of code ..."  will 
>> create
>> code maintainance nightmare as to trace visually what will happen and when 
>> will not be a task for human anymore.
> 
> I submit that based on what's been posted in this thread, it's easier to get 
> on_scope *correct* than try-finally, because most of the try-finally 
> examples posted here do not work as intended by the author. Not only that, 
> the try-finally examples fail in ways that are difficult to write test cases 
> for, so the errors are likely to go unnoticed.

The only complaint I've heard about on_scope that I consider valid is 
that program flow may be a tad confusing in excessively long functions. 
 But traditional RAII is no better, and try-finally introduces 
maintenance and readability problems by breaking the logical connection 
between unwinding code and the code block it's associated with.  It's 
also helpful that throwing an exception while another is in-flight in D 
does not result in program termination, even if doing so is not advisable.

>> And as far as I understand main idea of on_scope_exit is a sort of poor 
>> man struct destructor...
>> I suspect that you are thinking about how to remove 'auto'/RAII, right?
> 
> No. RAII is for managing resources, which is different from managing state 
> or transactions. try-catch is still needed, as on_scope doesn't catch 
> exceptions. It's try-finally that becomes redundant, though it is useful to 
> keep it because so many people are used to it. 

That may have been the original intent, but RAII has since become almost 
indispensable for writing exception-safe code, be it with resources, 
transactions, or something else.  Personally, I've never liked 
try-finally, but I attribute that to my C++ background.  If I were a 
Java person it may be a different story.


Sean
March 01, 2006
Re: Negative
Don Clugston wrote:
> Walter Bright wrote:
>> I hope that these buggy examples show just how hard it is to get 
>> try-catch-finally to be correct, and how easy it is to get the 
>> on_scope correct. This leads me to believe that try-catch-finally is 
>> just conceptually wrong, as it does not match up with how we think 
>> despite being in common use for over a decade. 
> 
> This is very interesting. Seems to me that these on_scope_xxx are kind 
> of "naked destructors". If you consider them to be the low-level 
> construct, then putting a destructor into a class means: when the 
> constructor is called, insert "on_scope_exit ~this()" at the same time.

on_scope does practically eliminate the need for an 'auto' keyword, 
assuming auto classes would be allocated on the heap either way.

> Is the convoluted nature of the RAII solution simply because
> the same destructor is executed regardless of whether the function was 
> exited normally, or whether an exception occurred? And because there's 
> no easy way of determining if you are inside an exception handler. So 
> you only have "finally", without "catch".
> I wonder if destructors could be jazzed up, so that they can insert an 
> "on_scope_failure" as well as "on_scope_exit"?

I've considered adding functionality to Ares to allow a user to 
determine if an exception is currently in flight--C++ offers this but 
it's little used as it's not terribly reliable.  But with on_scope there 
seems little need for this.

> Maybe called ~catch()?
> 
> class Foo
> {
> ~catch() {
> unwind_foo();
> }
> }
> 
> class Bar
> {
>   ~this() { // destroy bar
>    }
>   ~catch() {
>    unwind_bar();
>   //  now we go to ~this(), which behaves like finally.
>   }
> }
> 
> Transaction abc()
> {
>     Foo f;
>     Bar b;
>     Def d;
> 
>     f = dofoo();
>     b = dobar();
>     d = dodef();
> 
>     return Transaction(f, b, d);
> }
> 
> Doesn't have the flexibility of on_scope, where you have access to all 
> variables -- but on the other hand, it has the RAII benefit that users 
> of the class don't need to remember to do it.

True.  But I would argue that the burden of writing exception-safe code 
is on the function writer moreso than the class writer, largely because 
the class writer can't predict or address every way that his class may 
be used.  on_scope also allows a bit more flexibility:

{
    Foo f = acquireFoo();

    on_scope_exit    f.commitAll();
    on_scope_failure f.unwindAll();

    f.setFirst();
    {
        f.setSecond();

        on_scope_failure f.unwindLast();
    }
}


Sean
March 01, 2006
Re: Negative
Sean Kelly wrote:
<snip>
> on_scope does practically eliminate the need for an 'auto' keyword, 
> assuming auto classes would be allocated on the heap either way.
<snip>

How would you declare an auto class without the auto keyword?

Moreover, while

    auto Qwert yuiop = new Qwert;

appears to be syntactic sugar for

    Qwert yuiop = new Qwert;
    on_scope_exit delete yuiop;

the former does still (I assume) have the advantage of stopping you from 
inadvertently reassigning to yuiop.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- 
PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
March 01, 2006
Re: Negative
"Sean Kelly" <sean@f4.ca> wrote in message 
news:du4mfe$18k5$1@digitaldaemon.com...
> Walter Bright wrote:
>> RAII is for managing resources, which is different from managing state or 
>> transactions. try-catch is still needed, as on_scope doesn't catch 
>> exceptions. It's try-finally that becomes redundant, though it is useful 
>> to keep it because so many people are used to it.
>
> That may have been the original intent, but RAII has since become almost 
> indispensable for writing exception-safe code, be it with resources, 
> transactions, or something else.

RAII is used for those other things in C++ because there is *no other 
choice*. Nevertheless, the reality of using destructors to manage 
transaction processing is:

1) it's so hard to do that most programmers simply ignore the problem, 
trusting to luck that exceptions won't happen

2) those that do try it, most of the time get it wrong

3) it's pretty hard to visually inspect the code and determine that it is 
exception safe

This suggests to me that RAII and try-finally are the wrong paradigms for 
doing transaction programming. I've attended Scott Meyer's insightful 
lecture on doing transaction programming in C++. There is no hope for it to 
be reliably done by anyone but experts.


> Personally, I've never liked try-finally, but I attribute that to my C++ 
> background.  If I were a Java person it may be a different story.

Try-finally and RAII are like goto's. They work, but aren't using whiles, 
fors, switches, etc., much more natural?
March 01, 2006
Re: Negative
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message 
news:du4q5j$1ckc$1@digitaldaemon.com...
> Moreover, while
>
>     auto Qwert yuiop = new Qwert;
>
> appears to be syntactic sugar for
>
>     Qwert yuiop = new Qwert;
>     on_scope_exit delete yuiop;

That's correct. In fact, it's implemented that way <g>.

> the former does still (I assume) have the advantage of stopping you from 
> inadvertently reassigning to yuiop.

Yes, whereas the latter allows state unwinding for things that aren't class 
objects. Without on_scope_exit, extra dummy classes would have to be defined 
for each, turning a one liner into a dozen lines that appear out of context.
9 10 11 12 13 14 15 16
Top | Discussion index | About this forum | D home