Browse Source

feat: 新增监视线程模块

SongZihuan 3 years ago
parent
commit
f9457b2bcf
6 changed files with 105 additions and 8 deletions
  1. 1 0
      include/core/env.h
  2. 4 1
      src/core/__env.h
  3. 20 0
      src/core/__monitor.h
  4. 25 6
      src/core/env.c
  5. 52 0
      src/core/monitor.c
  6. 3 1
      src/core/run.c

+ 1 - 0
include/core/env.h

@@ -57,6 +57,7 @@ AFUN_CORE_EXPORT void setGcRun(enum GcRunTime grt, af_Environment *env);
 AFUN_CORE_EXPORT char setPrefix(size_t name, char prefix, af_Environment *env);
 AFUN_CORE_EXPORT void setCoreStop(af_Environment *env);
 AFUN_CORE_EXPORT void setCoreExit(int exit_code, af_Environment *env);
+AFUN_CORE_EXPORT void setCoreExitNotExitCode(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);

+ 4 - 1
src/core/__env.h

@@ -20,6 +20,7 @@ typedef struct af_EnvironmentList af_EnvironmentList;
 #include "__code.h"
 #include "__gc.h"
 #include "__func.h"
+#include "__monitor.h"
 #include "regex.h"
 
 #define DEFAULT_GC_COUNT_MAX (50)
