[exception] uncaught_exception_count, scope(failure), scope(success)

Hello All, There is implementation of uncaught_exception_count - https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/un... . uncaught_exception_count is a function similar to std::uncaught_exception from standard library, but instead of boolean result it returns unsigned int showing current count of uncaught exceptions. uncaught_exception_count allow us to implement scope(failure) and scope(success) features from D language in C++. ( previous discussion is at http://boost.2283326.n4.nabble.com/scope-exit-D-style-scope-failure-and-scop... ) Implementation of uncaught_exception_count is tested on {Clang 3.2, GCC 3.4.6, GCC 4.1.2, GCC 4.4.6, GCC 4.4.7, MSVC2005SP1, MSVC2008SP1, MSVC2010SP1, MSVC2012} x {x32, x64}. There are also live stress tests - detection of 500 simultaneous uncaught exceptions: GCC 4.6.3: http://liveworkspace.org/code/2qmSso%240 GCC 4.7.2: http://liveworkspace.org/code/dY0VD%240 Clang 3.2: http://liveworkspace.org/code/49MaPk%240 I think that uncaught_exception_count (and uncaught_exception_count_latch primitive) can be added into Boost.Exception library, at least into "detail" section. After that scope(failure) and scope(success) features can be implemented in Boost.ScopeExit library. Note, approximately 14 of 16 Boost.ScopeExit examples in manual are in fact emulations of scope(failure)/scope(success). So, looks like in first place Boost.ScopeExit was introduced to simplify emulation of scope(failure) and scope(success) features. What do you think? Thank you. Best Regards, Evgeny Panasyuk

On Tue, Feb 5, 2013 at 11:11 AM, Evgeny Panasyuk <evgeny.panasyuk@gmail.com> wrote:
uncaught_exception_count allow us to implement scope(failure) and scope(success) features from D language in C++. ( previous discussion is at http://boost.2283326.n4.nabble.com/scope-exit-D-style-scope-failure-and-scop...
I'm not an expert on D but Google tells me that it doesn't support automatic deterministic termination. So, if you have a file or a handle open, you need scope(exit) to close it. It also means that the programmer must keep track of all non-memory resources and dispose them "manually" like a C programmer. In C++, RAII makes scope(exit) unnecessary, and catch(...) is the same as scope(failure). Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

06.02.2013 0:40, Emil Dotchevski:
I'm not an expert on D but Google tells me that it doesn't support automatic deterministic termination.
Could you please describe what do you mean?
So, if you have a file or a handle open, you need scope(exit) to close it. It also means that the programmer must keep track of all non-memory resources and dispose them "manually" like a C programmer.
In C++, RAII makes scope(exit) unnecessary,
While scope(exit) is some kind of ad-hoc replacement for RAII wrappers, scope(failure) and scope(success) are not. Nowadays scope(failure) and scope(success) are emulated in C++ via ScopeGuard idiom. For motivating examples check: ScopeGuard: http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/18440375... scope(failure)/scope(success): http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Three-Unlikely-Succ... , http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandre... (ScopeGuard11 part)
and catch(...) is the same as scope(failure).
Compare: scope(failure) { rollback1(); }; do1(); scope(failure) { rollback2(); }; do2(); scope(failure) { rollback3(); }; do3(); with try { do1(); try { do2(); try { do3(); } catch(...) { rollback3(); throw; } } catch(...) { rollback2(); throw; } } catch(...) { rollback1(); throw; } -- Evgeny Panasyuk

On Tue, Feb 5, 2013 at 1:23 PM, Evgeny Panasyuk <evgeny.panasyuk@gmail.com> wrote:
06.02.2013 0:40, Emil Dotchevski:
I'm not an expert on D but Google tells me that it doesn't support automatic deterministic termination.
Could you please describe what do you mean?
I mean that in D/Java/C#/etc you don't know when the destructor will get called automatically, which means that you're stuck with having to manually keep track of all allocated resources exactly like in C, except for memory.
While scope(exit) is some kind of ad-hoc replacement for RAII wrappers, scope(failure) and scope(success) are not. Nowadays scope(failure) and scope(success) are emulated in C++ via ScopeGuard idiom.
Could you clarify what does uncaught_exceptions_count() use look like? How is it different scope guard? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

06.02.2013 2:57, Emil Dotchevski:
I mean that in D/Java/C#/etc you don't know when the destructor will get called automatically, which means that you're stuck with having to manually keep track of all allocated resources exactly like in C, except for memory.
scope(exit) (in C++) has similar behaviour to normal destructors, and in fact it is implemented on top of destructors. scope(failure) and scope(success) differs from scope(exit) only by additional condition - code in scope(failure) is called only when scope is exited by exception, and code in scope(success) is called only during "normal" scope exit. D's documentation says ( http://dlang.org/statement.html#ScopeGuardStatement ) : "The ScopeGuardStatement executes NonEmptyOrScopeBlockStatement at the close of the current scope, rather than at the point where the ScopeGuardStatement appears." Regarding C# and Java: they have some "workarounds" for resource management: C# has "using", and Java has "try-with-resources". Regarding C: there are also approaches to manage resources automatically, but that's another story.
While scope(exit) is some kind of ad-hoc replacement for RAII wrappers, scope(failure) and scope(success) are not. Nowadays scope(failure) and scope(success) are emulated in C++ via ScopeGuard idiom.
Could you clarify what does uncaught_exceptions_count() use look like? How is it different scope guard?
For instance, check first example at Boost.ScopeExit documentation (C++98 syntax): http://www.boost.org/doc/libs/1_53_0/libs/scope_exit/doc/html/index.html void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); } BOOST_SCOPE_EXIT_END // ... commit = true; } Using SCOPE_FAILURE it would became (C++98 syntax): void world::add_person(person const& a_person) { persons_.push_back(a_person); SCOPE_FAILURE(&persons_) { persons_.pop_back(); } SCOPE_FAILURE_END // ... } Also, there are side-by-side examples at https://github.com/panaseleus/stack_unwinding#d-style-scope-guardsactions . -- Evgeny Panasyuk

On Tue, Feb 5, 2013 at 3:25 PM, Evgeny Panasyuk <evgeny.panasyuk@gmail.com> wrote:
06.02.2013 2:57, Emil Dotchevski:
Could you clarify what does uncaught_exceptions_count() use look like? How is it different scope guard?
For instance, check first example at Boost.ScopeExit documentation (C++98 syntax): http://www.boost.org/doc/libs/1_53_0/libs/scope_exit/doc/html/index.html
void world::add_person(person const& a_person) { bool commit = false;
persons_.push_back(a_person); BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); } BOOST_SCOPE_EXIT_END
// ...
commit = true; }
Using SCOPE_FAILURE it would became (C++98 syntax):
void world::add_person(person const& a_person) { persons_.push_back(a_person); SCOPE_FAILURE(&persons_) { persons_.pop_back(); } SCOPE_FAILURE_END
// ... }
I was asking specifically how uncaught_exception_count would be used. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

06.02.2013 4:32, Emil Dotchevski:
I was asking specifically how uncaught_exception_count would be used.
Here is self-contained example of uncaught_exception_count_latch (which is thin wrapper around uncaught_exception_count): http://ideone.com/jCCew0 -- Evgeny Panasyuk

On Tuesday 05 February 2013 16:32:33 Emil Dotchevski wrote:
I was asking specifically how uncaught_exception_count would be used.
I'm using uncaught_exception_count in a few places of Boost.Log to implement guards that do the main work in destructor and only when an exception is not being thrown. For instance, this expression: BOOST_LOG(lg) << foo(); will create a guard object that will collect the result of foo into a stream and emit a log record on destructor if foo doesn't throw.

06.02.2013 16:36, Vicente J. Botet Escriba:
Hi, +1 for both inclusions.
Thank you for interest. 06.02.2013 7:30, Andrey Semashev:
I was asking specifically how uncaught_exception_count would be used.
I'm using uncaught_exception_count in a few places of Boost.Log to implement guards that do the main work in destructor and only when an exception is not being thrown. For instance, this expression:
BOOST_LOG(lg) << foo();
will create a guard object that will collect the result of foo into a stream and emit a log record on destructor if foo doesn't throw.
Thank you, that is interesting example - without uncaught_exception_count it would be not easy to achieve same syntax. However, here is my attempt: http://ideone.com/ynQ2XX . And honestly, if that "for"-based approach would cover all your needs - I would prefer it instead of uncaught_exception_count - because it is more portable. Though uncaught_exception_count still has some good use cases. -- Evgeny Panasyuk

06.02.2013 2:57, Emil Dotchevski:
While scope(exit) is some kind of ad-hoc replacement for RAII wrappers, scope(failure) and scope(success) are not. Nowadays scope(failure) and scope(success) are emulated in C++ via ScopeGuard idiom.
Could you clarify what does uncaught_exceptions_count() use look like? How is it different scope guard?
[skipped]
There is proposal by Herb Sutter for add similar functionality to ISO - std::unwinding_exception http://isocpp.org/blog/2013/03/n3614-unwinding-exception , http://isocpp.org/files/papers/N3614.pdf which is aimed on providing basis for implementation of scope(failure)/scope(success). Emil, could you please clarify what is your position on adding uncaught_exception_count into Boost.Exception? ( https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/un... ) -- Evgeny Panasyuk

Le 05/02/13 20:11, Evgeny Panasyuk a écrit :
Hello All,
<snip>
I think that uncaught_exception_count (and uncaught_exception_count_latch primitive) can be added into Boost.Exception library, at least into "detail" section.
After that scope(failure) and scope(success) features can be implemented in Boost.ScopeExit library. Note, approximately 14 of 16 Boost.ScopeExit examples in manual are in fact emulations of scope(failure)/scope(success). So, looks like in first place Boost.ScopeExit was introduced to simplify emulation of scope(failure) and scope(success) features.
What do you think?
Hi, +1 for both inclusions. If the Boost.Exception and Boost.ScopedExit authors are not for, you could propose them in a new library for review. Best, Vicente

Vicente J. Botet Escriba <vicente.botet <at> wanadoo.fr> writes:
Le 05/02/13 20:11, Evgeny Panasyuk a écrit :
Hello All,
<snip>
I think that uncaught_exception_count (and uncaught_exception_count_latch primitive) can be added into Boost.Exception library, at least into "detail" section.
<snip>
What do you think?
Hi, +1 for both inclusions. If the Boost.Exception and Boost.ScopedExit authors are not for, you could propose them in a new library for review.
Best, Vicente
Hi, I agree. This function looks really useful, and enable a valuable improvement to both libraries. Evan Wallace
participants (5)
-
Andrey Semashev
-
Emil Dotchevski
-
Evan Wallace
-
Evgeny Panasyuk
-
Vicente J. Botet Escriba