Now I've finished my "C++ multithreading" tutorial and opened a
discussion in comp.programming.threads:
Message-ID: <4899c3e1$0$90276$1472...@news.sunsite.dk>
http://groups.google.com/group/comp.programming.threads/msg/b52ce202a371778b
But there exist some points that deserve C++ specific attention. And one
of these points is "exceptions being thrown as smart pointers to actual
exception objects".
In particular, the object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;
See http://ders.stml.net/cpp/mtprog/doc/exception_8hpp-source.html for
the details.
There also can be nested exceptions and used like this:
void f(mem_pool& mp, int i)
{
shException exc(mp, 0);
try {
g(mp, i);
return;
}
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }
catch (...) { exc=recatchException(mp, _FLINE_); } // recatch!
throw newException(_FLINE_, "Problems in f()", exc); // use as nested!
}
That is we recatch an exception and use it as a nested. The output can
look like this:
-----------------------------------8<-----------------------------------
Exception #1:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ExampleException [..\tst_exc.cpp:136], message: Hello from g()
Exception #2:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ders::StdExternException [..\tst_exc.cpp:154],
typeName="St12out_of_range", message: vector::_M_range_check
Exception #3:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ders::UnknExternException [..\tst_exc.cpp:154], typeName="unknown",
message: Unknown exception
Exception #4:
ders::UnknExternException [..\tst_exc.cpp:110], typeName="unknown",
message: Unknown exception
Non-empty exit message
-----------------------------------8<-----------------------------------
The sources are available here: http://ders.stml.net/cpp/mtprog/code.zip
So you can compile mtprog\derslib\tst\tst_exc.cpp yourself and se what's
going on.
Function recatchException() is defined as
shException recatchException(mem_pool& mp, const FileLine& location)
{
try { throw; }
catch (shException she) {
return she;
}
catch (const std::exception& se) {
return newStdExternException(mp, location, se.what(),
typeid(se).name());
}
catch (...) {
return newUnknExternException(mp, location, "Unknown exception");
}
}
And you can browse the documentation to quickly get the remaining
details: http://ders.stml.net/cpp/mtprog/doc/exception_8cpp-source.html
--
With all respect, Sergey. http://ders.stml.net/
mailto : ders at skeptik.net
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
> catch (shException she) { if (she->is<MsgException>()) throw; else
> exc=she; }
catch(const MsgException e) { throw; }
--
I thought I had put a & there.
Sorry.
The object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;
There is no bare MsgException. Only a sh_ptr<Exception> which
contains MsgException object so you can't catch(const MsgException e).
--
With all respect, Sergey. http://ders.stml.net/
mailto : ders at skeptik.net
--
Yes. The problem is that throwing smart pointers is stupid.
Throw objects so that you can use the type identification mechanism of
catch-blocks. It's really ridiculous to catch some type and re-
identify it with if-else thingies.
The good way to use exceptions is to throw by value and catch by const-
reference.
That was already established decades ago.
void f(mem_pool& mp, /* ... */)
{
try {
g(mp, i);
// ...
return;
}
catch (...) {
throw newException(_FLINE_, "Problems in f()",
recatchException(mp, _FLINE_));
}
}
void g(mem_pool& mp, /* ... */)
{
try {
h(mp, i);
// ...
return;
}
catch (...) {
throw newException(_FLINE_, "Problems in g()",
recatchException(mp, _FLINE_));
}
}
shException recatchException(mem_pool& mp, const FileLine& location)
{
try { throw; }
catch (shException she) {
return she;
}
catch (const std::exception& se) {
return newStdExternException(mp, location, se.what(),
typeid(se).name());
}
catch (...) {
return newUnknExternException(mp, location, "Unknown exception");
}
}
> The good way to use exceptions is to throw by value and catch by const-
> reference.
> That was already established decades ago.
>
Believe or not, but C++ still evolves.
--
With all respect, Sergey. http://ders.stml.net/
mailto : ders at skeptik.net
--
> But there exist some points that deserve C++ specific attention. And one
> of these points is "exceptions being thrown as smart pointers to actual
> exception objects".
This is an interesting technique. It might be interesting to note that
it has been discovered independently (the paper by Alisdair Meredith
credits Bronek Kozicki and the BSI panel):
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2509.html
The variation in the paper avoids the need to throw smart pointers by
taking advantage of a new C++0x feature that allows one to obtain a
smart pointer to the currently active exception:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html
I, personally, would have preferred the N2509 functionality to go
directly into std::exception, but this would have raised ABI
compatibility issues.
> I, personally, would have preferred the N2509 functionality to go
> directly into std::exception, but this would have raised ABI
> compatibility issues.
>
But my code works right now. It was published in 2004, to be exact.
Also there is some problem with certain compilers (can be checked with
mtprog\derslib\tst\tst_exc.cpp). The point is that a correct compiler
needs only one catch(...) block:
void f(mem_pool& mp, /* ... */)
{
try {
g(mp, i);
// ...
return;
}
catch (...) {
throw newException(_FLINE_, "Problems in f()",
recatchException(mp, _FLINE_));
}
}
But other compilers crash with this code and require one more catch:
void f(mem_pool& mp, /* ... */)
{
shException exc(mp, 0);
try {
g(mp, i);
// ...
return;
}
catch (shException she) { exc=she; }
catch (...) { exc=recatchException(mp, _FLINE_); }
throw newException(_FLINE_, "Problems in f()", exc);
}
P.S.
The code: http://ders.stml.net/cpp/mtprog/code.zip
The doxygen: http://ders.stml.net/cpp/mtprog/doc/index.html
--
With all respect, Sergey. http://ders.stml.net/
mailto : ders at skeptik.net
--