提交 a6b327fb 编写于 作者: S Shengliang Guan

exception

上级 0fae01c9
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _TD_UTIL_EXCEPTION_H #ifndef _TD_UTIL_EXCEPTION_H_
#define _TD_UTIL_EXCEPTION_H #define _TD_UTIL_EXCEPTION_H_
#include "os.h" #include "os.h"
...@@ -26,100 +26,106 @@ extern "C" { ...@@ -26,100 +26,106 @@ extern "C" {
* cleanup actions * cleanup actions
*/ */
typedef struct SCleanupAction { typedef struct SCleanupAction {
bool failOnly; bool failOnly;
uint8_t wrapper; uint8_t wrapper;
uint16_t reserved; uint16_t reserved;
void* func; void* func;
union { union {
void* Ptr; void* Ptr;
bool Bool; bool Bool;
char Char; char Char;
int8_t Int8; int8_t Int8;
uint8_t Uint8; uint8_t Uint8;
int16_t Int16; int16_t Int16;
uint16_t Uint16; uint16_t Uint16;
int Int; int Int;
unsigned int Uint; unsigned int Uint;
int32_t Int32; int32_t Int32;
uint32_t Uint32; uint32_t Uint32;
int64_t Int64; int64_t Int64;
uint64_t Uint64; uint64_t Uint64;
float Float; float Float;
double Double; double Double;
} arg1, arg2; } arg1, arg2;
} SCleanupAction; } SCleanupAction;
/* /*
* exception hander registration * exception hander registration
*/ */
typedef struct SExceptionNode { typedef struct SExceptionNode {
struct SExceptionNode* prev; struct SExceptionNode* prev;
jmp_buf jb; jmp_buf jb;
int32_t code; int32_t code;
int32_t maxCleanupAction; int32_t maxCleanupAction;
int32_t numCleanupAction; int32_t numCleanupAction;
SCleanupAction* cleanupActions; SCleanupAction* cleanupActions;
} SExceptionNode; } SExceptionNode;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// functions & macros for auto-cleanup // functions & macros for auto-cleanup
void cleanupPush_void_ptr_ptr ( bool failOnly, void* func, void* arg1, void* arg2 ); void cleanupPush_void_ptr_ptr(bool failOnly, void* func, void* arg1, void* arg2);
void cleanupPush_void_ptr_bool ( bool failOnly, void* func, void* arg1, bool arg2 ); void cleanupPush_void_ptr_bool(bool failOnly, void* func, void* arg1, bool arg2);
void cleanupPush_void_ptr ( bool failOnly, void* func, void* arg ); void cleanupPush_void_ptr(bool failOnly, void* func, void* arg);
void cleanupPush_int_int ( bool failOnly, void* func, int arg ); void cleanupPush_int_int(bool failOnly, void* func, int arg);
void cleanupPush_void ( bool failOnly, void* func ); void cleanupPush_void(bool failOnly, void* func);
void cleanupPush_int_ptr ( bool failOnly, void* func, void* arg ); void cleanupPush_int_ptr(bool failOnly, void* func, void* arg);
int32_t cleanupGetActionCount(); int32_t cleanupGetActionCount();
void cleanupExecuteTo( int32_t anchor, bool failed ); void cleanupExecuteTo(int32_t anchor, bool failed);
void cleanupExecute( SExceptionNode* node, bool failed ); void cleanupExecute(SExceptionNode* node, bool failed);
bool cleanupExceedLimit(); bool cleanupExceedLimit();
#define CLEANUP_PUSH_VOID_PTR_PTR( failOnly, func, arg1, arg2 ) cleanupPush_void_ptr_ptr( (failOnly), (void*)(func), (void*)(arg1), (void*)(arg2) ) #define CLEANUP_PUSH_VOID_PTR_PTR(failOnly, func, arg1, arg2) \
#define CLEANUP_PUSH_VOID_PTR_BOOL( failOnly, func, arg1, arg2 ) cleanupPush_void_ptr_bool( (failOnly), (void*)(func), (void*)(arg1), (bool)(arg2) ) cleanupPush_void_ptr_ptr((failOnly), (void*)(func), (void*)(arg1), (void*)(arg2))
#define CLEANUP_PUSH_VOID_PTR( failOnly, func, arg ) cleanupPush_void_ptr( (failOnly), (void*)(func), (void*)(arg) ) #define CLEANUP_PUSH_VOID_PTR_BOOL(failOnly, func, arg1, arg2) \
#define CLEANUP_PUSH_INT_INT( failOnly, func, arg ) cleanupPush_void_ptr( (failOnly), (void*)(func), (int)(arg) ) cleanupPush_void_ptr_bool((failOnly), (void*)(func), (void*)(arg1), (bool)(arg2))
#define CLEANUP_PUSH_VOID( failOnly, func ) cleanupPush_void( (failOnly), (void*)(func) ) #define CLEANUP_PUSH_VOID_PTR(failOnly, func, arg) cleanupPush_void_ptr((failOnly), (void*)(func), (void*)(arg))
#define CLEANUP_PUSH_INT_PTR( failOnly, func, arg ) cleanupPush_int_ptr( (failOnly), (void*)(func), (void*)(arg) ) #define CLEANUP_PUSH_INT_INT(failOnly, func, arg) cleanupPush_void_ptr((failOnly), (void*)(func), (int)(arg))
#define CLEANUP_PUSH_FREE( failOnly, arg ) cleanupPush_void_ptr( (failOnly), free, (void*)(arg) ) #define CLEANUP_PUSH_VOID(failOnly, func) cleanupPush_void((failOnly), (void*)(func))
#define CLEANUP_PUSH_CLOSE( failOnly, arg ) cleanupPush_int_int( (failOnly), close, (int)(arg) ) #define CLEANUP_PUSH_INT_PTR(failOnly, func, arg) cleanupPush_int_ptr((failOnly), (void*)(func), (void*)(arg))
#define CLEANUP_PUSH_FCLOSE( failOnly, arg ) cleanupPush_int_ptr( (failOnly), fclose, (void*)(arg) ) #define CLEANUP_PUSH_FREE(failOnly, arg) cleanupPush_void_ptr((failOnly), free, (void*)(arg))
#define CLEANUP_PUSH_CLOSE(failOnly, arg) cleanupPush_int_int((failOnly), close, (int)(arg))
#define CLEANUP_GET_ANCHOR() cleanupGetActionCount() #define CLEANUP_PUSH_FCLOSE(failOnly, arg) cleanupPush_int_ptr((failOnly), fclose, (void*)(arg))
#define CLEANUP_EXECUTE_TO( anchor, failed ) cleanupExecuteTo( (anchor), (failed) )
#define CLEANUP_EXCEED_LIMIT() cleanupExceedLimit() #define CLEANUP_GET_ANCHOR() cleanupGetActionCount()
#define CLEANUP_EXECUTE_TO(anchor, failed) cleanupExecuteTo((anchor), (failed))
#define CLEANUP_EXCEED_LIMIT() cleanupExceedLimit()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// functions & macros for exception handling // functions & macros for exception handling
void exceptionPushNode( SExceptionNode* node ); void exceptionPushNode(SExceptionNode* node);
int32_t exceptionPopNode(); int32_t exceptionPopNode();
void exceptionThrow( int32_t code ); void exceptionThrow(int32_t code);
#define TRY(maxCleanupActions) do { \ #define TRY(maxCleanupActions) \
SExceptionNode exceptionNode = { 0 }; \ do { \
SCleanupAction cleanupActions[(maxCleanupActions) > 0 ? (maxCleanupActions) : 1]; \ SExceptionNode exceptionNode = {0}; \
SCleanupAction cleanupActions[(maxCleanupActions) > 0 ? (maxCleanupActions) : 1]; \
exceptionNode.maxCleanupAction = (maxCleanupActions) > 0 ? (maxCleanupActions) : 1; \ exceptionNode.maxCleanupAction = (maxCleanupActions) > 0 ? (maxCleanupActions) : 1; \
exceptionNode.cleanupActions = cleanupActions; \ exceptionNode.cleanupActions = cleanupActions; \
exceptionPushNode( &exceptionNode ); \ exceptionPushNode(&exceptionNode); \
int caughtException = setjmp( exceptionNode.jb ); \ int caughtException = setjmp(exceptionNode.jb); \
if( caughtException == 0 ) if (caughtException == 0)
#define CATCH( code ) int32_t code = exceptionPopNode(); \ #define CATCH(code) \
if( caughtException == 1 ) int32_t code = exceptionPopNode(); \
if (caughtException == 1)
#define FINALLY( code ) int32_t code = exceptionPopNode(); #define FINALLY(code) int32_t code = exceptionPopNode();
#define END_TRY } while( 0 ); #define END_TRY \
} \
while (0) \
;
#define THROW( x ) exceptionThrow( (x) ) #define THROW(x) exceptionThrow((x))
#define CAUGHT_EXCEPTION() ((bool)(caughtException == 1)) #define CAUGHT_EXCEPTION() ((bool)(caughtException == 1))
#define CLEANUP_EXECUTE() cleanupExecute( &exceptionNode, CAUGHT_EXCEPTION() ) #define CLEANUP_EXECUTE() cleanupExecute(&exceptionNode, CAUGHT_EXCEPTION())
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /*_TD_UTIL_EXCEPTION_H*/ #endif /*_TD_UTIL_EXCEPTION_H_*/
...@@ -13,154 +13,137 @@ ...@@ -13,154 +13,137 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "os.h" #define _DEFAULT_SOURCE
#include "exception.h" #include "exception.h"
static threadlocal SExceptionNode* expList; static threadlocal SExceptionNode* expList;
void exceptionPushNode( SExceptionNode* node ) { void exceptionPushNode(SExceptionNode* node) {
node->prev = expList; node->prev = expList;
expList = node; expList = node;
} }
int32_t exceptionPopNode() { int32_t exceptionPopNode() {
SExceptionNode* node = expList; SExceptionNode* node = expList;
expList = node->prev; expList = node->prev;
return node->code; return node->code;
} }
void exceptionThrow( int32_t code ) { void exceptionThrow(int32_t code) {
expList->code = code; expList->code = code;
longjmp( expList->jb, 1 ); longjmp(expList->jb, 1);
} }
static void cleanupWrapper_void_ptr_ptr(SCleanupAction* ca) {
void (*func)(void*, void*) = ca->func;
static void cleanupWrapper_void_ptr_ptr( SCleanupAction* ca ) { func(ca->arg1.Ptr, ca->arg2.Ptr);
void (*func)( void*, void* ) = ca->func;
func( ca->arg1.Ptr, ca->arg2.Ptr );
} }
static void cleanupWrapper_void_ptr_bool( SCleanupAction* ca ) { static void cleanupWrapper_void_ptr_bool(SCleanupAction* ca) {
void (*func)( void*, bool ) = ca->func; void (*func)(void*, bool) = ca->func;
func( ca->arg1.Ptr, ca->arg2.Bool ); func(ca->arg1.Ptr, ca->arg2.Bool);
} }
static void cleanupWrapper_void_ptr( SCleanupAction* ca ) { static void cleanupWrapper_void_ptr(SCleanupAction* ca) {
void (*func)( void* ) = ca->func; void (*func)(void*) = ca->func;
func( ca->arg1.Ptr ); func(ca->arg1.Ptr);
} }
static void cleanupWrapper_int_int( SCleanupAction* ca ) { static void cleanupWrapper_int_int(SCleanupAction* ca) {
int (*func)( int ) = ca->func; int32_t (*func)(int32_t) = ca->func;
func( ca->arg1.Int ); func(ca->arg1.Int);
} }
static void cleanupWrapper_void( SCleanupAction* ca ) { static void cleanupWrapper_void(SCleanupAction* ca) {
void (*func)() = ca->func; void (*func)() = ca->func;
func(); func();
} }
static void cleanupWrapper_int_ptr( SCleanupAction* ca ) { static void cleanupWrapper_int_ptr(SCleanupAction* ca) {
int (*func)( void* ) = ca->func; int32_t (*func)(void*) = ca->func;
func( ca->arg1.Ptr ); func(ca->arg1.Ptr);
} }
typedef void (*wrapper)(SCleanupAction*); typedef void (*wrapper)(SCleanupAction*);
static wrapper wrappers[] = { static wrapper wrappers[] = {
cleanupWrapper_void_ptr_ptr, cleanupWrapper_void_ptr_ptr, cleanupWrapper_void_ptr_bool, cleanupWrapper_void_ptr,
cleanupWrapper_void_ptr_bool, cleanupWrapper_int_int, cleanupWrapper_void, cleanupWrapper_int_ptr,
cleanupWrapper_void_ptr,
cleanupWrapper_int_int,
cleanupWrapper_void,
cleanupWrapper_int_ptr,
}; };
void cleanupPush_void_ptr_ptr(bool failOnly, void* func, void* arg1, void* arg2) {
assert(expList->numCleanupAction < expList->maxCleanupAction);
void cleanupPush_void_ptr_ptr( bool failOnly, void* func, void* arg1, void* arg2 ) { SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
assert( expList->numCleanupAction < expList->maxCleanupAction ); ca->wrapper = 0;
ca->failOnly = failOnly;
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; ca->func = func;
ca->wrapper = 0; ca->arg1.Ptr = arg1;
ca->failOnly = failOnly; ca->arg2.Ptr = arg2;
ca->func = func;
ca->arg1.Ptr = arg1;
ca->arg2.Ptr = arg2;
} }
void cleanupPush_void_ptr_bool( bool failOnly, void* func, void* arg1, bool arg2 ) { void cleanupPush_void_ptr_bool(bool failOnly, void* func, void* arg1, bool arg2) {
assert( expList->numCleanupAction < expList->maxCleanupAction ); assert(expList->numCleanupAction < expList->maxCleanupAction);
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
ca->wrapper = 1; ca->wrapper = 1;
ca->failOnly = failOnly; ca->failOnly = failOnly;
ca->func = func; ca->func = func;
ca->arg1.Ptr = arg1; ca->arg1.Ptr = arg1;
ca->arg2.Bool = arg2; ca->arg2.Bool = arg2;
} }
void cleanupPush_void_ptr( bool failOnly, void* func, void* arg ) { void cleanupPush_void_ptr(bool failOnly, void* func, void* arg) {
assert( expList->numCleanupAction < expList->maxCleanupAction ); assert(expList->numCleanupAction < expList->maxCleanupAction);
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
ca->wrapper = 2; ca->wrapper = 2;
ca->failOnly = failOnly; ca->failOnly = failOnly;
ca->func = func; ca->func = func;
ca->arg1.Ptr = arg; ca->arg1.Ptr = arg;
} }
void cleanupPush_int_int( bool failOnly, void* func, int arg ) { void cleanupPush_int_int(bool failOnly, void* func, int32_t arg) {
assert( expList->numCleanupAction < expList->maxCleanupAction ); assert(expList->numCleanupAction < expList->maxCleanupAction);
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
ca->wrapper = 3; ca->wrapper = 3;
ca->failOnly = failOnly; ca->failOnly = failOnly;
ca->func = func; ca->func = func;
ca->arg1.Int = arg; ca->arg1.Int = arg;
} }
void cleanupPush_void( bool failOnly, void* func ) { void cleanupPush_void(bool failOnly, void* func) {
assert( expList->numCleanupAction < expList->maxCleanupAction ); assert(expList->numCleanupAction < expList->maxCleanupAction);
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
ca->wrapper = 4; ca->wrapper = 4;
ca->failOnly = failOnly; ca->failOnly = failOnly;
ca->func = func; ca->func = func;
} }
void cleanupPush_int_ptr( bool failOnly, void* func, void* arg ) { void cleanupPush_int_ptr(bool failOnly, void* func, void* arg) {
assert( expList->numCleanupAction < expList->maxCleanupAction ); assert(expList->numCleanupAction < expList->maxCleanupAction);
SCleanupAction *ca = expList->cleanupActions + expList->numCleanupAction++; SCleanupAction* ca = expList->cleanupActions + expList->numCleanupAction++;
ca->wrapper = 5; ca->wrapper = 5;
ca->failOnly = failOnly; ca->failOnly = failOnly;
ca->func = func; ca->func = func;
ca->arg1.Ptr = arg; ca->arg1.Ptr = arg;
} }
int32_t cleanupGetActionCount() { return expList->numCleanupAction; }
int32_t cleanupGetActionCount() { static void doExecuteCleanup(SExceptionNode* node, int32_t anchor, bool failed) {
return expList->numCleanupAction; while (node->numCleanupAction > anchor) {
} --node->numCleanupAction;
SCleanupAction* ca = node->cleanupActions + node->numCleanupAction;
if (failed || !(ca->failOnly)) {
static void doExecuteCleanup( SExceptionNode* node, int32_t anchor, bool failed ) { wrappers[ca->wrapper](ca);
while( node->numCleanupAction > anchor ) {
--node->numCleanupAction;
SCleanupAction *ca = node->cleanupActions + node->numCleanupAction;
if( failed || !(ca->failOnly) ) {
wrappers[ca->wrapper]( ca );
}
} }
}
} }
void cleanupExecuteTo( int32_t anchor, bool failed ) { void cleanupExecuteTo(int32_t anchor, bool failed) { doExecuteCleanup(expList, anchor, failed); }
doExecuteCleanup( expList, anchor, failed );
}
void cleanupExecute( SExceptionNode* node, bool failed ) { void cleanupExecute(SExceptionNode* node, bool failed) { doExecuteCleanup(node, 0, failed); }
doExecuteCleanup( node, 0, failed ); bool cleanupExceedLimit() { return expList->numCleanupAction >= expList->maxCleanupAction; }
}
bool cleanupExceedLimit() {
return expList->numCleanupAction >= expList->maxCleanupAction;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册