On 15 Sep 2013 at 18:25, Eric Niebler wrote:
Sorry, my unclear phrasing again ... by wrapping destructors I specifically meant:
destructor::~destructor() { try { ... } catch(...) { /* do something useful */ } }
Can you elaborate on what "something useful" is in this context?
Sure. A bit more than a decade ago I took two years out to implement a next-gen software platform. It conceptualised GUI components as a distributed, adhoc, semantically generated graph of data stream processors, so think of something like Boost.iostreams spread out over disparate compute units and whose relationships were described by a triplestore, and you've got a good idea (if it sounds like Plan 9, you're not wrong). One of the big problems in the client-server relationship was exception propagation. If I ask for an instantiation of an editing processor for a Word file, and I am not on a Microsoft Windows machine, the framework automatically found a nearby machine with the requisite Word COM objects and simply plugged together the needed bits code from the semantic graph database. If the Word COM object threw a COM exception, that got converted into a C++ exception and propagated over the asynchronous RPC channel such that it pops out locally. Because it's asynchronous, it pops out only at certain points i.e. when you next talk to the relevent item (Boost.AFIO does exactly the same BTW). The problem is what happens when exceptions cascade. In the above situation, an exception from COM could cause a chain of bits of intermediate processing to also throw exceptions, and they had a nasty habit of "popping out" via propagation during object destruction as often client code hadn't done anything in between to otherwise retrieve the asynchronous exception state. In this situation, we really *want* exception throws during object destruction to NOT call std::terminate() because no unsafe and ill defined program state has occurred. And hence the solution I mentioned earlier which was a script to add try...catch to all destructors, and if an exception was already in flight, it appended the new exception to the existing one as a nested exception and it retried the destructor. Later on, my additions to the C++ runtime would spot the situation and figure out if the nested exception throws created indeterminate program state - in which case now we fatal exit - or if the destructor retry was successful, and the party can continue. Most would say a better solution would have been the make the throwing destructors private and force people to use a virtual Destroy() function. On the hand, that's not very C++-ish, and my solution did work very nicely so long as you didn't mess up retryable destructors. I also hooked management of the Python GIL into the same framework, so one could traverse between C++ and Python and back into C++ and so on. It worked well. Lots more info on nested exception handling at http://tnfox.sourceforge.net/TnFOX-svn/html/class_f_x_1_1_f_x_exceptio n.html for those really interested. Niall -- Currently unemployed and looking for work. Work Portfolio: http://careers.stackoverflow.com/nialldouglas/