Browse Source

feat: 变量空间新增读写锁

SongZihuan 3 years ago
parent
commit
e47d876cdc
7 changed files with 116 additions and 22 deletions
  1. 1 1
      include/core/var.h
  2. 1 1
      src/core/__env.h
  3. 4 1
      src/core/__var.h
  4. 3 2
      src/core/env.c
  5. 7 0
      src/core/gc.c
  6. 99 16
      src/core/var.c
  7. 1 1
      src/main.c

+ 1 - 1
include/core/var.h

@@ -32,7 +32,7 @@ AFUN_CORE_EXPORT bool delVarFromVarSpace(char *name, af_Object *visitor, af_VarS
 AFUN_CORE_EXPORT bool setVarToVarSpace(char *name, af_Object *obj, af_Object *visitor, af_VarSpace *vs);
 AFUN_CORE_EXPORT bool setVarToVarSpace(char *name, af_Object *obj, af_Object *visitor, af_VarSpace *vs);
 AFUN_CORE_EXPORT void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external);
 AFUN_CORE_EXPORT void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external);
 AFUN_CORE_EXPORT void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external);
 AFUN_CORE_EXPORT void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external);
-AFUN_CORE_EXPORT bool setVarSpaceProtect(af_Object *visitor, af_VarSpace *vs, char protect);
+AFUN_CORE_EXPORT bool setVarSpaceProtect(af_Object *visitor, af_VarSpace *vs, bool protect);
 
 
 /* 变量空间链 相关操作 */
 /* 变量空间链 相关操作 */
 AFUN_CORE_EXPORT bool addVarToVarSpaceList(af_Var *var, af_Object *visitor, af_VarSpaceListNode *vsl);
 AFUN_CORE_EXPORT bool addVarToVarSpaceList(af_Var *var, af_Object *visitor, af_VarSpaceListNode *vsl);

+ 1 - 1
src/core/__env.h

@@ -229,9 +229,9 @@ struct af_Environment {  // 运行环境
     struct af_VarSpace *gc_VarSpace;
     struct af_VarSpace *gc_VarSpace;
 
 
     struct af_EnvVarSpace *esv;
     struct af_EnvVarSpace *esv;
-    struct af_Activity *activity;
     struct af_TopMsgProcess *process;
     struct af_TopMsgProcess *process;
     struct af_Guardian *guardian;
     struct af_Guardian *guardian;
+    struct af_Activity *activity;
     pthread_mutex_t in_run;
     pthread_mutex_t in_run;
 };
 };
 
 

+ 4 - 1
src/core/__var.h

@@ -1,6 +1,7 @@
 #ifndef AFUN_VAR_H_
 #ifndef AFUN_VAR_H_
 #define AFUN_VAR_H_
 #define AFUN_VAR_H_
 #include "macro.h"
 #include "macro.h"
+#include "pthread.h"
 
 
 // 这些typedef可能会被下面include的文件使用
 // 这些typedef可能会被下面include的文件使用
 typedef struct af_VarNode af_VarNode;
 typedef struct af_VarNode af_VarNode;
@@ -34,7 +35,9 @@ struct af_VarSpace {
     struct af_VarCup *(var[VAR_HASHTABLE_SIZE]);
     struct af_VarCup *(var[VAR_HASHTABLE_SIZE]);
     struct af_Object *belong;  // 属主
     struct af_Object *belong;  // 属主
     char permissions[3];  // 可定义(2),可删除(1) [自身权限 后代权限 外部权限]
     char permissions[3];  // 可定义(2),可删除(1) [自身权限 后代权限 外部权限]
-    GC_VarSpace gc;
+    pthread_rwlock_t lock;  // 控制 除gc 外其他字段的访问
+
+    GC_VarSpace gc;  // 仅能由 gc 机制访问
 };
 };
 
 
 struct af_VarSpaceListNode {  // 变量链
 struct af_VarSpaceListNode {  // 变量链

+ 3 - 2
src/core/env.c

@@ -876,7 +876,7 @@ af_Environment *makeEnvironment(enum GcRunTime grt) {
 }
 }
 
 
 void enableEnvironment(af_Environment *env) {
 void enableEnvironment(af_Environment *env) {
-    env->protect->is_protect = true;
+    setVarSpaceProtect(NULL, env->protect, true);
     env->status = core_normal;
     env->status = core_normal;
 }
 }
 
 
@@ -1266,6 +1266,7 @@ bool setFuncActivityAddVar(af_Environment *env){
         pushMessageDown(makeERRORMessage(API_RUN_ERROR, API_DONOT_GIVE(FuncInfo), env), env);
         pushMessageDown(makeERRORMessage(API_RUN_ERROR, API_DONOT_GIVE(FuncInfo), env), env);
         return false;
         return false;
     }
     }
+
     if (fi->scope == super_pure_scope && env->activity->fi->scope == super_embedded) {
     if (fi->scope == super_pure_scope && env->activity->fi->scope == super_embedded) {
         /* 超纯函数和超内嵌函数不得搭配使用 */
         /* 超纯函数和超内嵌函数不得搭配使用 */
         pushMessageDown(makeERRORMessage(RUN_ERROR, PURE_EMBEDDED_INFO, env), env);
         pushMessageDown(makeERRORMessage(RUN_ERROR, PURE_EMBEDDED_INFO, env), env);
@@ -1330,7 +1331,7 @@ bool setFuncActivityAddVar(af_Environment *env){
     }
     }
 
 
     if (fi->embedded == protect_embedded)
     if (fi->embedded == protect_embedded)
-        env->activity->run_varlist->vs->is_protect = true;
+        setVarSpaceProtect(env->activity->belong, env->activity->run_varlist->vs, true);
 
 
     /* ArgCodeList 在此处被清理 */
     /* ArgCodeList 在此处被清理 */
     freeAllArgCodeList(env->activity->acl_start);
     freeAllArgCodeList(env->activity->acl_start);

+ 7 - 0
src/core/gc.c

@@ -3,6 +3,7 @@
 #include "__var.h"
 #include "__var.h"
 #include "__gc.h"
 #include "__gc.h"
 #include "__env.h"
 #include "__env.h"
+#include "pthread.h"
 
 
 /* gc 操控函数 */
 /* gc 操控函数 */
 
 
@@ -219,6 +220,7 @@ static pgc_Analyzed reachableObjectData(struct af_ObjectData *od, pgc_Analyzed p
 }
 }
 
 
 static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist) {
 static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist) {
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->gc.info.reachable)
     if (vs->gc.info.reachable)
         return plist;
         return plist;
 
 
@@ -230,6 +232,7 @@ static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist
             plist = reachableVar(var->var, plist);
             plist = reachableVar(var->var, plist);
     }
     }
 
 
+    pthread_rwlock_unlock(&vs->lock);
     return plist;
     return plist;
 }
 }
 
 
@@ -326,6 +329,10 @@ void resetGC(af_Environment *env) {
         var->gc.info.reachable = false;
         var->gc.info.reachable = false;
 }
 }
 
 
+/**
+ * 清理对象, 清除不可达的对象
+ * @param env
+ */
 static void freeValue(af_Environment *env) {
 static void freeValue(af_Environment *env) {
     for (af_ObjectData *od = env->gc_ObjectData, *next; od != NULL; od = next) {
     for (af_ObjectData *od = env->gc_ObjectData, *next; od != NULL; od = next) {
         next = od->gc.next;
         next = od->gc.next;

+ 99 - 16
src/core/var.c

@@ -112,6 +112,8 @@ af_VarSpace *makeVarSpace(af_Object *belong, char p_self, char p_posterity, char
     vs->permissions[0] = p_self;
     vs->permissions[0] = p_self;
     vs->permissions[1] = p_posterity;
     vs->permissions[1] = p_posterity;
     vs->permissions[2] = p_external;
     vs->permissions[2] = p_external;
+
+    pthread_rwlock_init(&vs->lock, NULL);
     gc_addVarSpace(vs, env);
     gc_addVarSpace(vs, env);
     return vs;
     return vs;
 }
 }
@@ -120,6 +122,7 @@ void freeVarSpace(af_VarSpace *vs, af_Environment *env) {
     for (int i = 0; i < VAR_HASHTABLE_SIZE; i++)
     for (int i = 0; i < VAR_HASHTABLE_SIZE; i++)
         freeAllVarCup(vs->var[i]);
         freeAllVarCup(vs->var[i]);
     GC_FREE_EXCHANGE(vs, VarSpace, env);
     GC_FREE_EXCHANGE(vs, VarSpace, env);
+    pthread_rwlock_destroy(&vs->lock);
     free(vs);
     free(vs);
 }
 }
 
 
@@ -163,6 +166,12 @@ bool freeVarSpaceListCount(size_t count, af_VarSpaceListNode *vsl) {
     return true;
     return true;
 }
 }
 
 
+/**
+ * 检查访问者是否有定义变量的权限
+ * 注意: 无锁, 由调用者加锁
+ * @param visitor 访问者
+ * @param vs 变量空间
+ */
 static bool checkVarSpaceDefinePermissions(af_Object *visitor, af_VarSpace *vs){
 static bool checkVarSpaceDefinePermissions(af_Object *visitor, af_VarSpace *vs){
     char p = vs->permissions[2];  // 默认外部权限
     char p = vs->permissions[2];  // 默认外部权限
 
 
@@ -174,29 +183,36 @@ static bool checkVarSpaceDefinePermissions(af_Object *visitor, af_VarSpace *vs){
     return p == 2 || p == 3;
     return p == 2 || p == 3;
 }
 }
 
 
-/*
- * 函数名: addVarToVarSpace
- * 目标: 把var添加到VarSpace中
- * 若空间被保护, 权限错误或已存在同名Var则返回false不作修改
- * 否则返回true
+/**
+ * 把var添加到VarSpace中
+ * @param var 变量
+ * @param visitor 访问者
+ * @param vs 变量空间
+ * @return 若空间被保护, 权限错误或已存在同名Var则返回false不作修改 否则返回true
  */
  */
 bool addVarToVarSpace(af_Var *var, af_Object *visitor, af_VarSpace *vs) {
 bool addVarToVarSpace(af_Var *var, af_Object *visitor, af_VarSpace *vs) {
     time33_t index = time33(var->name) % VAR_HASHTABLE_SIZE;
     time33_t index = time33(var->name) % VAR_HASHTABLE_SIZE;
     af_VarCup **pCup = &vs->var[index];
     af_VarCup **pCup = &vs->var[index];
+    pthread_rwlock_wrlock(&vs->lock);
 
 
     if (vs->is_protect)
     if (vs->is_protect)
-        return false;
+        goto RETURN_FALSE;
 
 
     if (!checkVarSpaceDefinePermissions(visitor, vs))
     if (!checkVarSpaceDefinePermissions(visitor, vs))
-        return false;
+        goto RETURN_FALSE;
 
 
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
         if (EQ_STR((*pCup)->var->name, var->name))
         if (EQ_STR((*pCup)->var->name, var->name))
-            return false;
+            goto RETURN_FALSE;
     }
     }
 
 
     *pCup = makeVarCup(var);
     *pCup = makeVarCup(var);
+    pthread_rwlock_unlock(&vs->lock);
     return true;
     return true;
+
+RETURN_FALSE:
+    pthread_rwlock_unlock(&vs->lock);
+    return false;
 }
 }
 
 
 /*
 /*
@@ -244,9 +260,15 @@ bool makeVarToVarSpaceList(char *name, char p_self, char p_posterity, char p_ext
  * 调用 addVarToVarSpace
  * 调用 addVarToVarSpace
  */
  */
 bool makeVarToProtectVarSpace(char *name, char p_self, char p_posterity, char p_external, af_Object *obj, af_Environment *env){
 bool makeVarToProtectVarSpace(char *name, char p_self, char p_posterity, char p_external, af_Object *obj, af_Environment *env){
+    pthread_rwlock_wrlock(&env->protect->lock);
     env->protect->is_protect = false;
     env->protect->is_protect = false;
+    pthread_rwlock_unlock(&env->protect->lock);
+
     bool re = addVarToVarSpace(makeVar(name, p_self, p_posterity, p_external, obj, env), env->activity->belong, env->protect);
     bool re = addVarToVarSpace(makeVar(name, p_self, p_posterity, p_external, obj, env), env->activity->belong, env->protect);
+
+    pthread_rwlock_wrlock(&env->protect->lock);
     env->protect->is_protect = true;
     env->protect->is_protect = true;
+    pthread_rwlock_unlock(&env->protect->lock);
     return re;
     return re;
 }
 }
 
 
@@ -258,14 +280,27 @@ bool makeVarToProtectVarSpace(char *name, char p_self, char p_posterity, char p_
  * 调用 addVarToVarSpace
  * 调用 addVarToVarSpace
  */
  */
 bool addVarToProtectVarSpace(af_Var *var, af_Environment *env) {
 bool addVarToProtectVarSpace(af_Var *var, af_Environment *env) {
+    pthread_rwlock_wrlock(&env->protect->lock);
     bool is_protect = env->protect->is_protect;
     bool is_protect = env->protect->is_protect;
     env->protect->is_protect = false;
     env->protect->is_protect = false;
+    pthread_rwlock_unlock(&env->protect->lock);
+
     bool re = addVarToVarSpace(var, NULL, env->protect);
     bool re = addVarToVarSpace(var, NULL, env->protect);
+
+    pthread_rwlock_wrlock(&env->protect->lock);
     env->protect->is_protect = is_protect;
     env->protect->is_protect = is_protect;
+    pthread_rwlock_unlock(&env->protect->lock);
     return re;
     return re;
 }
 }
 
 
 
 
+/**
+ * 检查访问者是否有删除变量的权限
+ * 注意: 无锁, 由调用者加锁
+ * @param visitor 访问者
+ * @param vs 变量空间
+ * @return
+ */
 static bool checkVarSpaceDelPermissions(af_Object *visitor, af_VarSpace *vs) {
 static bool checkVarSpaceDelPermissions(af_Object *visitor, af_VarSpace *vs) {
     char p = vs->permissions[2];  // 默认外部权限
     char p = vs->permissions[2];  // 默认外部权限
 
 
@@ -285,21 +320,26 @@ static bool checkVarSpaceDelPermissions(af_Object *visitor, af_VarSpace *vs) {
  */
  */
 bool delVarFromVarSpace(char *name, af_Object *visitor, af_VarSpace *vs) {
 bool delVarFromVarSpace(char *name, af_Object *visitor, af_VarSpace *vs) {
     time33_t index = time33(name) % VAR_HASHTABLE_SIZE;
     time33_t index = time33(name) % VAR_HASHTABLE_SIZE;
+
+    pthread_rwlock_wrlock(&vs->lock);
     af_VarCup **pCup = &vs->var[index];
     af_VarCup **pCup = &vs->var[index];
 
 
     if (vs->is_protect)
     if (vs->is_protect)
-        return false;
+        goto RETRUN_FALSE;
 
 
     if (!checkVarSpaceDelPermissions(visitor, vs))
     if (!checkVarSpaceDelPermissions(visitor, vs))
-        return false;
+        goto RETRUN_FALSE;
 
 
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
     for (NULL; *pCup != NULL; pCup = &((*pCup)->next)) {
         if (EQ_STR((*pCup)->var->name, name)) {
         if (EQ_STR((*pCup)->var->name, name)) {
             *pCup = freeVarCup(*pCup);
             *pCup = freeVarCup(*pCup);
+            pthread_rwlock_unlock(&vs->lock);
             return true;
             return true;
         }
         }
     }
     }
 
 
+RETRUN_FALSE:
+    pthread_rwlock_unlock(&vs->lock);
     return false;
     return false;
 }
 }
 
 
@@ -320,21 +360,35 @@ bool delVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *vsl)
  * 权限检查交给 findVarFromVarSpace 和 findVarFromVarList
  * 权限检查交给 findVarFromVarSpace 和 findVarFromVarList
  */
  */
 static af_Var *findVarFromVarSpaceByIndex(time33_t index, char *name, af_VarSpace *vs) {
 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) {
     for (af_VarCup *cup = vs->var[index]; cup != NULL; cup = cup->next) {
-        if (EQ_STR(cup->var->name, name))
-            return cup->var;
+        if (EQ_STR(cup->var->name, name)) {
+            af_Var *var = cup->var;
+            pthread_rwlock_unlock(&vs->lock);
+            return var;
+        }
     }
     }
+    pthread_rwlock_unlock(&vs->lock);
     return NULL;
     return NULL;
 }
 }
 
 
+/**
+ * 检查访问者是否有读取变量的权限
+ * 注意: 会给VarSpace加读锁
+ * @param var 变量
+ * @param visitor 访问者
+ * @param vs  变量空间
+ * @return 返回是否具有读取权限
+ */
 static bool checkVarReadPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
 static bool checkVarReadPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
     char p = var->permissions[2];  // 默认外部权限
     char p = var->permissions[2];  // 默认外部权限
 
 
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
     if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = var->permissions[0];
         p = var->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = var->permissions[1];
         p = var->permissions[1];
-
+    pthread_rwlock_unlock(&vs->lock);
     return p == 1 || p == 3;
     return p == 1 || p == 3;
 }
 }
 
 
@@ -374,6 +428,14 @@ af_Var *findVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *
     return NULL;
     return NULL;
 }
 }
 
 
+/**
+ * 检查访问者是否有改写变量的权限
+ * 注意: 无锁, 由调用者加锁
+ * @param var 变量
+ * @param visitor 访问者
+ * @param vs 变量空间
+ * @return
+ */
 static bool checkVarWritePermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
 static bool checkVarWritePermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
     char p = var->permissions[2];  // 默认外部权限
     char p = var->permissions[2];  // 默认外部权限
 
 
@@ -395,10 +457,14 @@ bool setVarToVarSpace(char *name, af_Object *obj, af_Object *visitor, af_VarSpac
     if (var == NULL)
     if (var == NULL)
         return false;
         return false;
 
 
+    pthread_rwlock_wrlock(&vs->lock);
     if (checkVarWritePermissions(var, visitor, vs)) {
     if (checkVarWritePermissions(var, visitor, vs)) {
+        pthread_rwlock_wrlock(&vs->lock);
         var->vn->obj = obj;
         var->vn->obj = obj;
         return true;
         return true;
     }
     }
+
+    pthread_rwlock_unlock(&vs->lock);
     return false;
     return false;
 }
 }
 
 
@@ -414,10 +480,13 @@ bool setVarToVarList(char *name, af_Object *obj, af_Object *visitor, af_VarSpace
     for (NULL; vsl != NULL; vsl = vsl->next) {
     for (NULL; vsl != NULL; vsl = vsl->next) {
         var = findVarFromVarSpaceByIndex(index, name, vsl->vs);
         var = findVarFromVarSpaceByIndex(index, name, vsl->vs);
         if (var != NULL) {
         if (var != NULL) {
+            pthread_rwlock_wrlock(&vsl->vs->lock);
             if (checkVarWritePermissions(var, visitor, vsl->vs)) {
             if (checkVarWritePermissions(var, visitor, vsl->vs)) {
+                pthread_rwlock_wrlock(&vsl->vs->lock);
                 var->vn->obj = obj;
                 var->vn->obj = obj;
                 return true;
                 return true;
             }
             }
+            pthread_rwlock_wrlock(&vsl->vs->lock);
             return false;
             return false;
         }
         }
     }
     }
@@ -431,29 +500,43 @@ af_VarSpaceListNode *pushNewVarList(af_Object *belong, af_VarSpaceListNode *base
 }
 }
 
 
 void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
 void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->belong->data != visitor->data)
     if (vs->belong->data != visitor->data)
         return;
         return;
+    pthread_rwlock_unlock(&vs->lock);
+
     var->permissions[0] = p_self;
     var->permissions[0] = p_self;
     var->permissions[1] = p_posterity;
     var->permissions[1] = p_posterity;
     var->permissions[2] = p_external;
     var->permissions[2] = p_external;
 }
 }
 
 
 void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
 void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
+    pthread_rwlock_rdlock(&vs->lock);
     if (vs->belong->data != visitor->data)
     if (vs->belong->data != visitor->data)
         return;
         return;
+    pthread_rwlock_unlock(&vs->lock);
+
     vs->permissions[0] = p_self;
     vs->permissions[0] = p_self;
     vs->permissions[1] = p_posterity;
     vs->permissions[1] = p_posterity;
     vs->permissions[2] = p_external;
     vs->permissions[2] = p_external;
 }
 }
 
 
 bool isProtectVarSpace(af_VarSpace *vs) {
 bool isProtectVarSpace(af_VarSpace *vs) {
-    return vs->is_protect;
+    pthread_rwlock_rdlock(&vs->lock);
+    bool res = vs->is_protect;
+    pthread_rwlock_unlock(&vs->lock);
+    return res;
 }
 }
 
 
-bool setVarSpaceProtect(af_Object *visitor, af_VarSpace *vs, char protect) {
+bool setVarSpaceProtect(af_Object *visitor, af_VarSpace *vs, bool protect) {
+    pthread_rwlock_wrlock(&vs->lock);
     bool re = vs->is_protect;
     bool re = vs->is_protect;
-    if (vs->belong->data != visitor->data)
+    if (vs->belong != NULL && vs->belong->data != visitor->data) {
+        pthread_rwlock_unlock(&vs->lock);
         return re;
         return re;
+    }
+
     vs->is_protect = protect;
     vs->is_protect = protect;
+    pthread_rwlock_unlock(&vs->lock);
     return re;
     return re;
 }
 }

+ 1 - 1
src/main.c

@@ -87,7 +87,7 @@ int main(int argc, char **argv) {
     aFunAtExit(freeBaseName, NULL);
     aFunAtExit(freeBaseName, NULL);
 
 
     if (setjmp(main_buf) == 1)
     if (setjmp(main_buf) == 1)
-        aFunExit(aFunExitFail);
+        aFunExit(2);
 
 
     aFunInitInfo info = {.base_dir=base_path,
     aFunInitInfo info = {.base_dir=base_path,
 #ifdef aFunDEBUG
 #ifdef aFunDEBUG