@@ -206,6 +207,8 @@ struct af_EnvironmentList {
 };
 
 struct af_Environment {  // 运行环境
+    af_Monitor *monitor;  // 监视器线程
+
     bool is_derive;  // 是否派生
     struct af_Environment *base;  // 主线程
 
@@ -331,6 +334,6 @@ AFUN_CORE_NO_EXPORT af_GuardianList **contectGuardianList(af_GuardianList *new,
 
 /* 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);
+AFUN_CORE_NO_EXPORT void pushEnvironmentList(af_Environment *env, af_Environment *base);
 
 #endif //AFUN_ENV_H_

+ 20 - 0
src/core/__monitor.h

@@ -0,0 +1,20 @@
+#ifndef AFUN___MONITOR_H
+#define AFUN___MONITOR_H
+#include "pthread.h"
+#include "macro.h"
+
+typedef struct af_Monitor af_Monitor;
+struct af_Monitor {
+    struct af_Environment *env;
+    pthread_t thread;
+    bool exit;  // 外部通知守护线程结束
+    pthread_mutex_t lock;
+    pthread_cond_t cond;
+};
+
+
+#include "__env.h"
+AFUN_CORE_NO_EXPORT af_Monitor *makeMonitor(af_Environment *env);
+AFUN_CORE_NO_EXPORT void freeMonitor(af_Environment *env);
+
+#endif //AFUN___MONITOR_H

+ 25 - 6
src/core/env.c

@@ -157,13 +157,28 @@ void setCoreStop(af_Environment *env) {
 }
 
 void setCoreExit(int exit_code, af_Environment *env) {
+    pthread_rwlock_wrlock(&env->esv->lock);
+    env->exit_code_->num = exit_code;
+    pthread_rwlock_unlock(&env->esv->lock);
+
+    setCoreExitNotExitCode(env);
+}
+
+void setCoreExitNotExitCode(af_Environment *env) {
     pthread_mutex_lock(&env->status_lock);
     env->status = core_exit;
     pthread_mutex_unlock(&env->status_lock);
 
-    pthread_rwlock_wrlock(&env->esv->lock);
-    env->exit_code_->num = exit_code;
-    pthread_rwlock_unlock(&env->esv->lock);
+    if (env == env->base) {  // 若是主线程, 通知所有次线程
+        pthread_mutex_lock(&env->thread_lock);
+        for (af_EnvironmentList *envl = env->env_list; envl != NULL; envl = envl->next) {
+            pthread_mutex_lock(&envl->env->thread_lock);
+            if (envl->env->monitor != NULL)
+                pthread_cond_signal(&envl->env->monitor->cond);
+            pthread_mutex_unlock(&envl->env->thread_lock);
+        }
+        pthread_mutex_lock(&env->thread_lock);
+    }
 }
 
 void setCoreNormal(af_Environment *env) {
@@ -1757,7 +1772,7 @@ bool freeEnvironmentListByEnv(af_Environment *env, af_Environment *base) {
     return false;
 }
 
-bool pushEnvironmentList(af_Environment *env, af_Environment *base) {
+void pushEnvironmentList(af_Environment *env, af_Environment *base) {
     af_EnvironmentList *envl = makeEnvironmentList(env);
     pthread_mutex_lock(&env->thread_lock);
     envl->next = base->env_list;
@@ -2236,6 +2251,8 @@ enum af_CoreStatus getCoreStatus(af_Environment *env) {
 void setEnviromentExit_out(af_Environment *env) {
     pthread_mutex_lock(&env->thread_lock);
     env->son_exit = true;
+    if (env->monitor != NULL)
+        pthread_cond_signal(&env->monitor->cond);
     pthread_mutex_unlock(&env->thread_lock);
 }
 
@@ -2246,6 +2263,8 @@ bool isEnviromentExit(af_Environment *env) {
     pthread_mutex_unlock(&env->thread_lock);
     if (res)
         return true;
+    else if (env == base)
+        return false;
 
     enum af_CoreStatus status = getCoreStatus(base);
     res = status == core_exit || status == core_normal_gc;  // 主线程结束
@@ -2262,12 +2281,12 @@ void waitForEnviromentExit(af_Environment *env) {
     pthread_mutex_unlock(&env->status_lock);
 
     while (1) {
-        pthread_mutex_lock(&env->thread_lock);
+        pthread_mutex_lock(&env->thread_lock);  // TODO-szh 改用信号
         if (env->env_list == NULL) {
             pthread_mutex_unlock(&env->thread_lock);
             break;
         }
         pthread_mutex_unlock(&env->thread_lock);
-        safeSleep(0.01);
+        safeSleep(0.1);  // 不易设置太小
     }
 }

+ 52 - 0
src/core/monitor.c

@@ -0,0 +1,52 @@
+#include "__monitor.h"
+#include "__env.h"
+
+static void *monitorProgress(void *m);
+
+af_Monitor *makeMonitor(af_Environment *env) {
+    af_Monitor *monitor = calloc(1, sizeof(af_Monitor));
+    monitor->env = env;
+    pthread_mutex_init(&monitor->lock, NULL);
+    pthread_cond_init(&monitor->cond, NULL);
+
+    env->monitor = monitor;
+    pthread_create(&monitor->thread, NULL, monitorProgress, monitor);
+    return monitor;
+}
+
+void freeMonitor(af_Environment *env) {
+    af_Monitor *monitor = env->monitor;
+
+    pthread_mutex_lock(&monitor->lock);
+    monitor->exit = true;
+    pthread_mutex_unlock(&monitor->lock);
+    pthread_cond_signal(&monitor->cond);
+
+    pthread_join(monitor->thread, NULL);
+
+    pthread_mutex_lock(&env->thread_lock);
+    pthread_cond_destroy(&monitor->cond);
+    pthread_mutex_destroy(&monitor->lock);
+    free(monitor);
+    env->monitor = NULL;
+    pthread_mutex_unlock(&env->thread_lock);
+}
+
+static void *monitorProgress(void *m) {
+    af_Monitor *monitor = m;
+    af_Environment *env = monitor->env;
+    pthread_mutex_lock(&monitor->lock);
+    while (1) {
+        if (isEnviromentExit(env)) {
+            pthread_mutex_lock(&monitor->env->status_lock);
+            monitor->env->status = core_exit;
+            pthread_mutex_unlock(&monitor->env->status_lock);
+        }
+
+        pthread_cond_wait(&monitor->cond, &monitor->lock);
+        if (monitor->exit)
+            break;
+    }
+    pthread_mutex_unlock(&monitor->lock);
+    return NULL;
+}

+ 3 - 1
src/core/run.c

@@ -1,6 +1,7 @@
 #include "aFunCore.h"
 #include "__run.h"
 #include "__env.h"
+#include "__monitor.h"
 
 /* 工具函数: 初始化类型 */
 static bool iterCodeInit(af_Code *code, int mode, af_Environment *env);
@@ -362,7 +363,7 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
     if (!iterCodeInit(code, mode, env))
         return false;
     bool re = true;
-
+    af_Monitor *monitor = makeMonitor(env);
     /*
      * 问题: 如何确保循环跳出之前, top-Activity已经被pop。(即执行释放)
      * 为什么会有这个问题: top-Activity只有在bt_next=NULL时被pop, 而循环也是在bt_next=NULL时可能被退出
@@ -502,6 +503,7 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
 
 RETURN:
     pthread_mutex_unlock(&env->in_run);
+    freeMonitor(env);
     return re;
 }