TD-153: add defer support
This commit is contained in:
parent
736ddfbbff
commit
4826a1851c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
* Copyright (c) 2020 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
@ -17,33 +17,81 @@
|
||||||
#define TDENGINE_EXCEPTION_H
|
#define TDENGINE_EXCEPTION_H
|
||||||
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exception handling
|
||||||
|
*/
|
||||||
typedef struct SExceptionNode {
|
typedef struct SExceptionNode {
|
||||||
struct SExceptionNode* prev;
|
struct SExceptionNode* prev;
|
||||||
jmp_buf jb;
|
jmp_buf jb;
|
||||||
int code;
|
int code;
|
||||||
} SExceptionNode;
|
} SExceptionNode;
|
||||||
|
|
||||||
void expPushNode( SExceptionNode* node );
|
void exceptionPushNode( SExceptionNode* node );
|
||||||
int expPopNode();
|
int exceptionPopNode();
|
||||||
void expThrow( int code );
|
void exceptionThrow( int code );
|
||||||
|
|
||||||
|
#define THROW( x ) exceptionThrow( (x) )
|
||||||
|
#define CAUGHT_EXCEPTION() (caught_exception == 1)
|
||||||
|
|
||||||
#define TRY do { \
|
#define TRY do { \
|
||||||
SExceptionNode expNode = { 0 }; \
|
SExceptionNode expNode = { 0 }; \
|
||||||
expPushNode( &expNode ); \
|
exceptionPushNode( &expNode ); \
|
||||||
if( setjmp(expNode.jb) == 0 ) {
|
int caught_exception = setjmp(expNode.jb); \
|
||||||
|
if( caught_exception == 0 )
|
||||||
|
|
||||||
#define CATCH( code ) expPopNode(); \
|
#define CATCH( code ) int code = exceptionPopNode(); \
|
||||||
} else { \
|
if( caught_exception == 1 )
|
||||||
int code = expPopNode();
|
|
||||||
|
|
||||||
#define END_CATCH } } while( 0 );
|
#define FINALLY( code ) int code = exceptionPopNode();
|
||||||
|
|
||||||
#define THROW( x ) expThrow( (x) )
|
#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 DEFER_EXECUTE() do{ \
|
||||||
|
deferExecute( deferedOperations, numOfDeferedOperations ); \
|
||||||
|
numOfDeferedOperations = 0; \
|
||||||
|
} 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 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,41 @@
|
||||||
|
|
||||||
static _Thread_local SExceptionNode* expList;
|
static _Thread_local SExceptionNode* expList;
|
||||||
|
|
||||||
void expPushNode( SExceptionNode* node ) {
|
void exceptionPushNode( SExceptionNode* node ) {
|
||||||
node->prev = expList;
|
node->prev = expList;
|
||||||
expList = node;
|
expList = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
int expPopNode() {
|
int exceptionPopNode() {
|
||||||
SExceptionNode* node = expList;
|
SExceptionNode* node = expList;
|
||||||
expList = node->prev;
|
expList = node->prev;
|
||||||
return node->code;
|
return node->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void expThrow( int code ) {
|
void exceptionThrow( int code ) {
|
||||||
expList->code = code;
|
expList->code = code;
|
||||||
longjmp( expList->jb, 1 );
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue