130 lines
4.7 KiB
C
130 lines
4.7 KiB
C
/*
|
|
* Copyright (c) 2020 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#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_*/
|