diff --git a/src/util/inc/exception.h b/src/util/inc/exception.h index 5c9506f802836a7d4065f60afc532753895a0ba3..19c37561d2388519058a47ce7e58795011c416e4 100644 --- a/src/util/inc/exception.h +++ b/src/util/inc/exception.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 TAOS Data, Inc. + * Copyright (c) 2020 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 @@ -17,33 +17,81 @@ #define TDENGINE_EXCEPTION_H #include +#include +#include #ifdef __cplusplus extern "C" { #endif +/* + * exception handling + */ typedef struct SExceptionNode { struct SExceptionNode* prev; jmp_buf jb; int code; } SExceptionNode; -void expPushNode( SExceptionNode* node ); -int expPopNode(); -void expThrow( int code ); +void exceptionPushNode( SExceptionNode* node ); +int exceptionPopNode(); +void exceptionThrow( int code ); + +#define THROW( x ) exceptionThrow( (x) ) +#define CAUGHT_EXCEPTION() (caught_exception == 1) #define TRY do { \ SExceptionNode expNode = { 0 }; \ - expPushNode( &expNode ); \ - if( setjmp(expNode.jb) == 0 ) { + exceptionPushNode( &expNode ); \ + int caught_exception = setjmp(expNode.jb); \ + if( caught_exception == 0 ) + +#define CATCH( code ) int code = exceptionPopNode(); \ + if( caught_exception == 1 ) + +#define FINALLY( code ) int code = exceptionPopNode(); + +#define END_TRY } while( 0 ); + + +/* + * defered operations + */ +typedef struct SDeferedOperation { + void (*wrapper)( struct SDeferedOperation* dp ); + void* func; + void* arg; +} SDeferedOperation; + +void deferExecute( SDeferedOperation* operations, unsigned int numOfOperations ); +void deferWrapper_void_void( SDeferedOperation* dp ); +void deferWrapper_void_ptr( SDeferedOperation* dp ); +void deferWrapper_int_int( SDeferedOperation* dp ); + +#define DEFER_INIT( MaxOperations ) unsigned int maxDeferedOperations = MaxOperations, numOfDeferedOperations = 0; \ + SDeferedOperation deferedOperations[MaxOperations] + +#define DEFER_PUSH( wrapperFunc, deferedFunc, argument ) do { \ + assert( numOfDeferedOperations < maxDeferedOperations ); \ + SDeferedOperation* dp = deferedOperations + numOfDeferedOperations++; \ + dp->wrapper = wrapperFunc; \ + dp->func = (void*)deferedFunc; \ + dp->arg = (void*)argument; \ +} while( 0 ) + +#define DEFER_POP() do { --numOfDeferedOperations; } while( 0 ) -#define CATCH( code ) expPopNode(); \ - } else { \ - int code = expPopNode(); +#define DEFER_EXECUTE() do{ \ + deferExecute( deferedOperations, numOfDeferedOperations ); \ + numOfDeferedOperations = 0; \ +} while( 0 ) -#define END_CATCH } } while( 0 ); +#define DEFER_PUSH_VOID_PTR( func, arg ) DEFER_PUSH( deferWrapper_void_ptr, func, arg ) +#define DEFER_PUSH_INT_INT( func, arg ) DEFER_PUSH( deferWrapper_int_int, func, arg ) +#define DEFER_PUSH_VOID_VOID( func ) DEFER_PUSH( deferWrapper_void_void, func, 0 ) -#define THROW( x ) expThrow( (x) ) +#define DEFER_PUSH_FREE( arg ) DEFER_PUSH( deferWrapper_void_ptr, free, arg ) +#define DEFER_PUSH_CLOSE( arg ) DEFER_PUSH( deferWrapper_int_int, close, arg ) #ifdef __cplusplus } diff --git a/src/util/src/exception.c b/src/util/src/exception.c index 6363aaebf61f06be2a1e50cb657f9c30b8e20f56..45ebd349a59336b2673b6fe47fc5e2f57fe98332 100644 --- a/src/util/src/exception.c +++ b/src/util/src/exception.c @@ -3,18 +3,41 @@ static _Thread_local SExceptionNode* expList; -void expPushNode( SExceptionNode* node ) { +void exceptionPushNode( SExceptionNode* node ) { node->prev = expList; expList = node; } -int expPopNode() { +int exceptionPopNode() { SExceptionNode* node = expList; expList = node->prev; return node->code; } -void expThrow( int code ) { +void exceptionThrow( int code ) { expList->code = code; longjmp( expList->jb, 1 ); } + +void deferWrapper_void_ptr( SDeferedOperation* dp ) { + void (*func)( void* ) = dp->func; + func( dp->arg ); +} + +void deferWrapper_int_int( SDeferedOperation* dp ) { + int (*func)( int ) = dp->func; + func( (int)(intptr_t)(dp->arg) ); +} + +void deferWrapper_void_void( SDeferedOperation* dp ) { + void (*func)() = dp->func; + func(); +} + +void deferExecute( SDeferedOperation* operations, unsigned int numOfOperations ) { + while( numOfOperations > 0 ) { + --numOfOperations; + SDeferedOperation* dp = operations + numOfOperations; + dp->wrapper( dp ); + } +}