当前位置:主页 > 明星 >

云风的 BLOG: 在 C++ 中实现一个轻量的标记清除 gc 系统

2017-11-26 08:04字体:
分享到:

率先,我必要一个人选派笔来丢下它。 gc 零碎,一个人圆形的,是难解的处理的商议计数商议成绩。它不情愿比援用计数复杂得多。,并具有平等的或高的的效能。

我不情愿用复杂的东西。 template 技术,应用这样的基本规律糖使它出庭复杂。。条件必要,让这些 C++ 信号出庭更当代风格的。,更有“尝试”,我两者都不以为这很难。。

界面与意识到,相信尽量划分,较少的接触到应用它们的人的小事。但不要猛攻教条,逼上梁山做这么的事 COM 像市价 ABI 。或许尽量多地应用它 C++ 假释期自己的机制,不乱用。

尽量复杂地应用,不要让用户有这样的担负。。

效能使臻于完善最底下的销路。信号迅速地显示。,用户可以很快包含规律。,不要乱用它。。膨胀后使臻于完善新销路便于使用的。

信号列举如下:(可下载一组建议)

/* * filename: * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #ifndef interfacce_gcobject_h #define interfacce_gcobject_h #define interface struct interface i_gcobject { virtual ~i_gcobject() {} virtual void touch() {} virtual void mark() = 0 ; virtual void grab() = 0 ; virtual void release() = 0 ; static void collect(); }; #endif

自己人帮助 gc 托管界面结转到 i_gcobject ,求婚了三种方式。,

  1. mark 您可以警察这么地宾语。,警察的宾语将不会的被占用。 collect 回收。

  2. grab 将宾语附加到所转学的宾语上 root 的特别 gcobject 上。

  3. release 从宾语到宾语 root 上取掉。

另一个人 touch 模板方式 mark 回调,用于警察相同的材料的有区别的平衡。

mark 方式普通在 touch 方式中应用,留存,collect 方式将活跃的转学 root 的 mark 。


/* * filename: * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #ifndef interfacce_gcholder_h #define interfacce_gcholder_h #include "" interface i_gcholder : virtual i_gcobject { virtual void hold(i_gcobject *) = 0; virtual void unhold(i_gcobject *) = 0; static i_gcholder * create(); }; #endif

i_gcholder 为 root 的界面,求婚 hold 和 unhold 挂断方式需临时牧草。 gcobject 。


/* * filename: * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #ifndef gc_object_h #define gc_object_h #include "" class gcobject : virtual i_gcobject { bool marked; public: gcobject(); virtual void mark(); virtual void grab(); virtual void release(); struct f_unmarked; }; #endif /* * filename: * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #include "" #include "" #include #include static bool gc_trigger; static STD::带菌者 gc_pool; static i_gcholder * gc_root = i_gcholder::create(); struct gcobject::f_unmarked { bool operator() (gcobject * 值) { bool unmarked = value->marked != gc_trigger; if (警察) { delete value; } return unmarked; } }; gcobject::gcobject() : marked(!gc_trigger) { (这) } void gcobject::mark() { if (警察 != gc_trigger) { marked = gc_trigger; touch(); } } void gcobject::grab() { gc_root->hold(这) } void gcobject::release() { gc_root->unhold(这) } void i_gcobject::collect() { gc_root->mark(); (remove_if((), () , gcobject::f_unmarked()), ()); gc_trigger = !gc_trigger; }

gcobject 关于赠送的的 gc 意识到,意识到了 mark 、grab、release 和 collect 方式。

  1. mark 直接到一个人正式接受 bool 变量设置指出。这么地警察应用了 trigger 乒乓球运动转变,每回 collect 切换公务的。

  2. grab 和 release 你可以钩住材料 root 上,或许把它拿暴露。

  3. collect 将积极分子从 root 开端 mark ,尽职那个不注意 mark 的宾语。


/* * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #include "" #include "" #include #include #include class gcholder : public virtual i_gcholder, virtual gcobject { STD::带菌者 hold_set; STD::带菌者 unhold_set; bool set_changed; bool hold_set_sorted; bool unhold_set_sorted; void combine_set(); virtual void touch(); virtual void hold(i_gcobject obj) { (obj) hold_set_sorted = false; set_changed = true; } virtual void unhold(i_gcobject obj) { un(obj) unhold_set_sorted = false; set_changed = true; } struct f_mark { void operator() (i_gcobject obj) { obj->mark(); } }; public: gcholder() : set_changed(false), hold_set_sorted(true) , unhold_set_sorted(true) {} }; void gcholder::combine_set() { if (!hold_set_sorted) { STD::排序,()); hold_set_sorted = true; } if (!unhold_set_sorted) { 炽烈的::排序(联合国,un()); unhold_set_sorted = true; } if (!()) { STD::带菌者::iterator iter1 = (); STD::带菌者::iterator iter2 = un(); while (iter1 != () && iter2 != un()) { if (*iter1 == *iter2) { *iter1 = NULL; ++iter1; ++iter2; } else { assert(*iter1 < *iter2); ++iter1; } } i_gcobject * null = NULL; (std::remove((),(),null) , ()); (); } } void gcholder::touch() { if (set_changed) { combine_set(); set_changed = false; } std::for_each((), (), f_mark()); } i_gcholder * i_gcholder::create() { return new gcholder; }

gcholder 抽象地,有多个侦查。,他们是共同的触觉的。。(另外,您不用要结转它。)。 i_gcobject 这种设计可以用来模仿多级的堆栈。。但事实上否必要这么复杂。。由于它在聚集申请表格中,条件你的顺序有一个人过去某一特定历史时期的主流通,不克不及在 gc 该零碎模仿多级堆栈。。我们的无论怎样在流通不计做 collect 那就够了。堆栈转学的更深改编发射或使爆炸 collect 相反,它不起作用。,会形成很多的暂时性的 gc 宾语无法回复。


决定性的,看一眼玩意儿信号。,用 stl 里的 mutliset 意识到了一个人复杂的树界面。。那能够毫无用处。,又它演示了一个人复杂宾语当说话中肯相干。。它可以显示 gc 怎样符合公认准则的任务。

/* * filename: * Copyright (c) 2010 , * Cloud Wu . All rights 牧草。 * * * * Use, modification and distribution are subject to the "New BSD License" * as listed at . */ #include "" #include #include #include interface i_tree : virtual i_gcobject { virtual void link(i_tree *p) = 0; static i_tree * create(); }; class tree : public virtual i_tree , virtual gcobject { tree *parent; std::string children; struct f_mark { void operator() (树 压紧) { node->mark(); } }; virtual void touch() { if (母) parent->mark(); std::for_each((), (), f_mark()); } void unlink(); virtual void link(i_tree 母) public: tree() : 父(空) { printf(金属钱币 node %p ",这么地) } ~tree() { printf(尽职 node %p ",这么地) } }; void 树::抛开 { if (母) { parent->(这) parent = NULL; } } void 树::节(i_tree *p) { unlink(); if (p) { tree * cp = dynamic_cast(p); cp->(这) parent = cp; } } i_tree * i_tree::create() { return new tree; } int main() { i_tree *root = i_tree::create(); root->grab(); i_tree *node; node = i_tree::create(); node->link(root); node = i_tree::create(); node->link(root); i_gcobject::collect(); printf("collected "); node->link(NULL); i_gcobject::collect(); printf("finalize "); root->release(); i_gcobject::collect(); return 0; }

我们的在做一个人基础 gc 的宾语时,您可以先界限所需的界面。,让界面 i_gcobject 结转。比如,在下面的示例中 i_tree

那么,当您意识到此界面时,,可以虚结转 gcobject 。比如,在下面的示例中 tree

条件有必要,无论怎样过载 touch 方式,在 touch 方式中 mark 相互关系的 gcobject 。关于 tree 这么地窥测,转学父压紧和子压紧 mark 。

该宾语依然可以编译析构作用。,对等物于宾语 finalize 。在析构作用,不要废它 gcobject ,那个距 gc 零碎遵守。(比如,在) tree 里,就不要在 ~tree 中 delete children 包围说话中肯变量,你不用把它从你神父的压紧上取下降。


条件只应用这些界面,你不用要再包含它了。 ,由于 gcobject 境遇仅供实行。 i_gcobject 时应用。

下一篇:没有了