// Vesely::MFC-TRY/CATCH : listing 2
// replacement for AfxThrow
void AFXAPI CppThrow(CException* pException, BOOL bShared);
class CExceptionMonitor
{
public:
typedef void(*Callback)( BOOL bStartUnwinding);
private:
static int m_nCount;
static Callback m_pfCallback;
BOOL m_bResumed;
friend void AFXAPI CppThrow(CException* pException;
BOOL bShared); // calls here
static void OnThrow(); // just before each throw
public:
CExceptionMonitor() : m_bResumed( FALSE)
{
// there must be one auto object inside each handler's block,
// as done in the macro redefinitions below
ASSERT( m_nCount > 0);
}
~CExceptionMonitor();
void Resume();
static BOOL Unwinding() { ASSERT( m_nCount >= 0); return m_nCount; }
static Callback HookOnThrow( Callback newCallback);
};
#if defined( _DEBUG)
class CDebugException : public CException
// only CATCH_ALL/END_CATCH_ALL get this:
// CATCH( CDebugException, e) => compile error in retail build
{
DECLARE_DYNAMIC( CDebugException)
public:
CDebugException();
};
// this intermittently throws the relevant exception
void ThrowPointTest( CRuntimeClass *pE, LPCSTR lpszFileName, int nline);
#define EXCEPTIONS_CAN_BE_THROWN(e) \
ThrowPointTest( RUNTIME_CLASS( e), THIS_FILE, __LINE__)
#else
#define EXCEPTIONS_CAN_BE_THROWN(e) ((void)0)
#endif // _DEBUG
#under TRY
#define TRY { AFX_EXCEPTION_LINK _afxExceptionLink; \
try { EXCEPTIONS_CAN_BE_THROWN( CDebugException); {
#undef CATCH
// CATCH can only be the first handler in the list:
// in the (rare) case of a handler list with more than one
// meaningful selective handler, EXCEPTIONS_CAN_BE_THROWN
// needs to be coded explicitely.
#define CATCH(class, e) EXCEPTIONS_CAN_BE_THROWN( class); } \
} catch (class* e) \
{ ASSERT( e->IsKindOf(RUNTIME_CLASS(class))); \
ASSERT( _afxExceptionLink.m_pException == e); \
CExceptionMonitor ExceptionMonitor;
#undef AND_CATCH
#define AND_CATCH(class, e) } catch (class* e) \
{ ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \
ASSERT( _afxExceptionLink.m_PException == e); \
CExceptionMonitor ExceptionMonitor;
#undef END_CATCH
#define END_CATCH } catch (CException* e) \
{ ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
ASSERT( _afxExceptionLink.m_pException == e); \
CExceptionMonitor ExceptionMonitor; \
CppThrow( 0, FALSE); } }
#undef THROW
#define THROW(e) CppThrow( e, FALSE)
#undef THROW_LAST
#define THROW_LAST() CppThrow( 0, FALSE)
// end of listing 2
// End of File