update defer and rename it to cleanup
This commit is contained in:
parent
4826a1851c
commit
c24f7ea7bf
|
@ -25,73 +25,87 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exception handling
|
* cleanup actions
|
||||||
|
*/
|
||||||
|
typedef struct SCleanupAction {
|
||||||
|
bool failOnly;
|
||||||
|
uint8_t wrapper;
|
||||||
|
uint16_t reserved;
|
||||||
|
void* func;
|
||||||
|
union {
|
||||||
|
void* Ptr;
|
||||||
|
bool Bool;
|
||||||
|
char Char;
|
||||||
|
int8_t Int8;
|
||||||
|
uint8_t Uint8;
|
||||||
|
int16_t Int16;
|
||||||
|
uint16_t Uint16;
|
||||||
|
int Int;
|
||||||
|
unsigned int Uint;
|
||||||
|
int32_t Int32;
|
||||||
|
uint32_t Uint32;
|
||||||
|
int64_t Int64;
|
||||||
|
uint64_t Uint64;
|
||||||
|
float Float;
|
||||||
|
double Double;
|
||||||
|
} arg1, arg2;
|
||||||
|
} SCleanupAction;
|
||||||
|
|
||||||
|
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 failOnly, void* func, void* arg );
|
||||||
|
void cleanupPush_int_int ( bool failOnly, void* func, int arg );
|
||||||
|
void cleanupPush_void ( bool failOnly, void* func );
|
||||||
|
|
||||||
|
int32_t cleanupGetActionCount();
|
||||||
|
void cleanupExecute( bool failed, int32_t toIndex );
|
||||||
|
|
||||||
|
#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_BOOL( failOnly, func, arg1, arg2 ) cleanupPush_void_ptr_bool( (failOnly), (void*)(func), (void*)(arg1), (bool)(arg2) )
|
||||||
|
#define CLEANUP_PUSH_VOID_PTR( failOnly, func, arg ) cleanupPush_void_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_VOID( failOnly, func ) cleanupPush_void( (failOnly), (void*)(func) )
|
||||||
|
#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_CREATE_ANCHOR() int32_t cleanupAnchor = cleanupGetActionCount()
|
||||||
|
#define CLEANUP_EXECUTE( failed ) cleanupExecute( cleanupAnchor, (failed) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exception hander registration
|
||||||
*/
|
*/
|
||||||
typedef struct SExceptionNode {
|
typedef struct SExceptionNode {
|
||||||
struct SExceptionNode* prev;
|
struct SExceptionNode* prev;
|
||||||
jmp_buf jb;
|
jmp_buf jb;
|
||||||
int code;
|
int32_t code;
|
||||||
|
int32_t maxCleanupAction;
|
||||||
|
int32_t numCleanupAction;
|
||||||
|
SCleanupAction* cleanupActions;
|
||||||
} SExceptionNode;
|
} SExceptionNode;
|
||||||
|
|
||||||
void exceptionPushNode( SExceptionNode* node );
|
void exceptionPushNode( SExceptionNode* node );
|
||||||
int exceptionPopNode();
|
int32_t exceptionPopNode();
|
||||||
void exceptionThrow( int code );
|
void exceptionThrow( int code );
|
||||||
|
|
||||||
#define THROW( x ) exceptionThrow( (x) )
|
#define TRY(maxCleanupActions) do { \
|
||||||
#define CAUGHT_EXCEPTION() (caught_exception == 1)
|
SExceptionNode exceptionNode = { 0 }; \
|
||||||
|
SDeferedOperation cleanupActions[maxCleanupActions > 0 ? maxCleanupActions : 1]; \
|
||||||
#define TRY do { \
|
exceptionNode.maxCleanupAction = maxCleanupActions > 0 ? maxDefered : 1; \
|
||||||
SExceptionNode expNode = { 0 }; \
|
exceptionNode.cleanupActions = cleanupActions; \
|
||||||
exceptionPushNode( &expNode ); \
|
int32_t cleanupAnchor = 0; \
|
||||||
int caught_exception = setjmp(expNode.jb); \
|
exceptionPushNode( &exceptionNode ); \
|
||||||
if( caught_exception == 0 )
|
int caughtException = setjmp( exceptionNode.jb ); \
|
||||||
|
if( caughtException == 0 )
|
||||||
|
|
||||||
#define CATCH( code ) int code = exceptionPopNode(); \
|
#define CATCH( code ) int code = exceptionPopNode(); \
|
||||||
if( caught_exception == 1 )
|
if( caughtEexception == 1 )
|
||||||
|
|
||||||
#define FINALLY( code ) int code = exceptionPopNode();
|
#define FINALLY( code ) int code = exceptionPopNode();
|
||||||
|
|
||||||
#define END_TRY } while( 0 );
|
#define END_TRY } while( 0 );
|
||||||
|
|
||||||
|
#define THROW( x ) exceptionThrow( (x) )
|
||||||
/*
|
#define CAUGHT_EXCEPTION() ((bool)(caughtEexception == 1))
|
||||||
* 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ void exceptionPushNode( SExceptionNode* node ) {
|
||||||
expList = node;
|
expList = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exceptionPopNode() {
|
int32_t exceptionPopNode() {
|
||||||
SExceptionNode* node = expList;
|
SExceptionNode* node = expList;
|
||||||
expList = node->prev;
|
expList = node->prev;
|
||||||
return node->code;
|
return node->code;
|
||||||
|
@ -19,25 +19,105 @@ void exceptionThrow( int code ) {
|
||||||
longjmp( expList->jb, 1 );
|
longjmp( expList->jb, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferWrapper_void_ptr( SDeferedOperation* dp ) {
|
|
||||||
void (*func)( void* ) = dp->func;
|
|
||||||
func( dp->arg );
|
static void cleanupWrapper_void_ptr_ptr( SCleanupAction* ca ) {
|
||||||
|
void (*func)( void*, void* ) = ac->func;
|
||||||
|
func( ca->arg1.Ptr, ca->arg2.Ptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferWrapper_int_int( SDeferedOperation* dp ) {
|
static void cleanupWrapper_void_ptr_bool( SCleanupAction* ca ) {
|
||||||
int (*func)( int ) = dp->func;
|
void (*func)( void*, bool ) = ca->func;
|
||||||
func( (int)(intptr_t)(dp->arg) );
|
func( ca->arg1.Ptr, ca->arg2.Bool );
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferWrapper_void_void( SDeferedOperation* dp ) {
|
static void cleanupWrapper_void_ptr( SCleanupAction* ca ) {
|
||||||
void (*func)() = dp->func;
|
void (*func)( void* ) = ca->func;
|
||||||
|
func( ca->arg1.Ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanupWrapper_int_int( SCleanupAction* ca ) {
|
||||||
|
int (*func)( int ) = ca->func;
|
||||||
|
func( (int)(intptr_t)(ca->arg1.Int) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanupWrapper_void_void( SCleanupAction* ca ) {
|
||||||
|
void (*func)() = ca->func;
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferExecute( SDeferedOperation* operations, unsigned int numOfOperations ) {
|
static void (*wrappers)(SCleanupAction*)[] = {
|
||||||
while( numOfOperations > 0 ) {
|
cleanupWrapper_void_ptr_ptr,
|
||||||
--numOfOperations;
|
cleanupWrapper_void_ptr_bool,
|
||||||
SDeferedOperation* dp = operations + numOfOperations;
|
cleanupWrapper_void_ptr,
|
||||||
dp->wrapper( dp );
|
cleanupWrapper_int_int,
|
||||||
|
cleanupWrapper_void_void,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void cleanupPush_void_ptr_ptr( bool failOnly, void* func, void* arg1, void* arg2 ) {
|
||||||
|
assert( expList->numCleanupAction < expList->maxCleanupAction );
|
||||||
|
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction++;
|
||||||
|
ac->wrapper = 0;
|
||||||
|
ac->failOnly = failOnly;
|
||||||
|
ac->func = func;
|
||||||
|
ac->arg1.Ptr = arg1;
|
||||||
|
ac->arg2.Ptr = arg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupPush_void_ptr_bool( bool failOnly, void* func, void* arg1, bool arg2 ) {
|
||||||
|
assert( expList->numCleanupAction < expList->maxCleanupAction );
|
||||||
|
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction++;
|
||||||
|
ac->wrapper = 1;
|
||||||
|
ac->failOnly = failOnly;
|
||||||
|
ac->func = func;
|
||||||
|
ac->arg1.Ptr = arg1;
|
||||||
|
ac->arg2.Bool = arg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupPush_void_ptr( bool failOnly, void* func, void* arg ) {
|
||||||
|
assert( expList->numCleanupAction < expList->maxCleanupAction );
|
||||||
|
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction++;
|
||||||
|
ac->wrapper = 2;
|
||||||
|
ac->failOnly = failOnly;
|
||||||
|
ac->func = func;
|
||||||
|
ac->arg1.Ptr = arg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupPush_int_int( bool failOnly, void* func, int arg ) {
|
||||||
|
assert( expList->numCleanupAction < expList->maxCleanupAction );
|
||||||
|
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction++;
|
||||||
|
ac->wrapper = 3;
|
||||||
|
ac->failOnly = failOnly;
|
||||||
|
ac->func = func;
|
||||||
|
ac->arg1.Int = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupPush_void( bool failOnly, void* func ) {
|
||||||
|
assert( expList->numCleanupAction < expList->maxCleanupAction );
|
||||||
|
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction++;
|
||||||
|
ac->wrapper = 4;
|
||||||
|
ac->failOnly = failOnly;
|
||||||
|
ac->func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32 cleanupGetActionCount() {
|
||||||
|
return expList->numCleanupAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cleanupExecute( int32_t anchor, bool failed ) {
|
||||||
|
while( expList->numCleanupAction > anchor ) {
|
||||||
|
--expList->numCleanupAction;
|
||||||
|
SCleanupAction *ac = expList->cleanupActions + expList->numCleanupAction;
|
||||||
|
if( failed || !(ac->failOnly) )
|
||||||
|
ac->wrapper( ac );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue