فهرست منبع

refactor & feat: 预备GC机制

SongZihuan 3 سال پیش
والد
کامیت
cebb5dadf9

+ 3 - 0
include/core/gc.h

@@ -14,10 +14,13 @@ namespace aFuncore {
 
         inline void addReference();
         inline void delReference();
+        inline GcCount getReference() const;
         inline void setClear(bool clear=false);
         inline void setReachable(bool is_reference=false);
 
     protected:
+        std::mutex lock;
+
         inline GcObjectBase();
         virtual ~GcObjectBase() = default;
 

+ 7 - 1
include/core/gc.inline.h

@@ -3,18 +3,24 @@
 #include "gc.h"
 
 namespace aFuncore {
-    inline GcObjectBase::GcObjectBase() : not_clear{false}, reference{0}, reachable{false} {
+    inline GcObjectBase::GcObjectBase() : not_clear{false}, reference{1}, reachable{false} {
 
     }
 
     inline void GcObjectBase::addReference() {
+        std::unique_lock<std::mutex> mutex{lock};
         reference++;
     }
 
     inline void GcObjectBase::delReference() {
+        std::unique_lock<std::mutex> mutex{lock};
         reference--;
     }
 
+    inline GcCount GcObjectBase::getReference() const {
+        return reference;
+    }
+
     inline void GcObjectBase::setClear(bool clear) {
         not_clear=!clear;
     }

+ 1 - 1
include/core/inter.h

@@ -24,7 +24,7 @@ namespace aFuncore {
         friend class Inter;
 
     public:
-        Environment(int argc = 0, char **argv = nullptr);
+        explicit Environment(int argc = 0, char **argv = nullptr);
         ~Environment() noexcept(false);
         Environment(Environment &) = delete;
         Environment &operator=(Environment &) = delete;

+ 1 - 1
include/core/msg.h

@@ -26,7 +26,7 @@ namespace aFuncore {
 
     class AFUN_CORE_EXPORT NormalMessage : public TopMessage {
     public:
-        explicit inline NormalMessage(Object *obj_);
+        explicit NormalMessage(Object *obj_);
         inline NormalMessage(NormalMessage &&msg) noexcept;
         ~NormalMessage() override;
         void topProgress(Inter &inter, Activation &activation) override;

+ 0 - 4
include/core/msg.inline.h

@@ -3,10 +3,6 @@
 #include "msg.h"
 
 namespace aFuncore {
-    inline NormalMessage::NormalMessage(Object *obj_) : obj {obj_} {
-
-    }
-
     inline NormalMessage::NormalMessage(NormalMessage &&msg) noexcept : obj {msg.obj}{
         msg.obj = nullptr;
     }

+ 1 - 4
include/core/value.h

@@ -16,10 +16,7 @@ namespace aFuncore {
 
         Object(std::string type_, Inter &inter);
         Object(std::string type_, Environment &env_);
-        ~Object() override = default;
-
-    protected:
-        std::mutex lock;
+        ~Object() override;
     };
 
     class AFUN_CORE_EXPORT Function : public virtual Object {

+ 2 - 8
include/core/var.h

@@ -17,14 +17,11 @@ namespace aFuncore {
 
         Var(Object *data_, Inter &inter);
         Var(Object *data_, Environment &env_);
-        ~Var() override = default;
+        ~Var() override;
 
         [[nodiscard]] inline virtual Object *getData();
         virtual void inline setData(Object *data_);
 
-    protected:
-        std::mutex lock;
-
     private:
         Object *data;
     };
@@ -42,7 +39,7 @@ namespace aFuncore {
 
         explicit VarSpace(Inter &inter);
         explicit VarSpace(Environment &env_);
-        ~VarSpace() override = default;
+        ~VarSpace() override;
 
         template <typename Callable,typename...T>
         void forEach(Callable func, T...arg);
@@ -61,9 +58,6 @@ namespace aFuncore {
 
         static const size_t VAR_HASH_SIZE = 100;  // 环境变量哈希表大小
 
-    protected:
-        std::mutex lock;
-
     private:
         std::unordered_map<std::string, Var *> var;
     };

+ 10 - 4
src/core/activation.cpp

@@ -54,6 +54,7 @@ namespace aFuncore {
         if (code_type == Code::ByteCode::code_start) {  // start 不处理 msg
             auto *none = new Object("None", inter);
             down.pushMessage("NORMAL", new NormalMessage(none));
+            none->delReference();
         } else {
             if (code_type == Code::ByteCode::code_element) {
                 runCodeElement(code);
@@ -142,14 +143,17 @@ namespace aFuncore {
 
     }
 
-    FuncActivation::~FuncActivation(){
-        delete call_func;
-    }
-
     FuncActivation::FuncActivation(Function *func_, Inter &inter_) : Activation(inter_), call{nullptr} {
         on_tail = false;  // 跳过所有阶段
         status = func_get_func;
         func = func_;
+        func->addReference();
+    }
+
+    FuncActivation::~FuncActivation(){
+        if (func != nullptr)
+            func->delReference();
+        delete call_func;
     }
 
     Activation::ActivationStatus FuncActivation::getCode(const Code::ByteCode *&code) {
@@ -187,6 +191,7 @@ namespace aFuncore {
                         func = dynamic_cast<Function *>(obj);
                         if (func == nullptr || !func->isInfix())
                             continue;
+                        func->addReference();
                         status = func_get_func;
                         break;  /* 跳转到: 执行变量获取前的准备 */
                     }
@@ -218,6 +223,7 @@ namespace aFuncore {
                     down.pushMessage("ERROR", new ErrorMessage("TypeError", "Callback without function.", this));
                     return as_end;
                 }
+                func->addReference();
             }
 
             /* Label: 执行变量获取前的准备 */

+ 4 - 1
src/core/inter.cpp

@@ -106,7 +106,7 @@ namespace aFuncore {
             return false;
         }
 
-        Function *func_obj = dynamic_cast<Function *>(func);
+        auto func_obj = dynamic_cast<Function *>(func);
         if (func_obj == nullptr) {
             errorLog(aFunCoreLogger, "Run without function");
             return false;
@@ -200,6 +200,9 @@ namespace aFuncore {
 
         delete global_varlist;
 
+        protect->delReference();
+        global->delReference();
+
         Object::destruct(obj);
         Var::destruct(var);
         VarSpace::destruct(varspace);

+ 7 - 1
src/core/msg.cpp

@@ -4,8 +4,14 @@
 #include "env-var.h"
 
 namespace aFuncore {
+    NormalMessage::NormalMessage(Object *obj_) : obj {obj_} {
+        obj->addReference();
+    }
+
     NormalMessage::~NormalMessage(){
-        this->obj = nullptr;
+        if (obj != nullptr)
+            obj->delReference();
+            obj = nullptr;
     }
 
     void NormalMessage::topProgress(Inter &inter, Activation &activation){

+ 6 - 0
src/core/value.cpp

@@ -1,5 +1,6 @@
 #include "value.h"
 #include "inter.h"
+#include "init.h"
 
 namespace aFuncore {
     Object::Object(std::string type_, Inter &inter)
@@ -13,4 +14,9 @@ namespace aFuncore {
         std::unique_lock<std::mutex> mutex{env.lock};
         this->addObject(env.obj);
     }
+
+    Object::~Object() {
+        if (getReference() != 0)
+            warningLog(aFunCoreLogger, "Object %p destruct reference: %d", this, getReference());
+    }
 }

+ 14 - 1
src/core/var.cpp

@@ -1,5 +1,6 @@
 #include "var.h"
 #include "inter.h"
+#include "init.h"
 
 namespace aFuncore {
     Var::Var(Object *data_, Inter &inter) : data{data_}, env{inter.getEnvironment()}{
@@ -11,6 +12,11 @@ namespace aFuncore {
         std::unique_lock<std::mutex> mutex{env.lock};
         addObject(env.var);
     }
+
+    Var::~Var() {
+        if (getReference() != 0)
+            warningLog(aFunCoreLogger, "Var %p destruct reference: %d", this, getReference());
+    }
     
     VarSpace::VarSpace(Inter &inter) : env{inter.getEnvironment()}{
         std::unique_lock<std::mutex> mutex{env.lock};
@@ -21,6 +27,11 @@ namespace aFuncore {
         std::unique_lock<std::mutex> mutex{env.lock};
         addObject(env.varspace);
     }
+
+    VarSpace::~VarSpace() {
+        if (getReference() != 0)
+            warningLog(aFunCoreLogger, "VarSpace %p destruct reference: %d", this, getReference());
+    }
     
     /**
      * 访问指定变量
@@ -45,7 +56,9 @@ namespace aFuncore {
         std::unique_lock<std::mutex> mutex{lock};
         if (var.find(name) != var.end())
             return vof_redefine_var;
-        var.emplace(name, new Var(data, env));
+        auto new_var = new Var(data, env);
+        var.emplace(name, new_var);
+        new_var->delReference();
         return vof_success;
     }
     

+ 28 - 1
test/src/run-code.cpp

@@ -129,26 +129,30 @@ void thread_test(Inter &son) {
     fputs_stdout("\n");
 }
 
-int main() {
+int Main() {
     Environment env {};
     Inter inter {env};
 
     auto obj = new Object("Object", inter);
     inter.getGlobalVarlist()->defineVar("test-var", obj);
     aFuntool::cout << "obj: " << obj << "\n";
+    obj->delReference();
 
     auto func = new Func1(inter);
     inter.getGlobalVarlist()->defineVar("test-func", func);
     aFuntool::cout << "func: " << func << "\n";
+    func->delReference();
 
     auto literaler = new Literaler1(inter);
     inter.getGlobalVarlist()->defineVar("test-literaler", literaler);
     aFuntool::cout << "literaler: " << literaler << "\n";
+    literaler->delReference();
 
     auto cbv = new CBV1(inter);
     inter.getGlobalVarlist()->defineVar("test-cbv", cbv);
     aFuntool::cout << "cbv: " << cbv << "\n\n";
     inter.getEnvVarSpace().setNumber("sys:error_std", 1);
+    cbv->delReference();
 
     {
         fputs_stdout("Test-1: block-p & get test-var\n");
@@ -252,4 +256,27 @@ int main() {
     }
 
     return 0;
+}
+
+int main() {
+    std::string base_path = getExedir(1);
+    if (base_path.empty()) {
+        printf_stderr(0, "aFunlang init error.");
+        aFunExitReal(EXIT_FAILURE);
+    }
+
+    aFuntool::LogFactory factor {};
+    aFuncore::InitInfo info = {.base_dir=base_path,
+                               .factor=factor,
+                               .log_asyn=true,
+                               .level=log_debug,
+    };
+
+    if (!aFunCoreInit(&info)) {
+        printf_stderr(0, "aFunlang init error.");
+        aFunExitReal(EXIT_FAILURE);
+    }
+
+    int exit_code = Main();
+    aFunExitReal(exit_code);
 }