Przeglądaj źródła

feat: 多线程支持

SongZihuan 3 lat temu
rodzic
commit
3cfe12fd67
8 zmienionych plików z 266 dodań i 25 usunięć
  1. 5 1
      include/core/env.h
  2. 1 1
      include/runtime/aFunlang.h
  3. 23 1
      src/core/__env.h
  4. 205 8
      src/core/env.c
  5. 23 5
      src/core/gc.c
  6. 3 4
      src/core/run.c
  7. 3 2
      src/runtime/aFunlang.c
  8. 3 3
      test/src/run_code.c

+ 5 - 1
include/core/env.h

@@ -31,7 +31,7 @@ enum GcRunTime {
 
 /* 运行环境 创建与释放 */
 AFUN_CORE_EXPORT af_Environment *makeEnvironment(enum GcRunTime grt);
-AFUN_CORE_EXPORT void freeEnvironment(af_Environment *env);
+AFUN_CORE_EXPORT bool freeEnvironment(af_Environment *env);
 
 /* 消息 创建与释放 */
 AFUN_CORE_EXPORT af_Message *makeMessage(char *type, size_t size);
@@ -59,6 +59,8 @@ AFUN_CORE_EXPORT void setCoreStop(af_Environment *env);
 AFUN_CORE_EXPORT void setCoreExit(int exit_code, af_Environment *env);
 AFUN_CORE_EXPORT void setCoreNormal(af_Environment *env);
 AFUN_CORE_EXPORT void setArgc(int argc, af_Environment *env);
+AFUN_CORE_EXPORT void setEnviromentExit_out(af_Environment *env);
+AFUN_CORE_EXPORT void waitForEnviromentExit(af_Environment *env);
 
 /* 消息 相关操作 */
 AFUN_CORE_EXPORT void pushMessageUp(af_Message *msg, af_Environment *env);
@@ -116,6 +118,8 @@ AFUN_CORE_EXPORT int isCoreExit(af_Environment *env);
 AFUN_CORE_EXPORT bool getErrorStd(af_Environment *env);
 AFUN_CORE_EXPORT int32_t getCoreExitCode(af_Environment *env);
 AFUN_CORE_EXPORT af_Object *getActivityFunc(af_Environment *env);
+AFUN_CORE_EXPORT bool isEnviromentExit(af_Environment *env);
+AFUN_CORE_EXPORT size_t getEnviromentSonCount(af_Environment *env);
 
 /* 消息 属性访问 */
 AFUN_CORE_EXPORT af_Object *getMsgNormalData(af_Message *msg);

+ 1 - 1
include/runtime/aFunlang.h

@@ -25,7 +25,7 @@ AFUN_LANG_EXPORT void defineRunEnv(aFunRunInfo *run_env);
 AFUN_LANG_EXPORT void undefRunEnv(aFunRunInfo *run_env);
 
 AFUN_LANG_EXPORT af_Environment *creatAFunEnvironment(int argc, char **argv);
-AFUN_LANG_EXPORT void destructAFunEnvironment(af_Environment *env);
+AFUN_LANG_EXPORT bool destructAFunEnvironment(af_Environment *env);
 
 /* 源文件运行 */
 AFUN_LANG_EXPORT int runCodeFromString(char *code, char *string_name, int mode, af_Environment *env);

+ 23 - 1
src/core/__env.h

@@ -12,7 +12,7 @@ typedef struct af_Guardian af_Guardian;
 typedef struct af_LiteralDataList af_LiteralDataList;
 typedef struct af_LiteralRegex af_LiteralRegex;
 typedef struct af_ErrorBacktracking af_ErrorBacktracking;
-
+typedef struct af_EnvironmentList af_EnvironmentList;
 
 #include "env.h"
 #include "__object.h"
@@ -196,11 +196,28 @@ struct af_EnvVarSpace {  // 环境变量
     pthread_rwlock_t lock;
 };
 
+struct af_EnvironmentList {
+    size_t id;
+    struct af_Environment *env;
+    struct af_EnvironmentList *next;
+    struct af_EnvironmentList *prev;
+};
+
 struct af_Environment {  // 运行环境
+    bool is_derive;  // 是否派生
+    struct af_Environment *base;  // 主线程
+
+    struct af_Object *result;  // 线程执行的结果
+    struct af_EnvironmentList *env_list;  // 主线程记录所有的子线程
+    bool all_exit;  // 由线程自己控制, 用于通知子线程退出
+    bool son_exit;  // 由线程外部控制, 命令线程结束
+    pthread_mutex_t thread_lock;  // 保护 father_exit 和 son_exit 和 son_count
+
     enum af_CoreStatus {
         core_creat = 0,
         core_init,  // 执行初始化程序
         core_normal,  // 正常执行
+        core_normal_gc,  // 正常执行
         core_stop,  // 当前运算退出
         core_exit,  // 解释器退出
     } status;
@@ -234,6 +251,7 @@ struct af_Environment {  // 运行环境
 
 struct af_LiteralRegex {
     af_Regex *rg;
+    char *pattern;  // 派生 LiteralRegex 时实用
     char *func;  // 调用的函数
     bool in_protect;  // 是否在protect空间
     struct af_LiteralRegex *next;
@@ -308,4 +326,8 @@ AFUN_CORE_NO_EXPORT af_EnvVar *setEnvVarData_(char *name, char *data, af_Environ
 /* af_GuardianList管理函数 */
 AFUN_CORE_NO_EXPORT af_GuardianList **contectGuardianList(af_GuardianList *new, af_GuardianList **base);
 
+/* EnvironmentList 管理函数 */
+AFUN_CORE_NO_EXPORT bool freeEnvironmentListByEnv(af_Environment *env, af_Environment *base);
+AFUN_CORE_NO_EXPORT bool pushEnvironmentList(af_Environment *env, af_Environment *base);
+
 #endif //AFUN_ENV_H_

+ 205 - 8
src/core/env.c

@@ -57,6 +57,10 @@ static af_LiteralRegex *makeLiteralRegex(char *pattern, char *func, bool in_prot
 static af_LiteralRegex *freeLiteralRegex(af_LiteralRegex *lr);
 static void freeAllLiteralRegex(af_LiteralRegex *lr);
 
+/* EnvironmentList 创建与释放 */
+static af_EnvironmentList *makeEnvironmentList(af_Environment *env);
+static bool freeEnvironmentList(af_EnvironmentList *envl, af_Environment *env);
+
 /* af_ErrorBacktracking 创建与释放 */
 static af_ErrorBacktracking *makeErrorBacktracking(FileLine line, FilePath file, char *note);
 static af_ErrorBacktracking *freeErrorBacktracking(af_ErrorBacktracking *ebt);
@@ -718,6 +722,21 @@ static void mp_NORMAL(af_Message *msg, bool is_top, af_Environment *env) {
         writeDebugLog(aFunCoreLogger, "NORMAL Point: %p", *(af_Object **)msg->msg);
 }
 
+static void mp_NORMALThread(af_Message *msg, bool is_top, af_Environment *env) {
+    if (msg->msg == NULL || *(af_Object **)msg->msg == NULL) {
+        writeErrorLog(aFunCoreLogger, "Thread-NORMAL msg: %p error", msg->msg);
+        return;
+    }
+
+    pthread_mutex_lock(&env->thread_lock);
+    env->result = *(af_Object **)msg->msg;
+    gc_delReference(env->result);
+    pthread_mutex_unlock(&env->thread_lock);
+
+    if (is_top)
+        writeDebugLog(aFunCoreLogger, "Thread-NORMAL Point: %p", *(af_Object **)msg->msg);
+}
+
 static void mp_ERROR(af_Message *msg, bool is_top, af_Environment *env) {
     if (msg->msg == NULL || *(af_ErrorInfo **)msg->msg == NULL) {
         writeErrorLog(aFunCoreLogger, "ERROR msg: %p error", msg->msg);
@@ -826,6 +845,9 @@ af_Environment *makeEnvironment(enum GcRunTime grt) {
     pthread_mutex_init(&env->in_run, &attr);  // 检测锁
     pthread_mutexattr_destroy(&attr);
 
+    env->is_derive = false;
+    env->base = env;
+
     env->gc_factory = makegGcFactory();
     env->esv = makeEnvVarSpace();
 
@@ -873,6 +895,70 @@ af_Environment *makeEnvironment(enum GcRunTime grt) {
 
     env->status = core_init;
     env->activity = makeTopActivity(NULL, NULL, env->protect, env->global);
+    pthread_mutex_init(&env->thread_lock, NULL);
+    return env;
+}
+
+af_Environment *deriveEnvironment(bool derive_tmp, bool derive_guardian, bool derive_lr, bool enable,
+                                  af_Environment *base) {
+    af_Environment *env = calloc(1, sizeof(af_Environment));
+
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+    pthread_mutex_init(&env->in_run, &attr);  // 检测锁
+    pthread_mutexattr_destroy(&attr);
+
+    env->is_derive = true;
+    env->base = base->base;
+    pushEnvironmentList(env, base);
+
+#define D(v) env->v = (env->base)->v
+    D(gc_factory);
+    D(esv);
+    D(prefix);
+    D(gc_runtime);
+    D(gc_max);
+    D(gc_count);
+    D(exit_code_);
+    D(argc);
+    D(error_std);
+    D(protect);
+    D(global);
+#undef D
+
+    if (derive_tmp) {
+        for (af_TopMsgProcess *tmp = base->process; tmp != NULL; tmp = tmp->next)
+            addTopMsgProcess(tmp->type, tmp->func, env);
+    }
+
+    DLC_SYMBOL(TopMsgProcessFunc) func1 = MAKE_SYMBOL(mp_NORMALThread, TopMsgProcessFunc);
+    af_TopMsgProcess *tmp = findTopMsgProcessFunc("NORMAL", env);
+    if (tmp == NULL) {
+        addTopMsgProcess("NORMAL", func1, env);
+        FREE_SYMBOL(func1);
+    } else {
+        FREE_SYMBOL(tmp->func);
+        tmp->func = func1;
+    }
+
+    if (derive_guardian) {
+        for (af_Guardian *gu = base->guardian; gu != NULL; gu = gu->next)
+            addGuardian(gu->type, gu->always, gu->size, gu->func, gu->destruct, NULL, env);
+    }
+
+    if (derive_lr) {
+        for (af_LiteralRegex *lr = base->lr; lr != NULL; lr = lr->next)
+            pushLiteralRegex(lr->pattern, lr->func, lr->in_protect, env);
+    }
+
+    if (enable)
+        env->status = core_normal;
+    else
+        env->status = core_init;
+
+    env->activity = makeTopActivity(NULL, NULL, env->protect, env->global);
+    pthread_mutex_init(&env->thread_lock, NULL);
     return env;
 }
 
@@ -881,26 +967,35 @@ void enableEnvironment(af_Environment *env) {
     env->status = core_normal;
 }
 
-void freeEnvironment(af_Environment *env) {
+bool freeEnvironment(af_Environment *env) {
     bool res = true;
+    if (getEnviromentSonCount(env) != 0)
+        return false;
+
     if (env->status != core_creat)
         res = iterDestruct(10, env);
 
     freeAllActivity(env->activity);
-    freeEnvVarSpace(env->esv);
     freeAllTopMsgProcess(env->process);
     freeAllGuardian(env->guardian, env);
-
-    pthread_mutex_destroy(&env->in_run);
     freeAllLiteralRegex(env->lr);
-    gc_freeAllValueData(env);  // 先释放ObjectData的void *data
-    printGCByCore(env);
-    gc_freeAllValue(env);  // 再完全释放Object
-    freeGcFactory(env->gc_factory);
 
+    if (!env->is_derive) {
+        freeEnvVarSpace(env->esv);
+
+        gc_freeAllValueData(env);  // 先释放ObjectData的void *data
+        printGCByCore(env);
+        gc_freeAllValue(env);  // 再完全释放Object
+        freeGcFactory(env->gc_factory);
+    } else
+        freeEnvironmentListByEnv(env, env->base);
+
+    pthread_mutex_destroy(&env->in_run);
+    pthread_mutex_destroy(&env->thread_lock);
     if (!res)
         writeErrorLog(aFunCoreLogger, "Run iterDestruct error.");
     free(env);
+    return true;
 }
 
 static af_TopMsgProcess *makeTopMsgProcess(char *type, DLC_SYMBOL(TopMsgProcessFunc) func) {
@@ -1531,6 +1626,7 @@ static af_LiteralRegex *makeLiteralRegex(char *pattern, char *func, bool in_prot
 
     af_LiteralRegex *lr = calloc(1, sizeof(af_LiteralRegex));
     lr->rg = rg;
+    lr->pattern = strCopy(pattern);
     lr->func = strCopy(func);
     lr->in_protect = in_protect;
     return lr;
@@ -1540,6 +1636,7 @@ static af_LiteralRegex *freeLiteralRegex(af_LiteralRegex *lr) {
     af_LiteralRegex *next = lr->next;
     freeRegex(lr->rg);
     free(lr->func);
+    free(lr->pattern);
     free(lr);
     return next;
 }
@@ -1576,6 +1673,55 @@ bool checkLiteralCode(char *literal, char **func, bool *in_protect, af_Environme
     return false;
 }
 
+static af_EnvironmentList *makeEnvironmentList(af_Environment *env) {
+    static size_t id = 0;
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+    af_EnvironmentList *envl = calloc(1, sizeof(af_EnvironmentList));
+    envl->env = env;
+
+    pthread_mutex_lock(&mutex);
+    envl->id = id;
+    id++;
+    pthread_mutex_unlock(&mutex);
+    return envl;
+}
+
+static bool freeEnvironmentList(af_EnvironmentList *envl, af_Environment *env) {
+    pthread_mutex_lock(&env->thread_lock);
+    if (envl->prev == NULL)
+        env->env_list = envl->next;
+    else
+        envl->prev->next = envl->next;
+
+    if (envl->next != NULL)
+        envl->next->prev = envl->prev;
+
+    pthread_mutex_unlock(&env->thread_lock);
+    free(envl);
+    return true;
+}
+
+bool freeEnvironmentListByEnv(af_Environment *env, af_Environment *base) {
+    pthread_mutex_lock(&base->thread_lock);
+    for (af_EnvironmentList *envl = base->env_list; envl != NULL; envl = envl->next) {
+        if (envl->env == env) {
+            pthread_mutex_unlock(&base->thread_lock);
+            return freeEnvironmentList(envl, base);
+        }
+    }
+    pthread_mutex_unlock(&base->thread_lock);
+    return false;
+}
+
+bool pushEnvironmentList(af_Environment *env, af_Environment *base) {
+    af_EnvironmentList *envl = makeEnvironmentList(env);
+    pthread_mutex_lock(&env->thread_lock);
+    envl->next = base->env_list;
+    base->env_list = envl;
+    pthread_mutex_unlock(&env->thread_lock);
+}
+
 af_ErrorInfo *makeErrorInfo(char *type, char *error, char *note, FileLine line, FilePath path) {
     af_ErrorInfo *ei = calloc(1, sizeof(af_ErrorInfo));
     ei->error_type = strCopy(type);
@@ -2022,3 +2168,54 @@ af_Object *getActivityFunc(af_Environment *env) {
         return NULL;
     return env->activity->func;
 }
+
+size_t getEnviromentSonCount(af_Environment *env) {
+    pthread_mutex_lock(&env->thread_lock);
+    size_t res = 0;
+    for (af_EnvironmentList *envl = env->env_list; envl != NULL; envl = envl->next)
+        res++;
+    pthread_mutex_unlock(&env->thread_lock);
+    return res;
+}
+
+/**
+ * 线程外部 指示线程结束
+ * @param env
+ */
+void setEnviromentExit_out(af_Environment *env) {
+    pthread_mutex_lock(&env->thread_lock);
+    env->son_exit = true;
+    pthread_mutex_unlock(&env->thread_lock);
+}
+
+bool isEnviromentExit(af_Environment *env) {
+    pthread_mutex_lock(&env->thread_lock);
+    bool res = env->son_exit == true;  // 线程外部指示线程结束
+    af_Environment *base = env->base;
+    pthread_mutex_unlock(&env->thread_lock);
+    if (res)
+        return true;
+
+    pthread_mutex_lock(&base->thread_lock);
+    res = base->status == core_exit || base->status == core_normal_gc;  // 主线程结束
+    pthread_mutex_unlock(&base->thread_lock);
+    return res;
+}
+
+/**
+ * 等待次线程结束
+ * @param env
+ */
+void waitForEnviromentExit(af_Environment *env) {
+    env->status = core_exit;  // 不需要设置 exit_code
+
+    while (1) {
+        pthread_mutex_lock(&env->thread_lock);
+        if (env->env_list == NULL) {
+            pthread_mutex_unlock(&env->thread_lock);
+            break;
+        }
+        pthread_mutex_unlock(&env->thread_lock);
+        safeSleep(0.01);
+    }
+}

+ 23 - 5
src/core/gc.c

@@ -182,6 +182,7 @@ static pgc_Analyzed reachableObject(struct af_Object *obj, pgc_Analyzed plist);
 static void freeValue(af_Environment *env);
 static pgc_Analyzed reachable(af_Activity *activity, pgc_Analyzed plist);
 static pgc_Analyzed iterLinker(af_Environment *env, pgc_Analyzed plist);
+static pgc_Analyzed iterEnvironment(af_Environment *env, pgc_Analyzed plist);
 static pgc_Analyzed checkDestruct(af_Environment *env, paf_GuardianList *pgl, pgc_Analyzed plist);
 static pgc_Analyzed checkAnalyzed(gc_Analyzed *analyzed, pgc_Analyzed plist);
 
@@ -320,6 +321,16 @@ static pgc_Analyzed iterLinker(af_Environment *env, pgc_Analyzed plist) {
     return plist;
 }
 
+static pgc_Analyzed iterEnvironment(af_Environment *env, pgc_Analyzed plist) {
+    pthread_mutex_lock(&env->thread_lock);
+    if (env->result != NULL)
+        plist = reachableObject(env->result, plist);
+    pthread_mutex_unlock(&env->thread_lock);
+
+    plist = reachable(env->activity, plist);
+    return plist;
+}
+
 static pgc_Analyzed reachable(af_Activity *activity, pgc_Analyzed plist) {
     for (NULL; activity != NULL; activity = activity->prev) {
         if (activity->belong != NULL)
@@ -438,15 +449,22 @@ af_GuardianList *gc_RunGC(af_Environment *env) {
     af_GuardianList *gl = NULL;
     pgc_Analyzed plist = &analyzed;
     paf_GuardianList pgl = ≷
-    resetGC(env);
+    af_Environment *base = env->base;
+
+    resetGC(base);
+    plist = iterLinker(base, plist);  // 临时量分析 (临时量都是通过reference标记的)
+    plist = iterEnvironment(base, plist);
+
+    pthread_mutex_lock(&base->thread_lock);
+    for (af_EnvironmentList *envl = base->env_list; envl != NULL; envl = envl->next)
+        plist = iterEnvironment(envl->env, plist);
+    pthread_mutex_unlock(&base->thread_lock);
 
-    plist = iterLinker(env, plist);  // 临时量分析 (临时量都是通过reference标记的)
-    plist = reachable(env->activity, plist);
     plist = checkAnalyzed(analyzed, plist);  // 先处理剩余的Object
-    plist = checkDestruct(env, &pgl, plist);  // 在检查析构
+    plist = checkDestruct(base, &pgl, plist);  // 在检查析构
     checkAnalyzed(analyzed, plist);  // 在处理 checkDestruct 时产生的新引用
 
-    freeValue(env);
+    freeValue(base);
     freeAllAnalyzed(analyzed);
     return gl;
 }

+ 3 - 4
src/core/run.c

@@ -101,14 +101,12 @@ static int checkMacro(af_Message *msg, af_Environment *env) {
 static bool iterCodeInit(af_Code *code, int mode, af_Environment *env) {
     if (env == NULL || pthread_mutex_trylock(&env->in_run) != 0)
         return false;
-    if (env->activity == NULL || env->status == core_exit) {
+    if (env->activity == NULL) {
         pthread_mutex_unlock(&env->in_run);
         return false;
     }
 
-    if (env->status == core_stop)
-        env->status = core_normal;
-
+    env->status = core_normal_gc;
     switch (mode) {
         case 0:
             if (env->activity->type != act_top || !codeSemanticCheck(code))
@@ -512,5 +510,6 @@ bool iterDestruct(int deep, af_Environment *env) {
         if (!iterCode(NULL, 3, env))
             return false;
     }
+    env->status = core_exit;
     return false;
 }

+ 3 - 2
src/runtime/aFunlang.c

@@ -93,8 +93,9 @@ af_Environment *creatAFunEnvironment(int argc, char **argv){
     return env;
 }
 
-void destructAFunEnvironment(af_Environment *env) {
-    freeEnvironment(env);
+bool destructAFunEnvironment(af_Environment *env) {
+    waitForEnviromentExit(env);
+    return freeEnvironment(env);
 }
 
 static int runCode_(af_Parser *parser, int mode, FilePath save_path, af_Environment *env){

+ 3 - 3
test/src/run_code.c

@@ -1302,7 +1302,7 @@ INIT_ERROR:
     destructAFunEnvironment(env);
 
     undefRunEnv(&ri);
-    printf("Exit at 0.");
+    printf("Exit at 0.\n");
 #ifndef IN_CTEST
     getc(stdin);
 #endif
@@ -1311,7 +1311,7 @@ INIT_ERROR:
 
 RETURN_1:
     undefRunEnv(&ri);
-    printf("Exit at 1.");
+    printf("Exit at 1.\n");
 #ifndef IN_CTEST
     getc(stdin);
 #endif
@@ -1320,7 +1320,7 @@ RETURN_1:
 
 RETURN_2:
     undefRunEnv(&ri);
-    printf("Exit at 2.");
+    printf("Exit at 2.\n");
 #ifndef IN_CTEST
     getc(stdin);
 #endif