Topic: Guaranteed scope


Author: seh@panix.com ("Steven E. Harris")
Date: Tue, 14 Feb 2006 04:06:45 GMT
Raw View
invalid@bigfoot.com (Bob Hairgrove) writes:

> That's one of the major differences between C++ and Java: the
> standard gives us a guarantee as to when the destructor is called.

But the standard here doesn't say when the destructor is called, only
the lower bound on how soon it will be called:

,----
| it shall not be destroyed before the end of its block
`----

How long /after/ the end of its block is acceptable?

--
Steven E. Harris

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Tue, 14 Feb 2006 15:24:29 GMT
Raw View
On Tue, 14 Feb 2006 04:06:45 GMT, seh@panix.com ("Steven E. Harris")
wrote:

>invalid@bigfoot.com (Bob Hairgrove) writes:
>
>> That's one of the major differences between C++ and Java: the
>> standard gives us a guarantee as to when the destructor is called.
>
>But the standard here doesn't say when the destructor is called, only
>the lower bound on how soon it will be called:
>
>,----
>| it shall not be destroyed before the end of its block
>`----
>
>How long /after/ the end of its block is acceptable?

Well, section 6.7 paragraph 2 seems pretty clear to me:

"Variables with automatic storage duration (3.7.2) ... declared in the
block are destroyed on exit from the block (6.6)."

--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com
Date: Tue, 14 Feb 2006 09:36:33 CST
Raw View
>
> How long /after/ the end of its block is acceptable?
>

6.6/2 says: "On exit from a scope (however accomplished), destructors
(12.4) are called for all constructed objects with automatic storage
duration (3.7.2) (named objects or temporaries) that are declared in
that scope, in the reverse order of declaration."  I don't see any
leeway for delayed destruction at all.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: no.spam@no.spam.com (Maciej Sobczak)
Date: Tue, 14 Feb 2006 19:03:00 GMT
Raw View
Steven E. Harris wrote:

>>That's one of the major differences between C++ and Java: the
>>standard gives us a guarantee as to when the destructor is called.
>
> But the standard here doesn't say when the destructor is called, only
> the lower bound on how soon it will be called:
>
> ,----
> | it shall not be destroyed before the end of its block
> `----
>
> How long /after/ the end of its block is acceptable?

In microseconds? It's not specified, so even 1 hour would be OK. ;)

But more seriously, 6.7/2:

"Variables with automatic storage duration declared in the block are
destroyed on exit from the block"

This means that:

{
     {
         Lock lck(mtx);  // (1)
         // ...          // (2)
     }
     // ...              // (3)
}

The lck object will *not* be destroyed earlier than at the end of its
block (even if it seems to be unused), so (2) is always executed with
the mutex locked. When the block exits, the object is destroyed, so that
(3) is executed after the destructor of lck finished. Both of these
points make the whole idiom well defined.

The only thing that has left to be dissected is whether the object is
destroyed just before the closing brace '}' or just after, but there's
no way to observe it, so it simply doesn't matter. ;-)


--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: seh@panix.com ("Steven E. Harris")
Date: Tue, 14 Feb 2006 19:05:32 GMT
Raw View
johnchx2@yahoo.com writes:

> I don't see any leeway for delayed destruction at all.

Ah, that's better. Just reading the small extracts posted from 3.7.2/3
didn't sound sufficient to cover the OP's concerns.

--
Steven E. Harris

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "ScottM" <scott@mayo.name>
Date: Thu, 9 Feb 2006 22:49:05 CST
Raw View
I've been using a trick for years, and it occured to me I have no idea
if the standard guarantees the behaviour. I decided I wasn't sure, so
I'm asking the experts.

It's useful to lock a mutex, do some operations and then unlock the
mutex. It's useful to unlock the mutex even if the execution returns in
the middle, throws an exception or otherwise escapes from the middle of
the locked operations.

I've been creating a class that locks the mutex on construction, and
unlocks on destruction. I create an instance of the class when I want
to lock, and then do my locked operations. I surround all this with {}
so it's obvious when the object goes out of scope (and unlocks).

   {
     LockGuard g(address_of_mutex);  //does the lock

     //..code that's safe under the lock, but might throw or return...

   } //deconstructs g, unlocks lock

The problem is that there's no actual reference to g in the code. I
can't think of any reason that a compiler might not notice that, and
instantly deconstruct the object after the constructor runs, making the
whole thing useless. I haven't met a compiler yet that did that, but
I'm worried I'm going to. Does the standard have anything to say about
this?

Thanks.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Maciej Sobczak <no.spam@no.spam.com>
Date: Fri, 10 Feb 2006 09:47:51 CST
Raw View
ScottM wrote:

>    {
>      LockGuard g(address_of_mutex);  //does the lock
>
>      //..code that's safe under the lock, but might throw or return...
>
>    } //deconstructs g, unlocks lock
>
> The problem is that there's no actual reference to g in the code.

It does not matter. If the object is *named*, then it is a local object
with automatic storage duration and it exists until the block is left,
with some additional guarantees concerning the order of destructions
when there is more than one such object.

The following statement deals with your LockGuard case:

3.7.2/3:

"If a named automatic object has initialization or a destructor with
side effects, it shall not be destroyed before the end of its block,
[...] even if it appears to be unused [...]"


--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Fri, 10 Feb 2006 15:52:24 GMT
Raw View
ScottM ha scritto:
> The problem is that there's no actual reference to g in the code. I
> can't think of any reason that a compiler might not notice that, and
> instantly deconstruct the object after the constructor runs, making the
> whole thing useless. I haven't met a compiler yet that did that, but
> I'm worried I'm going to. Does the standard have anything to say about
> this?

Don't worry. That's THE correct way to use mutexes. And if you want a
precise reference in the standard, here it is:

3.7.2/3: "If a named automatic object has initialization or a destructor
with side effects, it shall not be destroyed before the end of its
block, nor shall it be eliminated as an optimization even if it appears
to be unused, except [exception irrelevant to your case]."

HTH,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net
Date: Fri, 10 Feb 2006 09:57:32 CST
Raw View
ScottM wrote:
> I've been using a trick for years, and it occured to me I have no idea
> if the standard guarantees the behaviour. I decided I wasn't sure, so
> I'm asking the experts.
>
> It's useful to lock a mutex, do some operations and then unlock the
> mutex. It's useful to unlock the mutex even if the execution returns in
> the middle, throws an exception or otherwise escapes from the middle of
> the locked operations.
>
> I've been creating a class that locks the mutex on construction, and
> unlocks on destruction. I create an instance of the class when I want
> to lock, and then do my locked operations. I surround all this with {}
> so it's obvious when the object goes out of scope (and unlocks).
>
>    {
>      LockGuard g(address_of_mutex);  //does the lock
>
>      //..code that's safe under the lock, but might throw or return...
>
>    } //deconstructs g, unlocks lock
>
> The problem is that there's no actual reference to g in the code. I
> can't think of any reason that a compiler might not notice that, and
> instantly deconstruct the object after the constructor runs, making the
> whole thing useless. I haven't met a compiler yet that did that, but
> I'm worried I'm going to. Does the standard have anything to say about
> this?

'g' has a guaranteed lifetime that continues to the end of the block
it's declared in. The only thing that would allow a compiler to
optimize it out of existence is the as-if rule. The as-if rule places a
burden on the implementation of being able to prove that the
optimization produces behavior that would be legal even if the
implementation didn't perform the optimization.. In the unlikely event
that the implementation can prove, to it's own satisfaction, that
removing that mutex has the same effect as leaving it there, then you
shouldn't worry. In practice, the only way that would be true is if you
were a) compiling for an environment where mutexes are unnecessary or
b) the implementation has already inserted mutexes, for purposes of
it's own, that happen to render your mutexes unnecessary.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gerhard Wesp <gwesp@ukato.freeshell.org>
Date: Fri, 10 Feb 2006 09:57:31 CST
Raw View
ScottM <scott@mayo.name> wrote:
> I've been using a trick for years, and it occured to me I have no idea
> if the standard guarantees the behaviour. I decided I wasn't sure, so

This trick is more or less the standard idiom for locks and mutexes.  It
is safe.  The standard library itself uses this idiom for sentry objects.

Regards
-Gerhard
--
Gerhard Wesp
Zuerich, Switzerland
+41 (0)76 505 1149 (mobile)
+41 (0)44 668 1878 (office)
+41 (0)44 200 1818 (office fax)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "John Hickin" <hickin@nortel.com>
Date: Fri, 10 Feb 2006 13:37:07 CST
Raw View
"ScottM" <scott@mayo.name> wrote in message
news:1139510250.058560.293450@o13g2000cwo.googlegroups.com...

>
>    {
>      LockGuard g(address_of_mutex);  //does the lock
>
>      //..code that's safe under the lock, but might throw or return...
>
>    } //deconstructs g, unlocks lock

It is guaranteed. There is a similar section guaranteeing that static
objects which do not appear to be used shall be kept.
3.7.2 Automatic storage duration

3 If a named automatic object has initialization or a destructor with side
effects, it shall not be destroyed, before the end of its block, nor shall
it be eliminated as an optimization even if it appears to be unused, except
that a class object or its copy may be eliminated as specified in 12.8.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "ScottM" <scott@mayo.name>
Date: Fri, 10 Feb 2006 13:37:13 CST
Raw View
Thanks, folk.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmabee@comcast.net (Robert Mabee)
Date: Sat, 11 Feb 2006 07:22:31 GMT
Raw View
> "If a named automatic object has initialization or a destructor with
> side effects, it shall not be destroyed before the end of its block,
> [...] even if it appears to be unused [...]"

How about the possibility that the destructor may not complete when
expected, so the mutex may be observed still held later in the same
thread?  In other words, when are destructors guaranteed to have
finished?  Could it be delayed to function exit if there isn't a loop
back to the constructor?

Another thread brought up some fine-grained parallelism that the
compiler might introduce, which raises questions about ordering that
are not clearly answered in the standard.  So, suppose the destructor
is run as a compiler-generated cheap thread.  When is the main line
required to wait for that thread to complete?

This is a very real problem with destruction by garbage collection,
as in Java.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Sun, 12 Feb 2006 01:20:38 GMT
Raw View
On Sat, 11 Feb 2006 07:22:31 GMT, rmabee@comcast.net (Robert Mabee)
wrote:

>> "If a named automatic object has initialization or a destructor with
>> side effects, it shall not be destroyed before the end of its block,
>> [...] even if it appears to be unused [...]"
>
>How about the possibility that the destructor may not complete when
>expected, so the mutex may be observed still held later in the same
>thread?  In other words, when are destructors guaranteed to have
>finished?  Could it be delayed to function exit if there isn't a loop
>back to the constructor?
>
>Another thread brought up some fine-grained parallelism that the
>compiler might introduce, which raises questions about ordering that
>are not clearly answered in the standard.  So, suppose the destructor
>is run as a compiler-generated cheap thread.  When is the main line
>required to wait for that thread to complete?
>
>This is a very real problem with destruction by garbage collection,
>as in Java.

That's one of the major differences between C++ and Java: the standard
gives us a guarantee as to when the destructor is called.

--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]