Provide wxApp::StoreCurrentException() implementation for C++11.
When using C++11 we can provide implementations of wxApp::StoreCurrentException() and RethrowStoredException() ourselves and thus make catching exceptions outside of the event loop work by default. Do this and update the documentation and the sample to reflect it. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@77470 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
73aea138c6
commit
3bcec846a0
@ -32,7 +32,8 @@ Changes in behaviour which may result in build errors
|
||||
|
||||
All:
|
||||
|
||||
- Add wxApp::StoreCurrentException() and RethrowStoredException().
|
||||
- Add wxApp::StoreCurrentException() and RethrowStoredException() and implement
|
||||
their functionality by default when using C++11 compiler.
|
||||
- Allow iterating over wxCmdLineParser arguments in order (Armel Asselin).
|
||||
- Add wxScopedArray ctor taking the number of elements to allocate.
|
||||
- Add wxDynamicLibrary::GetModuleFromAddress() (Luca Bacci).
|
||||
|
@ -97,13 +97,16 @@ void TestNewDocument()
|
||||
}
|
||||
@endcode
|
||||
|
||||
Unfortunately, by default this example does @e not work because an exception
|
||||
can't be safely propagated back to the code handling it in @c TestNewDocument()
|
||||
through the system event dispatch functions which are not compatible with C++
|
||||
exceptions. Because of this, you need to override wxApp::StoreCurrentException()
|
||||
and wxApp::RethrowStoredException() to help wxWidgets to safely transport the
|
||||
exception from the event handler that throws it to the @c catch clause. Please
|
||||
see the documentation of these functions for more details.
|
||||
Unfortunately, by default this example only works when using a C++11 compiler
|
||||
because the exception can't be safely propagated back to the code handling it
|
||||
in @c TestNewDocument() through the system event dispatch functions which are
|
||||
not compatible with C++ exceptions and needs to be stored by wxWidgets when it
|
||||
is first caught and rethrown later, when it is safe to do it. And such storing
|
||||
and rethrowing of exceptions is only possible in C++11, so while everything
|
||||
just works if you do use C++11, there is an extra step if you are using C++98:
|
||||
In this case you need to override wxApp::StoreCurrentException() and
|
||||
wxApp::RethrowStoredException() to help wxWidgets to do this, please see the
|
||||
documentation of these functions for more details.
|
||||
|
||||
|
||||
@section overview_exceptions_tech Technicalities
|
||||
|
@ -306,16 +306,25 @@ public:
|
||||
|
||||
// This function can be overridden to store the current exception, in view
|
||||
// of rethrowing it later when RethrowStoredException() is called. If the
|
||||
// exception was stored, return true. The default implementation returns
|
||||
// false, indicating that the exception wasn't stored and that the program
|
||||
// should be simply aborted.
|
||||
// exception was stored, return true. If the exception can't be stored,
|
||||
// i.e. if this function returns false, the program will abort after
|
||||
// calling OnUnhandledException().
|
||||
//
|
||||
// The default implementation of this function when using C++98 compiler
|
||||
// just returns false, as there is no generic way to store an arbitrary
|
||||
// exception in C++98 and each application must do it on its own for the
|
||||
// exceptions it uses in its overridden version. When using C++11, the
|
||||
// default implementation uses std::current_exception() and returns true,
|
||||
// so it's normally not necessary to override this method when using C++11.
|
||||
virtual bool StoreCurrentException();
|
||||
|
||||
// If StoreCurrentException() is overridden, this function should be
|
||||
// overridden as well to rethrow the exceptions stored by it when the
|
||||
// control gets back to our code, i.e. when it's safe to do it. The default
|
||||
// version does nothing.
|
||||
virtual void RethrowStoredException() { }
|
||||
// control gets back to our code, i.e. when it's safe to do it.
|
||||
//
|
||||
// The default version does nothing when using C++98 and uses
|
||||
// std::rethrow_exception() in C++11.
|
||||
virtual void RethrowStoredException();
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
|
||||
|
||||
|
@ -486,6 +486,14 @@ public:
|
||||
/**
|
||||
Method to store exceptions not handled by OnExceptionInMainLoop().
|
||||
|
||||
@note The default implementation of this function when using C++98
|
||||
compiler just returns false, as there is no generic way to store an
|
||||
arbitrary exception in C++98 and each application must do it on its
|
||||
own for the exceptions it uses in its overridden version. When
|
||||
using C++11, the default implementation uses
|
||||
std::current_exception() and returns true, so it's normally not
|
||||
necessary to override this method when using C++11.
|
||||
|
||||
This function can be overridden to store the current exception, in view
|
||||
of rethrowing it later when RethrowStoredException() is called. If the
|
||||
exception was stored, return true. If the exception can't be stored,
|
||||
@ -572,12 +580,18 @@ public:
|
||||
/**
|
||||
Method to rethrow exceptions stored by StoreCurrentException().
|
||||
|
||||
@note Just as with StoreCurrentException(), it is usually not necessary
|
||||
to override this method when using C++11.
|
||||
|
||||
If StoreCurrentException() is overridden, this function should be
|
||||
overridden as well to rethrow the exceptions stored by it when the
|
||||
control gets back to our code, i.e. when it's safe to do it.
|
||||
|
||||
See StoreCurrentException() for an example of implementing this method.
|
||||
|
||||
The default version does nothing when using C++98 and uses
|
||||
std::rethrow_exception() in C++11.
|
||||
|
||||
@since 3.1.0
|
||||
*/
|
||||
virtual void RethrowStoredException();
|
||||
|
@ -94,6 +94,10 @@ public:
|
||||
// 2nd-level exception handling helpers: if we can't deal with the
|
||||
// exception immediately, we may also store it and rethrow it later, when
|
||||
// we're back from events processing loop.
|
||||
//
|
||||
// Notice that overriding these methods is not necessary when using C++11
|
||||
// as they have a perfectly serviceable implementation inside the library
|
||||
// itself in this case.
|
||||
virtual bool StoreCurrentException() wxOVERRIDE;
|
||||
virtual void RethrowStoredException() wxOVERRIDE;
|
||||
|
||||
|
@ -46,12 +46,28 @@
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/thread.h"
|
||||
|
||||
#if wxUSE_STL
|
||||
#if wxUSE_EXCEPTIONS
|
||||
#if wxUSE_EXCEPTIONS
|
||||
// Do we have a C++ compiler with enough C++11 support for
|
||||
// std::exception_ptr and functions working with it?
|
||||
#if __cplusplus >= 201103L
|
||||
// Any conforming C++11 compiler should have it.
|
||||
#define HAS_EXCEPTION_PTR
|
||||
#elif wxCHECK_VISUALC_VERSION(10)
|
||||
// VC++ supports it since version 10, even though it doesn't define
|
||||
// __cplusplus to C++11 value.
|
||||
#define HAS_EXCEPTION_PTR
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EXCEPTION_PTR
|
||||
#include <exception> // for std::current_exception()
|
||||
#include <utility> // for std::swap()
|
||||
#endif
|
||||
|
||||
#if wxUSE_STL
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
#endif // wxUSE_STL
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
|
||||
#if !defined(__WINDOWS__) || defined(__WXMICROWIN__)
|
||||
#include <signal.h> // for SIGTRAP used by wxTrap()
|
||||
@ -659,11 +675,49 @@ bool wxAppConsoleBase::OnExceptionInMainLoop()
|
||||
throw;
|
||||
}
|
||||
|
||||
#ifdef HAS_EXCEPTION_PTR
|
||||
static std::exception_ptr gs_storedException;
|
||||
|
||||
bool wxAppConsoleBase::StoreCurrentException()
|
||||
{
|
||||
if ( gs_storedException )
|
||||
{
|
||||
// We can't store more than one exception currently: while we could
|
||||
// support this by just using a vector<exception_ptr>, it shouldn't be
|
||||
// actually necessary because we should never have more than one active
|
||||
// exception anyhow.
|
||||
return false;
|
||||
}
|
||||
|
||||
gs_storedException = std::current_exception();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::RethrowStoredException()
|
||||
{
|
||||
if ( gs_storedException )
|
||||
{
|
||||
std::exception_ptr storedException;
|
||||
std::swap(storedException, gs_storedException);
|
||||
|
||||
std::rethrow_exception(storedException);
|
||||
}
|
||||
}
|
||||
|
||||
#else // !HAS_EXCEPTION_PTR
|
||||
|
||||
bool wxAppConsoleBase::StoreCurrentException()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::RethrowStoredException()
|
||||
{
|
||||
}
|
||||
|
||||
#endif // HAS_EXCEPTION_PTR/!HAS_EXCEPTION_PTR
|
||||
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user