青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,長修遠,我們不能沒有錢
隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
數(shù)據(jù)加載中……

在 C++ 中實現(xiàn)一個輕量的標記清除 gc 系統(tǒng)(轉(zhuǎn)載)

# 在 C++ 中實現(xiàn)一個輕量的標記清除 gc 系統(tǒng)
[引用](https://blog.codingnow.com/2010/02/cpp_gc.html)
最近想把 engine 做一個簡單 C++ 封裝,結(jié)合 QT 使用。engine 本身是用純 C 實現(xiàn)的,大部分應用基于 lua 開發(fā)。對對象生命期管理也依賴 lua 的 gc 系統(tǒng)。關(guān)于這部分的設(shè)計,可以參考我以前寫的一篇 為 lua 封裝 C 對象的生存期管理問題 。
當我們把中間層搬到 C++ 中時,遇到的問題之一就是,C++ 沒有原生的 gc 支持。我也曾經(jīng)寫過一個 gc 庫。但在特定應用下還不夠簡潔。這幾天過年休息,仔細考慮了一下相關(guān)的需求,嘗試實現(xiàn)了一個更簡單的 gc 框架。不到 200 行代碼吧,我直接列在這篇 blog 里。
這些尚是一些玩具代碼,我花了一天時間來寫。有許多考慮不周的地方,以及不完整的功能。但可以闡明一些基本思路。
首先我需要一個`標記清除`的 `gc系統(tǒng)`,用來解決`引用記數(shù)`不容易解決的`循環(huán)引用`問題。它的實現(xiàn)不想比`引用記數(shù)`復雜太多,并有相同甚至更高的性能。
我不想使用復雜的 template 技術(shù),利用太多的語法糖讓使用看起來簡單。如果需要讓這些 C++ 代碼看起來更現(xiàn)代,更有“品味”,我想也不是很難的事情。
接口和實現(xiàn)希望盡量分離,對用的人少暴露細節(jié)。但不拘泥于教條,強求做成類似 COM 那樣的通用 ABI 。還是盡量利用 C++ 語言本身提供的機制,不濫用。
使用盡量簡單,不要讓使用人員有太大負擔。
功能滿足最低需求即可。代碼容易閱讀,使用人員可以很快理解原理,不至于誤用。也方便日后擴展以適應新的需求。
代碼如下:
 1 /* 
 2  * filename: i_gcobject.h 
 3  * Copyright (c) 2010 ,
 4  * Cloud Wu . All rights reserved. 
 5  * 
 6  * http://www.codingnow.com 
 7  * 
 8  * Use, modification and distribution are subject to the "New BSD License" 
 9  * as listed at . 
10  */ 
11   
12 #ifndef interfacce_gcobject_h 
13 #define interfacce_gcobject_h 
14 
15 #define interface struct 
16 
17 interface i_gcobject { 
18     virtual ~i_gcobject() {} 
19 
20     virtual void touch() {} 
21 
22     virtual void mark() = 0 ; 
23     virtual void grab() = 0 ; 
24     virtual void release() = 0 ; 
25 
26     static void collect(); 
27 }; 
28 #endif

所有支持 `gc管理的接口`都繼承至 `i_gcobject` ,提供三個方法:
* mark 可以把這個對象打上標記,被標記的對象將不會被 collect 回收。
* grab 將對象掛接到一個被稱呼為 root 的特殊 gcobject 上。
* release 將對象從 root 上取掉。
另提供 touch 的模板方法供 mark 回調(diào),用來標記同一對象中的不同部分。
mark 方法一般在 touch 方法中使用,另外,collect 方法將主動調(diào)用 root 的 mark 。
 1 /*  filename: i_gcholder.h
 2  *  Copyright (c) 2010 ,
 3  *      Cloud Wu . All rights reserved.
 4  *
 5  *      http://www.codingnow.com
 6  *
 7  *  Use, modification and distribution are subject to the "New BSD License"
 8  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 9  */
10 
11 #ifndef interfacce_gcholder_h
12 #define interfacce_gcholder_h
13 
14 #include "i_gcobject.h"
15 
16 interface i_gcholder : virtual i_gcobject {
17   virtual void hold(i_gcobject *) = 0;
18   virtual void unhold(i_gcobject *) = 0;
19   
20   static i_gcholder * create();
21 };
22 #endif
`i_gcholder` 為 root 的接口,提供 `hold` 和 `unhold` 方法來掛接需要持久保留的 gcobject 。

 1 /*  filename: i_gcobject.h
 2  *  Copyright (c) 2010 ,
 3  *      Cloud Wu . All rights reserved.
 4  *
 5  *      http://www.codingnow.com
 6  *
 7  *  Use, modification and distribution are subject to the "New BSD License"
 8  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 9  */
10 
11 #ifndef interfacce_gcobject_h
12 #define interfacce_gcobject_h
13 #define interface struct
14 
15 interface i_gcobject {
16 
17   virtual ~i_gcobject() {}
18 
19   virtual void touch() {}
20 
21   virtual void mark() = 0 ;
22   virtual void grab() = 0 ;
23   virtual void release() = 0 ;
24 
25   static void collect();
26 };
27 #endif
 1 /*  filename: gcobject.h
 2  *  Copyright (c) 2010 ,
 3  *      Cloud Wu . All rights reserved.
 4  *
 5  *      http://www.codingnow.com
 6  *
 7  *  Use, modification and distribution are subject to the "New BSD License"
 8  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 9  */
10 
11 #ifndef gc_object_h
12 #define gc_object_h
13 
14 #include "i_gcobject.h"
15 
16 class gcobject : virtual i_gcobject {
17   bool marked;
18 
19 public:
20   gcobject();
21 
22   virtual void mark();
23   virtual void grab();
24   virtual void release();
25 
26   struct f_unmarked;
27 
28 };
29 #endif
30 ```
31 
32 ```c++
33 /*  filename: gcobject.cpp 
34  *  Copyright (c) 2010 ,
35  *      Cloud Wu . All rights reserved.
36  *
37  *      http://www.codingnow.com
38  *
39  *  Use, modification and distribution are subject to the "New BSD License"
40  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
41  */
42 
43 #include "gcobject.h"
44 #include "i_gcholder.h"
45 #include <vector>
46 #include <algorithm>
47 
48 static bool gc_trigger;
49 static std::vector<gcobject *> gc_pool;
50 static i_gcholder * gc_root = i_gcholder::create();
51 
52 
53 struct gcobject::f_unmarked {
54   bool operator() (gcobject * value) {
55     bool unmarked = value->marked != gc_trigger;
56     if (unmarked) {
57       delete value;
58     }
59     return unmarked;
60   }
61 };
62 
63 gcobject::gcobject() : marked(!gc_trigger) {
64   gc_pool.push_back(this);
65 }
66 
67 void gcobject::mark() {
68   if (marked != gc_trigger) {
69     marked = gc_trigger;
70     touch();
71   }
72 }
73 
74 void gcobject::grab(){
75   gc_root->hold(this);
76 }
77 
78 void gcobject::release(){
79   gc_root->unhold(this);
80 }
81 
82 void i_gcobject::collect() {
83   gc_root->mark();
84   gc_pool.erase(remove_if(gc_pool.begin(), gc_pool.end() , gcobject::f_unmarked()), gc_pool.end());
85   gc_trigger = !gc_trigger;
86 }
gcobject 為具體的 gc 實現(xiàn),實現(xiàn)了 `mark` 、`grab`、`release` 和 `collect` 方法。
`mark` 采用的直接向一 bool 變量設(shè)置標記。這個標記利用了 `trigger` 這個乒乓開關(guān),每次 `collect` 都會切換狀態(tài)。
`grab` 和 `release` 可以把對象掛接到 root 上,或從上取掉。
`collect` 會主動從 root 開始 `mark` ,并釋放那些沒有 `mark` 的對象。

 1 /*  filename: gcholder.cpp
 2  *  Copyright (c) 2010 ,
 3  *      Cloud Wu . All rights reserved.
 4  *
 5  *      http://www.codingnow.com
 6  *
 7  *  Use, modification and distribution are subject to the "New BSD License"
 8  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 9  */
10 
11 #include "i_gcholder.h"
12 #include "gcobject.h"
13 #include <vector>
14 #include <algorithm>
15 #include <cassert>
16 
17 class gcholder : public virtual i_gcholder, virtual gcobject {
18   std::vector<i_gcobject *> hold_set;
19   std::vector<i_gcobject *> unhold_set;
20 
21   bool set_changed;
22   bool hold_set_sorted;
23   bool unhold_set_sorted;
24 
25   void combine_set();
26   virtual void touch();
27 
28   virtual void hold(i_gcobject *obj) {
29     hold_set.push_back(obj);
30     hold_set_sorted = false;
31     set_changed = true;
32   }
33 
34   virtual void unhold(i_gcobject *obj) {
35     unhold_set.push_back(obj);
36     unhold_set_sorted = false;
37     set_changed = true;
38   }
39 
40   struct f_mark {
41     void operator() (i_gcobject *obj) {
42       obj->mark();
43     }
44   };
45 
46 public:
47 
48   gcholder() :  set_changed(false),  hold_set_sorted(true) ,  unhold_set_sorted(true) {  }
49 
50 };
51 
52 void gcholder::combine_set(){
53   if (!hold_set_sorted) {
54     std::sort(hold_set.begin(),hold_set.end());
55     hold_set_sorted = true;
56   }
57   if (!unhold_set_sorted) {
58     std::sort(unhold_set.begin(),unhold_set.end());
59     unhold_set_sorted = true;
60   }
61   if (!unhold_set.empty()) {
62     std::vector<i_gcobject *>::iterator iter1 = hold_set.begin();
63     std::vector<i_gcobject *>::iterator iter2 = unhold_set.begin();
64     while (iter1 != hold_set.end() && iter2 != unhold_set.end()) {
65       if (*iter1 == *iter2) {
66         *iter1 = NULL;
67         ++iter1;
68         ++iter2;
69       } else {
70         assert(*iter1 < *iter2);
71         ++iter1;
72       }
73     }
74     i_gcobject * null = NULL;
75     hold_set.erase(std::remove(hold_set.begin(),hold_set.end(),null) , hold_set.end());
76     unhold_set.clear();
77   }
78 }
79 
80 void gcholder::touch(){
81   if (set_changed) {
82     combine_set();
83     set_changed = false;
84   }
85   std::for_each(hold_set.begin(), hold_set.end(), f_mark());
86 }
87 
88 i_gcholder * i_gcholder::create(){
89   return new gcholder;
90 }


gcholder 理論上可以有多個實例,并相互掛接。(否則不需要繼承至 i_gcobject )這個設(shè)計可以用來模擬多級的堆棧。但實際上并不需要這么復雜。因為在大部分應用里,如果你的程序有一個周期性的主循環(huán),就可以不在 gc 系統(tǒng)里模擬出一個多級的堆棧。我們只用在循環(huán)之外做 collect 即可。再堆棧調(diào)用的較深層次觸發(fā) collect 反而效果不佳,會導致許多臨時 gc 對象無法回收。
最后來看一個玩具代碼,用 stl 里的 mutliset 實現(xiàn)了一個簡單的樹接口。可能沒有什么使用價值,但它演示了一個較復雜的對象相互引用的關(guān)系。并可以展示 gc 如何正確工作。

 1 /*  filename: test.cpp
 2  *  Copyright (c) 2010 ,
 3  *      Cloud Wu . All rights reserved.
 4  *
 5  *      http://www.codingnow.com
 6  *
 7  *  Use, modification and distribution are subject to the "New BSD License"
 8  *  as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 9  */
10 #include "gcobject.h"
11 #include <cstdio>
12 #include <set>
13 #include <algorithm>
14 
15 interface i_tree : virtual i_gcobject {
16   virtual void link(i_tree *p) = 0;
17   static i_tree * create();
18 };
19 
20 class tree : public virtual i_tree , virtual gcobject {
21   tree *parent;
22   std::multiset<tree *> children;
23   struct f_mark {
24     void operator() (tree *node) {
25       node->mark();
26     }
27   };
28 
29   virtual void touch() {
30     if (parent)
31       parent->mark();
32     std::for_each(children.begin(), children.end(), f_mark());
33   }
34 
35   void unlink();
36   virtual void link(i_tree *parent);
37 
38 public:
39   tree() : parent(NULL) {
40     printf("create node %p\n",this);
41   }
42 
43   ~tree() {
44     printf("release node %p\n",this);
45   }
46 
47 };
48 
49 
50 void tree::unlink() {
51   if (parent) {
52     parent->children.erase(this);
53     parent = NULL;
54   }
55 }
56 
57 void tree::link(i_tree *p){
58   unlink();
59   if (p) {
60     tree * cp = dynamic_cast<tree *>(p);
61     cp->children.insert(this);
62     parent = cp;
63   }
64 }
65 
66 i_tree *i_tree::create(){
67   return new tree;
68 }
69 
70 int main(){
71   i_tree *root = i_tree::create();
72   root->grab();
73   i_tree *node;
74   node = i_tree::create();
75   node->link(root);
76   node = i_tree::create();
77   node->link(root);
78   i_gcobject::collect();
79   printf("collected\n");
80   node->link(NULL);
81   i_gcobject::collect();
82   printf("finalize\n");
83   root->release();
84   i_gcobject::collect();
85   return 0;
86 }
我們在實現(xiàn)一個基于 gc 的對象時,可以先定義出需要的接口,讓接口從 i_gcobject 繼承。例如上例中的 i_tree 。
然后在實現(xiàn)這個接口時,可以虛繼承 gcobject 。例如上例中的 tree 。
如果有需要,就重載 touch 方法,在 touch 方法中 mark 相關(guān)的 gcobject 。對于 tree 這個例子,就是調(diào)用父親和孩子節(jié)點的 mark 。
對象依然可以寫析構(gòu)函數(shù),相當于對象的 finalize 。在析構(gòu)函數(shù)中,不要再釋放和它相關(guān)的 gcobject ,那些留給 gc 系統(tǒng)去完成。(例如在 tree 里,就不要在 ~tree 中 delete children 容器中的變量,也不需要把自己從父親節(jié)點上摘掉)
如果僅僅只是使用那些接口,則不需要再包含 gcobject.h ,因為 gcobject 的細節(jié)只供實現(xiàn) i_gcobject 時使用。

posted on 2019-08-01 10:57 Khan 閱讀(595) 評論(0)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺開發(fā)

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            日韩视频一区二区| 国产欧美高清| 亚洲第一主播视频| 在线亚洲精品福利网址导航| 国产情人综合久久777777| 欧美精品福利在线| 性欧美超级视频| 一区二区三区四区五区视频 | 午夜免费在线观看精品视频| 亚洲二区在线视频| 国产精品一区二区久久久| 欧美激情视频一区二区三区免费| 久久精品视频在线播放| 欧美中文字幕不卡| 欧美日韩精品一二三区| 亚洲欧美一区二区激情| 国产麻豆91精品| 欧美日韩一区二区三区在线观看免| 老色鬼精品视频在线观看播放| 亚洲欧美日韩一区在线观看| 日韩午夜av在线| 亚洲欧洲三级| 蜜乳av另类精品一区二区| 久久久亚洲高清| 你懂的亚洲视频| 欧美激情四色| 亚洲精品乱码久久久久久蜜桃91| 91久久午夜| 一区二区三区不卡视频在线观看| 夜久久久久久| 午夜视频一区| 美女任你摸久久| 欧美另类人妖| 国产精品视频精品视频| 性欧美videos另类喷潮| 久久噜噜亚洲综合| 毛片av中文字幕一区二区| 欧美精品v日韩精品v国产精品| 久久精品理论片| 久热精品视频在线观看| 欧美理论电影网| 欧美肥婆在线| 国产精品扒开腿做爽爽爽软件| 欧美日韩国产精品一区二区亚洲| 久久在线播放| 夜夜嗨av一区二区三区中文字幕| 国产精品av久久久久久麻豆网| 久久久久久夜| 国产精品国产三级国产aⅴ入口| 国产亚洲成精品久久| 国产一区二区三区无遮挡| 欧美日韩一级大片网址| 久久久亚洲人| 欧美日韩国产高清| 亚洲国产精品精华液网站| 中国成人黄色视屏| 在线观看视频日韩| 中文av字幕一区| 欧美二区在线看| 日韩亚洲欧美成人一区| 免费观看成人| 午夜精品久久久久久久久久久久 | 性欧美1819性猛交| 99精品99| 国产精品久久久久久久久久尿 | 欧美日韩在线播放三区| 亚洲国产一区二区a毛片| 亚洲欧美另类综合偷拍| 亚洲视频一区在线观看| 国产精品久久久久久久午夜片| 亚洲视频在线一区| 91久久国产综合久久91精品网站| 久久综合给合久久狠狠狠97色69| 亚洲精品一级| 欧美日韩国产在线| 久久精品国产欧美激情| 另类亚洲自拍| 羞羞视频在线观看欧美| 午夜综合激情| 亚洲午夜在线观看| 午夜激情综合网| 亚洲激情在线激情| 欧美电影免费观看高清完整版| 日韩一级黄色av| 亚洲欧美日韩一区| 亚洲综合第一页| 日韩视频在线免费观看| 欧美色图天堂网| 欧美日韩激情小视频| 亚洲永久免费观看| 欧美巨乳在线| 亚洲人成77777在线观看网| 在线观看不卡| 欧美a级理论片| 99这里有精品| 久久久久国产一区二区| 久久久久久久一区二区| 免费看精品久久片| 亚洲国产免费| 欧美视频日韩视频| 性伦欧美刺激片在线观看| 欧美诱惑福利视频| 国产精品一区二区三区成人| 欧美一级夜夜爽| 久久国产精品久久久久久久久久| 国产精品日韩高清| 久久网站免费| 亚洲欧美电影在线观看| 暖暖成人免费视频| 一区二区三区免费观看| 国产亚洲一二三区| 欧美精品在线免费| 久久国产视频网站| 亚洲一二三区精品| 亚洲电影免费观看高清完整版| 亚洲丝袜av一区| av成人动漫| 亚洲高清自拍| 国产精品女人网站| 欧美另类videos死尸| 国产乱子伦一区二区三区国色天香 | 中日韩高清电影网| 亚洲一区二区三区免费视频 | 精品999久久久| 国产精品国产自产拍高清av王其 | 麻豆精品一区二区综合av| 欧美一区二区三区免费视频| 午夜在线视频一区二区区别| 亚洲专区一区| 久久久久国产精品厨房| 美女主播精品视频一二三四| 牛牛精品成人免费视频| 欧美国产精品v| 一区二区三区成人精品| 欧美一区二区精品| 久久久999精品| 欧美日韩精品系列| 激情欧美一区二区三区| 亚洲日本中文字幕区| 亚欧成人精品| 亚洲动漫精品| 午夜精品久久久久久99热| 久久综合色天天久久综合图片| 欧美精品国产精品日韩精品| 国产精品日韩欧美一区二区| 91久久综合亚洲鲁鲁五月天| 欧美一区二区三区播放老司机| 一本久久a久久免费精品不卡| 91久久久在线| 亚洲人被黑人高潮完整版| 欧美精品在线极品| 午夜精品视频在线观看一区二区| 久久激情网站| 性欧美超级视频| 日韩网站在线看片你懂的| 国产精品福利av| 欧美精品在线免费观看| 最新中文字幕一区二区三区| 美女福利精品视频| 久久www成人_看片免费不卡| 日韩一区二区精品视频| 国产精品久久77777| 欧美在线三区| 久久精品国产清高在天天线| 亚洲国产精品成人| 久久久久国产成人精品亚洲午夜| 国产精品老女人精品视频| 亚洲视频播放| 亚洲视频第一页| 国产精品永久免费在线| 午夜精品久久久久久久男人的天堂 | 午夜精品区一区二区三| 国产精品伦一区| 久久www成人_看片免费不卡| 欧美一区二区三区婷婷月色| 国产亚洲在线观看| 欧美电影免费| 国产精品毛片a∨一区二区三区|国 | 欧美日韩国内| 久久国内精品视频| 久久久五月婷婷| 一本色道久久综合| 欧美在线精品一区| 亚洲视频精选| 久久综合中文字幕| 一区二区三区高清| 久久天天躁狠狠躁夜夜av| 亚洲午夜激情| 欧美日韩久久久久久| 亚洲第一搞黄网站| 国产日韩欧美精品综合| 亚洲午夜精品视频| 99re热精品| 欧美精品一线| 亚洲九九爱视频| 亚洲一区二区三区午夜| 亚洲第一久久影院| 亚洲精品极品| 欧美日韩中文字幕在线| 一区二区三区欧美日韩|