Javascript多线程引擎(五)

Javascript多线程引擎(五)之异常处理

           C语言没有提供一个像Java一样的异常处理机制, 这就带来了一个问题, 对于一个子函数中发生异常后, 需要在父函数调用子函数的位置进行Check, 如果发生异常则直接reuren.   这种机制, 会带来一个问题 ------- 过多的return 和  判断语句, 使得程序的维护成本提高.

    而这个项目准备使用setjmp,longjmp的异常处理机制来实现throw异常后,能直接转到catch位置.

           

/*一个函数中mark都要不同*/
#define JS_TRY(mark) 
    int done##mark; 
    jmp_buf* jmp_buf##mark = (jmp_buf*)JsMalloc(sizeof(jmp_buf)); 
    for(done##mark = 0; 
        done##mark == 0 && (setjmp(*jmp_buf##mark) == 0 ? 
            (JsBuildRecord(jmp_buf##mark),1) : (JsOmitRecord(),0));  
        ++done##mark, JsOmitRecord())

/*Catch之后, 异常已经被清除了, 并且e会被赋值 [NULL,Value] */
#define JS_CATCH(e) 
        if((e = JsGetError()))
        

这里使用两组宏, done##mark .. 确保了可以在一个函数中多次使用JS_TRY,

如下是对其中的函数用途解析.

/*
    抛出一个String类型的错误
*/
void JsThrowString(char* msg);
/*
    抛出一个error
*/
void JsThrow(struct JsValue* e);
//保存一个还原点到环境中,p 为jmp_buf*指针

void JsBuildRecord(void* p);

//每次加锁的时候, 把对应的锁添加到最近还原点的上下文中
void JsPushLockToRecord(JsLock lock);
//解锁的时候,  把给定的锁从最后面扫描, 剔除
void JsPopLockInRecord(JsLock lock);

//检查当前环境是否存在异常, 当并不清除错误
int JsCheckError();
//在环境中删除一个最近的还原点
void JsOmitRecord();

//获得当前错误, 并且清除当前错误, 如果没有则返回NULL
struct JsValue* JsGetError();

//设置一个错误, NULL表示清除错误
void JsSetError(struct JsValue* v);

基本原理是在, TLS中建立一个异常链, 每次throw的时候, 直接获取最近的还原点(Record). 然后通过GetError()获取到这个异常.

为什么要使用TLS? , 因为setjmp/longjmp 是基于函数栈的, 多个线程之间是不能跳转的. 

值得一提的是, setjmp/longjmp 不会释放非托管资源(除内存外的所有资源, 比如说, lock, socket, file等), 所以在使用这些句柄的时候, 需要注意TRY --- CATCH

 基本使用用法:

JS_TRY(0){
        可以放置表达式(函数调用, 赋值,...)
        如果使用return , break 语句则需要在之前调用JsOmitPoint()
        
 }
 doFinally工作
 struct JsValue* e = NULL;
 JS_CATCH(e){
   1. 处理错误
   2. 继续抛出异常
         JsThrow(e);
    
 }

截至到现在,  该引擎的基本模块已经完成, 进入了代码验证和测试阶段.!

项目地址为:

             github.com/darkgem/js-engine

原文地址:https://www.cnblogs.com/tickobject/p/3617197.html