summaryrefslogtreecommitdiff
path: root/pjlib
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2005-11-21 16:57:02 +0000
committerBenny Prijono <bennylp@teluu.com>2005-11-21 16:57:02 +0000
commit5d8ed312c380f76e442ca170f0f791273c914bfa (patch)
tree552b3ccb4a8bb0b9144fac237822a147c6d48a24 /pjlib
parent54349030a3b401a96f1dc24dd351fe19110ddbb9 (diff)
Changed syntax to support Windows SEH
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@68 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib')
-rw-r--r--pjlib/include/pj/except.h83
-rw-r--r--pjlib/src/pj/except.c2
-rw-r--r--pjlib/src/pjlib-samples/except.c6
-rw-r--r--pjlib/src/pjlib-test/exception.c52
4 files changed, 95 insertions, 48 deletions
diff --git a/pjlib/include/pj/except.h b/pjlib/include/pj/except.h
index 301242a4..a96d5423 100644
--- a/pjlib/include/pj/except.h
+++ b/pjlib/include/pj/except.h
@@ -45,12 +45,12 @@ PJ_BEGIN_DECL
* \section pj_except_except Exception Handling
*
* This module provides exception handling syntactically similar to C++ in
- * C language. The underlying mechanism use setjmp() and longjmp(), and since
- * these constructs are ANSI standard, the mechanism here should be available
- * on most platforms/compilers which are ANSI compliant.
+ * C language. In Win32 systems, it uses Windows Structured Exception
+ * Handling (SEH) if macro PJ_EXCEPTION_USE_WIN32_SEH is non-zero.
+ * Otherwise it will use setjmp() and longjmp().
*
- * If ANSI libc is not available, then setjmp()/longjmp() implementation will
- * be provided. See <pj/compat/setjmp.h> for compatibility.
+ * On some platforms where setjmp/longjmp is not available, setjmp/longjmp
+ * implementation is provided. See <pj/compat/setjmp.h> for compatibility.
*
* The exception handling mechanism is completely thread safe, so the exception
* thrown by one thread will not interfere with other thread.
@@ -61,7 +61,9 @@ PJ_BEGIN_DECL
* hold some resorce such as pool or mutex etc.
* - You CAN NOT make nested exception in one single function without using
* a nested PJ_USE_EXCEPTION.
- * - Exceptions will always be caught by the first handle (unlike C++ where
+ * - You can not provide more than PJ_CATCH or PJ_CATCH_ANY nor use PJ_CATCH
+ * and PJ_CATCH_ANY for a single PJ_TRY.
+ * - Exceptions will always be caught by the first handler (unlike C++ where
* exception is only caught if the type matches.
*
* The exception handling constructs are similar to C++. The blocks will be
@@ -71,7 +73,7 @@ PJ_BEGIN_DECL
#define NO_MEMORY 1
#define SYNTAX_ERROR 2
- int main()
+ int sample1()
{
PJ_USE_EXCEPTION; // declare local exception stack.
@@ -81,11 +83,21 @@ PJ_BEGIN_DECL
PJ_CATCH(NO_MEMORY) {
... // handle exception 1
}
- PJ_CATCH(SYNTAX_ERROR) {
- ... // handle exception 2
+ PJ_END;
+ }
+
+ int sample2()
+ {
+ PJ_USE_EXCEPTION; // declare local exception stack.
+
+ PJ_TRY {
+ ...// do something..
}
- PJ_DEFAULT {
- ... // handle other exceptions.
+ PJ_CATCH_ANY {
+ if (PJ_GET_EXCEPTION() == NO_MEMORY)
+ ...; // handle no memory situation
+ else if (PJ_GET_EXCEPTION() == SYNTAX_ERROR)
+ ...; // handle syntax error
}
PJ_END;
}
@@ -126,6 +138,8 @@ PJ_BEGIN_DECL
* block.
* Actually, this is just a macro to declare local variable which is used to
* push the exception state to the exception stack.
+ * Note: you must specify PJ_USE_EXCEPTION as the last statement in the
+ * local variable declarations, since it may evaluate to nothing.
*
* \subsection PJ_TRY PJ_TRY
* The \a PJ_TRY keyword is typically followed by a block. If an exception is
@@ -137,18 +151,16 @@ PJ_BEGIN_DECL
* if the exception being thrown is equal to the expression specified in the
* \a PJ_CATCH.
*
- * \subsection PJ_DEFAULT PJ_DEFAULT
- * The \a PJ_DEFAULT keyword is normally followed by a block. This block will
- * be executed if the exception being thrown doesn't match any of the \a
- * PJ_CATCH specification. The \a PJ_DEFAULT block \b MUST be placed as the
- * last block of the handlers.
+ * \subsection PJ_CATCH_ANY PJ_CATCH_ANY
+ * The \a PJ_CATCH is normally followed by a block. This block will be executed
+ * if any exception was raised in the TRY block.
*
* \subsection PJ_END PJ_END
* Specify this keyword to mark the end of \a PJ_TRY / \a PJ_CATCH blocks.
*
* \subsection PJ_GET_EXCEPTION PJ_GET_EXCEPTION(void)
* Get the last exception thrown. This macro is normally called inside the
- * \a PJ_CATCH or \a PJ_DEFAULT block, altough it can be used anywhere where
+ * \a PJ_CATCH or \a PJ_CATCH_ANY block, altough it can be used anywhere where
* the \a PJ_USE_EXCEPTION definition is in scope.
*
*
@@ -200,6 +212,38 @@ PJ_DECL(const char*) pj_exception_id_name(pj_exception_id_t id);
/** @} */
+#if defined(PJ_EXCEPTION_USE_WIN32_SEH) && PJ_EXCEPTION_USE_WIN32_SEH != 0
+/*****************************************************************************
+ **
+ ** IMPLEMENTATION OF EXCEPTION USING WINDOWS SEH
+ **
+ ****************************************************************************/
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+PJ_IDECL_NO_RETURN(void)
+pj_throw_exception_(pj_exception_id_t id) PJ_ATTR_NORETURN
+{
+ RaiseException(id,1,0,NULL);
+}
+
+#define PJ_USE_EXCEPTION
+#define PJ_TRY __try
+#define PJ_CATCH(id) __except(GetExceptionCode()==id ? \
+ EXCEPTION_EXECUTE_HANDLER : \
+ EXCEPTION_CONTINUE_SEARCH)
+#define PJ_CATCH_ANY __except(EXCEPTION_EXECUTE_HANDLER)
+#define PJ_END
+#define PJ_THROW(id) pj_throw_exception_(id)
+#define PJ_GET_EXCEPTION() GetExceptionCode()
+
+#else
+/*****************************************************************************
+ **
+ ** IMPLEMENTATION OF EXCEPTION USING GENERIC SETJMP/LONGJMP
+ **
+ ****************************************************************************/
+
/**
* This structure (which should be invisible to user) manages the TRY handler
* stack.
@@ -252,7 +296,7 @@ PJ_DECL(void) pj_pop_exception_handler_(void);
* Catch any exception number.
* @hideinitializer
*/
-#define PJ_DEFAULT else
+#define PJ_CATCH_ANY else
/**
* End of exception specification block.
@@ -275,6 +319,9 @@ PJ_DECL(void) pj_pop_exception_handler_(void);
*/
#define PJ_GET_EXCEPTION() (pj_x_code__)
+#endif /* PJ_EXCEPTION_USE_WIN32_SEH */
+
+
PJ_END_DECL
diff --git a/pjlib/src/pj/except.c b/pjlib/src/pj/except.c
index ceaaad16..0a9f32ab 100644
--- a/pjlib/src/pj/except.c
+++ b/pjlib/src/pj/except.c
@@ -35,6 +35,7 @@ static long thread_local_id = -1;
#endif /* PJ_HAS_EXCEPTION_NAMES */
+#if !defined(PJ_EXCEPTION_USE_WIN32_SEH) || PJ_EXCEPTION_USE_WIN32_SEH==0
PJ_DEF(void) pj_throw_exception_(int exception_id)
{
struct pj_exception_state_t *handler;
@@ -69,6 +70,7 @@ PJ_DEF(void) pj_pop_exception_handler_(void)
pj_assert(handler != NULL);
pj_thread_local_set(thread_local_id, handler->prev);
}
+#endif
#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
diff --git a/pjlib/src/pjlib-samples/except.c b/pjlib/src/pjlib-samples/except.c
index 3bbfa544..5a319403 100644
--- a/pjlib/src/pjlib-samples/except.c
+++ b/pjlib/src/pjlib-samples/except.c
@@ -54,11 +54,7 @@ static int test_exception()
free(data);
randomly_throw_exception();
}
- PJ_CATCH( NO_MEMORY ) {
- puts("Can't allocate memory");
- return 0;
- }
- PJ_DEFAULT {
+ PJ_CATCH_ANY {
pj_exception_id_t x_id;
x_id = PJ_GET_EXCEPTION();
diff --git a/pjlib/src/pjlib-test/exception.c b/pjlib/src/pjlib-test/exception.c
index ef4bf4a2..5e9ef2b6 100644
--- a/pjlib/src/pjlib-test/exception.c
+++ b/pjlib/src/pjlib-test/exception.c
@@ -65,8 +65,8 @@ static int throw_id_2(void)
static int test(void)
{
- PJ_USE_EXCEPTION;
int rc = 0;
+ PJ_USE_EXCEPTION;
/*
* No exception situation.
@@ -74,10 +74,7 @@ static int test(void)
PJ_TRY {
rc = rc;
}
- PJ_CATCH( ID_1 ) {
- rc = -2;
- }
- PJ_DEFAULT {
+ PJ_CATCH_ANY {
rc = -3;
}
PJ_END;
@@ -95,14 +92,13 @@ static int test(void)
// should not reach here.
rc = -10;
}
- PJ_CATCH( ID_1 ) {
- if (!rc) rc = 0;
- }
- PJ_DEFAULT {
+ PJ_CATCH_ANY {
int id = PJ_GET_EXCEPTION();
- PJ_LOG(3,("", "...error: got unexpected exception %d (%s)",
- id, pj_exception_id_name(id)));
- if (!rc) rc = -20;
+ if (id != ID_1) {
+ PJ_LOG(3,("", "...error: got unexpected exception %d (%s)",
+ id, pj_exception_id_name(id)));
+ if (!rc) rc = -20;
+ }
}
PJ_END;
@@ -117,14 +113,16 @@ static int test(void)
// should not reach here.
rc = -25;
}
- PJ_CATCH( ID_1 ) {
- if (!rc) rc = -30;
- }
- PJ_CATCH( ID_2 ) {
- if (!rc) rc = 0;
- }
- PJ_DEFAULT {
- if (!rc) rc = -40;
+ PJ_CATCH_ANY {
+ switch (PJ_GET_EXCEPTION()) {
+ case ID_1:
+ if (!rc) rc = -30; break;
+ case ID_2:
+ if (!rc) rc = 0; break;
+ default:
+ if (!rc) rc = -40;
+ break;
+ }
}
PJ_END;
@@ -139,11 +137,15 @@ static int test(void)
// should not reach here
rc = -50;
}
- PJ_CATCH( ID_2 ) {
- if (!rc) rc = -60;
- }
- PJ_DEFAULT {
- if (!rc) rc = 0;
+ PJ_CATCH_ANY {
+ switch (PJ_GET_EXCEPTION()) {
+ case ID_1:
+ if (!rc) rc = 0;
+ break;
+ default:
+ if (!rc) rc = -60;
+ break;
+ }
}
PJ_END;