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:
@@ -32,7 +32,8 @@ Changes in behaviour which may result in build errors
|
|||||||
|
|
||||||
All:
|
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).
|
- Allow iterating over wxCmdLineParser arguments in order (Armel Asselin).
|
||||||
- Add wxScopedArray ctor taking the number of elements to allocate.
|
- Add wxScopedArray ctor taking the number of elements to allocate.
|
||||||
- Add wxDynamicLibrary::GetModuleFromAddress() (Luca Bacci).
|
- Add wxDynamicLibrary::GetModuleFromAddress() (Luca Bacci).
|
||||||
|
@@ -97,13 +97,16 @@ void TestNewDocument()
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Unfortunately, by default this example does @e not work because an exception
|
Unfortunately, by default this example only works when using a C++11 compiler
|
||||||
can't be safely propagated back to the code handling it in @c TestNewDocument()
|
because the exception can't be safely propagated back to the code handling it
|
||||||
through the system event dispatch functions which are not compatible with C++
|
in @c TestNewDocument() through the system event dispatch functions which are
|
||||||
exceptions. Because of this, you need to override wxApp::StoreCurrentException()
|
not compatible with C++ exceptions and needs to be stored by wxWidgets when it
|
||||||
and wxApp::RethrowStoredException() to help wxWidgets to safely transport the
|
is first caught and rethrown later, when it is safe to do it. And such storing
|
||||||
exception from the event handler that throws it to the @c catch clause. Please
|
and rethrowing of exceptions is only possible in C++11, so while everything
|
||||||
see the documentation of these functions for more details.
|
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
|
@section overview_exceptions_tech Technicalities
|
||||||
|
@@ -306,16 +306,25 @@ public:
|
|||||||
|
|
||||||
// This function can be overridden to store the current exception, in view
|
// This function can be overridden to store the current exception, in view
|
||||||
// of rethrowing it later when RethrowStoredException() is called. If the
|
// of rethrowing it later when RethrowStoredException() is called. If the
|
||||||
// exception was stored, return true. The default implementation returns
|
// exception was stored, return true. If the exception can't be stored,
|
||||||
// false, indicating that the exception wasn't stored and that the program
|
// i.e. if this function returns false, the program will abort after
|
||||||
// should be simply aborted.
|
// 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();
|
virtual bool StoreCurrentException();
|
||||||
|
|
||||||
// If StoreCurrentException() is overridden, this function should be
|
// If StoreCurrentException() is overridden, this function should be
|
||||||
// overridden as well to rethrow the exceptions stored by it when the
|
// 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
|
// control gets back to our code, i.e. when it's safe to do it.
|
||||||
// version does nothing.
|
//
|
||||||
virtual void RethrowStoredException() { }
|
// The default version does nothing when using C++98 and uses
|
||||||
|
// std::rethrow_exception() in C++11.
|
||||||
|
virtual void RethrowStoredException();
|
||||||
#endif // wxUSE_EXCEPTIONS
|
#endif // wxUSE_EXCEPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
@@ -486,6 +486,14 @@ public:
|
|||||||
/**
|
/**
|
||||||
Method to store exceptions not handled by OnExceptionInMainLoop().
|
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
|
This function can be overridden to store the current exception, in view
|
||||||
of rethrowing it later when RethrowStoredException() is called. If the
|
of rethrowing it later when RethrowStoredException() is called. If the
|
||||||
exception was stored, return true. If the exception can't be stored,
|
exception was stored, return true. If the exception can't be stored,
|
||||||
@@ -572,12 +580,18 @@ public:
|
|||||||
/**
|
/**
|
||||||
Method to rethrow exceptions stored by StoreCurrentException().
|
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
|
If StoreCurrentException() is overridden, this function should be
|
||||||
overridden as well to rethrow the exceptions stored by it when the
|
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.
|
control gets back to our code, i.e. when it's safe to do it.
|
||||||
|
|
||||||
See StoreCurrentException() for an example of implementing this method.
|
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
|
@since 3.1.0
|
||||||
*/
|
*/
|
||||||
virtual void RethrowStoredException();
|
virtual void RethrowStoredException();
|
||||||
|
@@ -94,6 +94,10 @@ public:
|
|||||||
// 2nd-level exception handling helpers: if we can't deal with the
|
// 2nd-level exception handling helpers: if we can't deal with the
|
||||||
// exception immediately, we may also store it and rethrow it later, when
|
// exception immediately, we may also store it and rethrow it later, when
|
||||||
// we're back from events processing loop.
|
// 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 bool StoreCurrentException() wxOVERRIDE;
|
||||||
virtual void RethrowStoredException() wxOVERRIDE;
|
virtual void RethrowStoredException() wxOVERRIDE;
|
||||||
|
|
||||||
|
@@ -46,12 +46,28 @@
|
|||||||
#include "wx/tokenzr.h"
|
#include "wx/tokenzr.h"
|
||||||
#include "wx/thread.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 <exception>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#endif
|
#endif
|
||||||
#endif // wxUSE_STL
|
#endif // wxUSE_EXCEPTIONS
|
||||||
|
|
||||||
#if !defined(__WINDOWS__) || defined(__WXMICROWIN__)
|
#if !defined(__WINDOWS__) || defined(__WXMICROWIN__)
|
||||||
#include <signal.h> // for SIGTRAP used by wxTrap()
|
#include <signal.h> // for SIGTRAP used by wxTrap()
|
||||||
@@ -659,11 +675,49 @@ bool wxAppConsoleBase::OnExceptionInMainLoop()
|
|||||||
throw;
|
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()
|
bool wxAppConsoleBase::StoreCurrentException()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxAppConsoleBase::RethrowStoredException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAS_EXCEPTION_PTR/!HAS_EXCEPTION_PTR
|
||||||
|
|
||||||
#endif // wxUSE_EXCEPTIONS
|
#endif // wxUSE_EXCEPTIONS
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user