浏览代码

feat: Var新增读写锁

SongZihuan 3 年之前
父节点
当前提交
8cb5207461
共有 6 个文件被更改,包括 81 次插入25 次删除
  1. 2 0
      src/core/__var.h
  2. 4 3
      src/core/env.c
  3. 5 4
      src/core/gc.c
  4. 4 4
      src/core/object.c
  5. 4 4
      src/core/run.c
  6. 62 10
      src/core/var.c

+ 2 - 0
src/core/__var.h

@@ -22,6 +22,8 @@ struct af_Var {
     char *name;
     struct af_VarNode *vn;
     char permissions[3];  // 读-1 写-2 读且写-3 不读不写-0 [自身权限 后代权限 外部权限]
+    pthread_rwlock_t lock;
+
     GC_Var gc;
 };
 

+ 4 - 3
src/core/env.c

@@ -141,7 +141,7 @@ af_VarSpace *getProtectVarSpace(af_Environment *env) {
 af_Object *getBaseObject(char *name, af_Environment *env) {
     af_Var *var = findVarFromVarSpace(name, NULL, env->protect);
     if (var != NULL)
-        return var->vn->obj;
+        return findVarNode(var, NULL);
     return NULL;
 }
 
@@ -1044,10 +1044,11 @@ static bool isInfixFunc(af_Code *code, af_Environment *env) {
     if (var == NULL)
         return false;
 
-    obj_isInfixFunc *func = findAPI("obj_isInfixFunc", var->vn->obj->data->api);
+    af_Object *obj = findVarNode(var, NULL);
+    obj_isInfixFunc *func = findAPI("obj_isInfixFunc", obj->data->api);
     if (func == NULL)
         return false;
-    return func(var->vn->obj->data->id, var->vn->obj);
+    return func(obj->data->id, obj);
 }
 
 bool pushExecutionActivity(af_Code *bt, bool return_first, af_Environment *env) {

+ 5 - 4
src/core/gc.c

@@ -245,11 +245,11 @@ static pgc_Analyzed reachableObjectData(struct af_ObjectData *od, pgc_Analyzed p
 }
 
 static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist) {
-    pthread_rwlock_rdlock(&vs->lock);
     if (vs->gc.info.reachable)
         return plist;
-
     vs->gc.info.reachable = true;
+
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->belong != NULL)
         plist = makeAnalyzed(vs->belong, plist);
     for (int i = 0; i < VAR_HASHTABLE_SIZE; i++) {
@@ -264,13 +264,14 @@ static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist
 static pgc_Analyzed reachableVar(struct af_Var *var, pgc_Analyzed plist) {
     if (var->gc.info.reachable)
         return plist;
-
     var->gc.info.reachable = true;
+
+    pthread_rwlock_rdlock(&var->lock);
     for (af_VarNode *vn = var->vn; vn != NULL; vn = vn->next) {
         if (!vn->obj->gc.info.reachable)
             plist = makeAnalyzed(vn->obj, plist);
     }
-
+    pthread_rwlock_unlock(&var->lock);
     return plist;
 }
 

+ 4 - 4
src/core/object.c

@@ -308,12 +308,12 @@ af_Object *findObjectAttributes(char *name, af_Object *visitor, af_Object *obj)
     af_Var *var = findVarFromVarSpace(name, visitor, obj->data->var_space);
 
     if (var != NULL)
-        return var->vn->obj;
+        return findVarNode(var, NULL);
 
     for (af_Inherit *ih = obj->data->inherit; ih != NULL; ih = ih->next) {
         var = findVarFromVarSpace(name, visitor, ih->vs);  // 搜索共享变量空间
         if (var != NULL)
-            return var->vn->obj;
+            return findVarNode(var, NULL);
     }
 
     return NULL;
@@ -328,12 +328,12 @@ af_Object *findObjectAttributesByObjectData(char *name, af_Object *visitor, af_O
     af_Var *var = findVarFromVarSpace(name, visitor, od->var_space);
 
     if (var != NULL)
-        return var->vn->obj;
+        return findVarNode(var, NULL);
 
     for (af_Inherit *ih = od->inherit; ih != NULL; ih = ih->next) {
         var = findVarFromVarSpace(name, visitor, ih->vs);  // 搜索共享变量空间
         if (var != NULL)
-            return var->vn->obj;
+            return findVarNode(var, NULL);
     }
 
     return NULL;

+ 4 - 4
src/core/run.c

@@ -172,8 +172,8 @@ static bool codeElement(af_Code *code, af_Environment *env) {
             return false;
         }
 
-        writeTrackLog(aFunCoreLogger, "Get literal %s : %p", code->element.data, var->vn->obj);
-        return pushLiteralActivity(code, code->element.data, var->vn->obj, env);
+        writeTrackLog(aFunCoreLogger, "Get literal %s : %p", code->element.data, findVarNode(var, NULL));
+        return pushLiteralActivity(code, code->element.data, findVarNode(var, NULL), env);
     }
 
     /* 变量执行 */
@@ -184,13 +184,13 @@ static bool codeElement(af_Code *code, af_Environment *env) {
         return false;
     }
 
-    af_Object *obj = var->vn->obj;
+    af_Object *obj = findVarNode(var, NULL);
     obj_isObjFunc *is_obj;
     obj_isInfixFunc *is_infix;
 
     if (code->prefix != getPrefix(E_QUOTE, env)) {
         if ((is_obj = findAPI("obj_isObjFunc", obj->data->api)) != NULL && is_obj(obj->data->id, obj))
-            return pushVariableActivity(code, var->vn->obj, env);  // 对象函数
+            return pushVariableActivity(code, obj, env);  // 对象函数
         else if (env->activity->status != act_func_get && // 在act_func_get 模式下不检查是否为is_infix函数 因为本来就要将其作为函数调用
                  (is_infix = findAPI("obj_isInfixFunc", obj->data->api)) != NULL && is_infix(obj->data->id, obj)) {
             pushMessageDown(makeERRORMessageFormat(INFIX_PROTECT, env,

+ 62 - 10
src/core/var.c

@@ -49,6 +49,7 @@ af_Var *makeVar(char *name, char p_self, char p_posterity, char p_external, af_O
     var->permissions[0] = p_self;
     var->permissions[1] = p_posterity;
     var->permissions[2] = p_external;
+    pthread_rwlock_init(&var->lock, NULL);
     gc_addVar(var, env);
     return var;
 }
@@ -57,9 +58,17 @@ void freeVar(af_Var *var, af_Environment *env){
     freeAllVarNode(var->vn);
     free(var->name);
     GC_FREE_EXCHANGE(var, Var, env);
+    pthread_rwlock_destroy(&var->lock);
     free(var);
 }
 
+/**
+ * 查找指定名字的VarNode
+ * 内部函数, 无锁
+ * @param var
+ * @param id
+ * @return
+ */
 static af_VarNode *findVarNode_(af_Var *var, char *id) {
     af_VarNode *vn = var->vn->next;
 
@@ -75,15 +84,27 @@ static af_VarNode *findVarNode_(af_Var *var, char *id) {
 
 void addVarNode(af_Var *var, af_Object *obj, char *id) {
     af_VarNode *vn = makeVarNode(obj, id);
-    vn->next = var->vn->next;  // 第一个 vn 必须表示返回值
+    pthread_rwlock_wrlock(&var->lock);
+    vn->next = var->vn->next;  // 第一个 vn 必须为 id=NULL
     var->vn->next = vn;
+    pthread_rwlock_unlock(&var->lock);
 }
 
+/**
+ * 查找指定名字的VarNode
+ * 外部函数, 带锁
+ * @param var
+ * @param id
+ * @return
+ */
 af_Object *findVarNode(af_Var *var, char *id) {
+    pthread_rwlock_rdlock(&var->lock);
     af_VarNode *vn = findVarNode_(var, id);
+    af_Object *obj = NULL;
     if (vn != NULL)
-        return vn->obj;
-    return NULL;
+        obj = vn->obj;
+    pthread_rwlock_unlock(&var->lock);
+    return obj;
 }
 
 static af_VarCup *makeVarCup(af_Var *var) {
@@ -191,9 +212,11 @@ static bool checkVarSpaceDefinePermissions(af_Object *visitor, af_VarSpace *vs){
  * @return 若空间被保护, 权限错误或已存在同名Var则返回false不作修改 否则返回true
  */
 bool addVarToVarSpace(af_Var *var, af_Object *visitor, af_VarSpace *vs) {
+    pthread_rwlock_rdlock(&var->lock);
+    pthread_rwlock_wrlock(&vs->lock);
+
     time33_t index = time33(var->name) % VAR_HASHTABLE_SIZE;
     af_VarCup **pCup = &vs->var[index];
-    pthread_rwlock_wrlock(&vs->lock);
 
     if (vs->is_protect)
         goto RETURN_FALSE;
@@ -202,16 +225,22 @@ bool addVarToVarSpace(af_Var *var, af_Object *visitor, af_VarSpace *vs) {
         goto RETURN_FALSE;
 
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
-        if (EQ_STR((*pCup)->var->name, var->name))
+        pthread_rwlock_wrlock(&(*pCup)->var->lock);
+        bool res = EQ_STR((*pCup)->var->name, var->name);
+        pthread_rwlock_unlock(&(*pCup)->var->lock);
+
+        if (res)
             goto RETURN_FALSE;
     }
 
     *pCup = makeVarCup(var);
     pthread_rwlock_unlock(&vs->lock);
+    pthread_rwlock_unlock(&var->lock);
     return true;
 
 RETURN_FALSE:
     pthread_rwlock_unlock(&vs->lock);
+    pthread_rwlock_unlock(&var->lock);
     return false;
 }
 
@@ -331,11 +360,16 @@ bool delVarFromVarSpace(char *name, af_Object *visitor, af_VarSpace *vs) {
         goto RETRUN_FALSE;
 
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
+        pthread_rwlock_wrlock(&(*pCup)->var->lock);
+
         if (EQ_STR((*pCup)->var->name, name)) {
             *pCup = freeVarCup(*pCup);
+            pthread_rwlock_unlock(&(*pCup)->var->lock);
             pthread_rwlock_unlock(&vs->lock);
             return true;
         }
+
+        pthread_rwlock_unlock(&(*pCup)->var->lock);
     }
 
 RETRUN_FALSE:
@@ -362,11 +396,16 @@ bool delVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *vsl)
 static af_Var *findVarFromVarSpaceByIndex(time33_t index, char *name, af_VarSpace *vs) {
     pthread_rwlock_rdlock(&vs->lock);
     for (af_VarCup *cup = vs->var[index]; cup != NULL; cup = cup->next) {
+        pthread_rwlock_wrlock(&cup->var->lock);
+
         if (EQ_STR(cup->var->name, name)) {
             af_Var *var = cup->var;
+            pthread_rwlock_unlock(&cup->var->lock);
             pthread_rwlock_unlock(&vs->lock);
             return var;
         }
+
+        pthread_rwlock_unlock(&cup->var->lock);
     }
     pthread_rwlock_unlock(&vs->lock);
     return NULL;
@@ -374,7 +413,7 @@ static af_Var *findVarFromVarSpaceByIndex(time33_t index, char *name, af_VarSpac
 
 /**
  * 检查访问者是否有读取变量的权限
- * 注意: 会给VarSpace加读锁
+ * 注意: 会给VarSpace和Var加读锁
  * @param var 变量
  * @param visitor 访问者
  * @param vs  变量空间
@@ -384,11 +423,13 @@ static bool checkVarReadPermissions(af_Var *var, af_Object *visitor, af_VarSpace
     char p = var->permissions[2];  // 默认外部权限
 
     pthread_rwlock_rdlock(&vs->lock);
+    pthread_rwlock_rdlock(&var->lock);
     if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = var->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = var->permissions[1];
     pthread_rwlock_unlock(&vs->lock);
+    pthread_rwlock_unlock(&var->lock);
     return p == 1 || p == 3;
 }
 
@@ -430,7 +471,7 @@ af_Var *findVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *
 
 /**
  * 检查访问者是否有改写变量的权限
- * 注意: 锁, 由调用者加锁
+ * 注意: 不会给VarList加锁, 给Var加读锁, 由调用者加锁
  * @param var 变量
  * @param visitor 访问者
  * @param vs 变量空间
@@ -439,10 +480,12 @@ af_Var *findVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *
 static bool checkVarWritePermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
     char p = var->permissions[2];  // 默认外部权限
 
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = var->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = var->permissions[1];
+    pthread_rwlock_unlock(&vs->lock);
 
     return p == 2 || p == 3;
 }
@@ -459,8 +502,11 @@ bool setVarToVarSpace(char *name, af_Object *obj, af_Object *visitor, af_VarSpac
 
     pthread_rwlock_wrlock(&vs->lock);
     if (checkVarWritePermissions(var, visitor, vs)) {
-        pthread_rwlock_wrlock(&vs->lock);
+        pthread_rwlock_unlock(&vs->lock);
+
+        pthread_rwlock_wrlock(&var->lock);
         var->vn->obj = obj;
+        pthread_rwlock_unlock(&var->lock);
         return true;
     }
 
@@ -482,11 +528,15 @@ bool setVarToVarList(char *name, af_Object *obj, af_Object *visitor, af_VarSpace
         if (var != NULL) {
             pthread_rwlock_wrlock(&vsl->vs->lock);
             if (checkVarWritePermissions(var, visitor, vsl->vs)) {
-                pthread_rwlock_wrlock(&vsl->vs->lock);
+                pthread_rwlock_unlock(&vsl->vs->lock);
+
+                pthread_rwlock_wrlock(&var->lock);
                 var->vn->obj = obj;
+                pthread_rwlock_unlock(&var->lock);
+
                 return true;
             }
-            pthread_rwlock_wrlock(&vsl->vs->lock);
+            pthread_rwlock_unlock(&vsl->vs->lock);
             return false;
         }
     }
@@ -505,9 +555,11 @@ void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_
         return;
     pthread_rwlock_unlock(&vs->lock);
 
+    pthread_rwlock_wrlock(&var->lock);
     var->permissions[0] = p_self;
     var->permissions[1] = p_posterity;
     var->permissions[2] = p_external;
+    pthread_rwlock_unlock(&var->lock);
 }
 
 void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {