ソースを参照

refactor & feat: gc链表使用STL实现

SongZihuan 3 年 前
コミット
21a440f880

+ 5 - 3
include/core/gc.h

@@ -1,11 +1,13 @@
 #ifndef AFUN_GC_H
 #define AFUN_GC_H
+#include <queue>
+#include <list>
 #include "aFuntool.h"
 #include "aFunCoreExport.h"
-#include "queue"
 
 namespace aFuncore {
     typedef unsigned GcCount;
+    class Inter;
 
     class AFUN_CORE_EXPORT GcObjectBase {
     public:
@@ -14,10 +16,11 @@ namespace aFuncore {
 
         inline void addReference();
         inline void delReference();
-        inline GcCount getReference() const;
+        [[nodiscard]] inline GcCount getReference() const;
         inline void setClear(bool clear=false);
         inline void setReachable(bool is_reference=false);
 
+        static void destructAll(std::list<GcObjectBase *> &list, Inter &gc_inter);
     protected:
         std::mutex lock;
 
@@ -46,6 +49,5 @@ namespace aFuncore {
 };
 
 #include "gc.inline.h"
-#include "gc.template.h"
 
 #endif //AFUN_GC_H

+ 0 - 42
include/core/gc.template.h

@@ -1,42 +0,0 @@
-#ifndef AFUN_GC_TEMPLATE_H
-#define AFUN_GC_TEMPLATE_H
-
-#include "gc.h"
-
-namespace aFuncore {
-    template<class T>
-    class GcObject : public GcObjectBase {
-        T *prev;
-        T *next;
-    protected:
-        GcObject() : GcObjectBase(), prev{nullptr}, next{nullptr}{}
-
-    public:
-        void addObject(T *&chain){
-            if (chain != nullptr) {
-                next = chain;
-                chain->prev = dynamic_cast<T *>(this);
-            }
-            chain = dynamic_cast<T *>(this);
-        }
-
-        void delObject(T *&chain){
-            if (next != nullptr)
-                next->prev = prev;
-
-            if (prev == nullptr)
-                chain = next;
-            else
-                prev->next = next;
-        }
-
-        static void destruct(T *&chain){
-            for (T *tmp = chain, *n; tmp != nullptr; tmp = n) {
-                n = tmp->next;
-                delete tmp;
-            }
-        }
-    };
-}
-
-#endif //AFUN_GC_TEMPLATE_H

+ 5 - 4
include/core/inter.h

@@ -11,11 +11,13 @@
 
 namespace aFuncore {
     class Activation;
+    class GcObjectBase;
     class Var;
     class ProtectVarSpace;
     class VarSpace;
     class VarList;
     class Object;
+    class Inter;
 
     class AFUN_CORE_EXPORT Environment {
         friend class Object;
@@ -35,12 +37,11 @@ namespace aFuncore {
         inline size_t operator--(int);
 
     private:
-        Object *obj;
-        Var *var;
-        VarSpace *varspace;
+        std::mutex lock;
         size_t reference;  // 引用计数
         bool destruct;
-        std::mutex lock;
+        std::list<GcObjectBase *> gc;
+        Inter &gc_inter;  /* 需要在lock和reference后初始化 */
 
         ProtectVarSpace *const protect;  // 保护变量空间
         VarSpace *const global;  // 全局变量空间

+ 1 - 1
include/core/value.h

@@ -9,7 +9,7 @@
 #include "inter.h"
 
 namespace aFuncore {
-    class AFUN_CORE_EXPORT Object : public GcObject<class Object> {
+    class AFUN_CORE_EXPORT Object : public GcObjectBase {
     public:
         Environment &env;
         const std::string type;  // 标识 Object 的字符串

+ 2 - 2
include/core/var.h

@@ -11,7 +11,7 @@
 namespace aFuncore {
     class Object;
 
-    class AFUN_CORE_EXPORT Var : public GcObject<class Var> {
+    class AFUN_CORE_EXPORT Var : public GcObjectBase {
     public:
         Environment &env;
 
@@ -26,7 +26,7 @@ namespace aFuncore {
         Object *data;
     };
 
-    class AFUN_CORE_EXPORT VarSpace : public GcObject<class VarSpace> {
+    class AFUN_CORE_EXPORT VarSpace : public GcObjectBase {
     public:
         typedef enum VarOperationFlat {
             vof_success = 0,  // 成功

+ 8 - 0
src/core/gc.cpp

@@ -1,6 +1,14 @@
 #include "gc.h"
+#include "inter.h"
 
 namespace aFuncore {
+    void GcObjectBase::destructAll(std::list<GcObjectBase *>& list, Inter &gc_inter) {
+        for (auto obj : list) {
+            delete obj;
+        }
+        list.clear();
+    }
+
     size_t GcList::add(GcObjectBase *obj){
         queue.push(obj);
         return queue.size();

+ 18 - 16
src/core/inter.cpp

@@ -172,11 +172,11 @@ namespace aFuncore {
     }
 
     Environment::Environment(int argc, char **argv)
-        : obj{nullptr}, var{nullptr}, varspace{nullptr},
+        : reference{0}, gc_inter{*(new Inter(*this))},
           protect{new ProtectVarSpace(*this)}, global{new VarSpace(*this)},
           global_varlist{new VarList(protect)}, destruct{false} {
         global_varlist->push(global);
-        reference = 0;
+        /* 生成 gc_inter 后, reference == 1 */
 
         envvar.setNumber("sys:gc-runtime", 2);
         envvar.setString("sys:prefix", "''");  // 引用,顺序执行
@@ -192,24 +192,26 @@ namespace aFuncore {
     }
 
     Environment::~Environment() noexcept(false) {
-        if (reference != 0)
-            throw EnvironmentDestructException();
+        {   /* 使用互斥锁, 防止与gc线程出现不同步的情况 */
+            std::unique_lock<std::mutex> mutex{lock};
+            if (reference != 1)  // gc_inter 有一个引用
+                throw EnvironmentDestructException();
+
+            if (destruct)
+                return;
 
-        if (destruct)
-            return;
+            delete global_varlist;
 
-        delete global_varlist;
+            protect->delReference();
+            global->delReference();
 
-        protect->delReference();
-        global->delReference();
+            destruct = true;
+        }
 
-        Object::destruct(obj);
-        Var::destruct(var);
-        VarSpace::destruct(varspace);
+        GcObjectBase::destructAll(gc, gc_inter);
 
-        obj = nullptr;
-        var = nullptr;
-        varspace = nullptr;
-        destruct = true;
+        delete &gc_inter;
+        if (reference != 0)
+            throw EnvironmentDestructException();
     }
 }

+ 2 - 2
src/core/value.cpp

@@ -6,13 +6,13 @@ namespace aFuncore {
     Object::Object(std::string type_, Inter &inter)
             : type{std::move(type_)}, env{inter.getEnvironment()}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        this->addObject(env.obj);
+        env.gc.push_front(this);
     }
 
     Object::Object(std::string type_, Environment &env_)
             : type{std::move(type_)}, env{env_}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        this->addObject(env.obj);
+        env.gc.push_front(this);
     }
 
     Object::~Object() {

+ 4 - 4
src/core/var.cpp

@@ -5,12 +5,12 @@
 namespace aFuncore {
     Var::Var(Object *data_, Inter &inter) : data{data_}, env{inter.getEnvironment()}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        addObject(env.var);
+        env.gc.push_front(this);
     }
     
     Var::Var(Object *data_, Environment &env_) : data{data_}, env{env_}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        addObject(env.var);
+        env.gc.push_front(this);
     }
 
     Var::~Var() {
@@ -20,12 +20,12 @@ namespace aFuncore {
     
     VarSpace::VarSpace(Inter &inter) : env{inter.getEnvironment()}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        addObject(env.varspace);
+        env.gc.push_front(this);
     }
     
     VarSpace::VarSpace(Environment &env_) : env{env_}{
         std::unique_lock<std::mutex> mutex{env.lock};
-        addObject(env.varspace);
+        env.gc.push_front(this);
     }
 
     VarSpace::~VarSpace() {