/* * 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 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef _TD_UTIL_EXCEPTION_H_ #define _TD_UTIL_EXCEPTION_H_ #include "os.h" #ifdef __cplusplus extern "C" { #endif /* * 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; int32_t Int; uint32_t Uint; int32_t Int32; uint32_t Uint32; int64_t Int64; uint64_t Uint64; float Float; double Double; } arg1, arg2; } SCleanupAction; /* * exception hander registration */ typedef struct SExceptionNode { struct SExceptionNode* prev; jmp_buf jb; int32_t code; int32_t maxCleanupAction; int32_t numCleanupAction; SCleanupAction* cleanupActions; } SExceptionNode; // functions & macros for auto-cleanup 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, int32_t arg); void cleanupPush_void(bool failOnly, void* func); void cleanupPush_int_ptr(bool failOnly, void* func, void* arg); int32_t cleanupGetActionCount(); void cleanupExecuteTo(int32_t anchor, bool failed); void cleanupExecute(SExceptionNode* node, bool failed); 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_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), (int32_t)(arg)) #define CLEANUP_PUSH_VOID(failOnly, func) cleanupPush_void((failOnly), (void*)(func)) #define CLEANUP_PUSH_INT_PTR(failOnly, func, arg) cleanupPush_int_ptr((failOnly), (void*)(func), (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, (int32_t)(arg)) #define CLEANUP_PUSH_FCLOSE(failOnly, arg) cleanupPush_int_ptr((failOnly), fclose, (void*)(arg)) #define CLEANUP_GET_ANCHOR() cleanupGetActionCount() #define CLEANUP_EXECUTE_TO(anchor, failed) cleanupExecuteTo((anchor), (failed)) #define CLEANUP_EXCEED_LIMIT() cleanupExceedLimit() // functions & macros for exception handling void exceptionPushNode(SExceptionNode* node); int32_t exceptionPopNode(); void exceptionThrow(int32_t code); #define TRY(maxCleanupActions) \ do { \ SExceptionNode exceptionNode = {0}; \ SCleanupAction cleanupActions[(maxCleanupActions) > 0 ? (maxCleanupActions) : 1]; \ exceptionNode.maxCleanupAction = (maxCleanupActions) > 0 ? (maxCleanupActions) : 1; \ exceptionNode.cleanupActions = cleanupActions; \ exceptionPushNode(&exceptionNode); \ int32_t caughtException = setjmp(exceptionNode.jb); \ if (caughtException == 0) #define CATCH(code) \ int32_t code = exceptionPopNode(); \ if (caughtException == 1) #define FINALLY(code) int32_t code = exceptionPopNode(); #define END_TRY \ } \ while (0) \ ; #define THROW(x) exceptionThrow((x)) #define CAUGHT_EXCEPTION() ((bool)(caughtException == 1)) #define CLEANUP_EXECUTE() cleanupExecute(&exceptionNode, CAUGHT_EXCEPTION()) #ifdef __cplusplus } #endif #endif /*_TD_UTIL_EXCEPTION_H_*/