我需要做一些liblisp
(在C11中(,它需要处理基本功能,就像libobjc
为Objective-C语言所做的一样。
编辑
我正在将问题重写为不那么通用的东西。
我得到了这样的实现:
typedef struct cons {
void *car, *cdr;
} *cons_t;
cons_t cons_init(void *, void *);
void *cons_get_car(cons_t);
void *cons_get_cdr(cons_t);
void cons_set_car(cons_t, void *);
void cons_set_cdr(cons_t, void *);
void cons_free(cons_t);
bool cons_is_managed(cons_t);
所以我可以制作一个 cons 单元格(它使用带有引用计数对象的内存池(。我还可以使用cons_is_managed
来检查 cons 单元格是否在内存池内(因此您可以使用外部定义的单元格,而不是使用 cons_init
创建的单元格(如静态数据(。
我如何在这里有效地实现自动引用计数,如果有人调用cons_set_car
或cons_set_cdr
如果void *
参数是托管的 cons 单元格,它将增加引用计数?
后宫和问题在这里没有用,因为每个单元格都有两种可能的去路(如果汽车和 cdr 是缺点,它可能无处可去(,它们可以是列表、树或图表。
我可能应该注册 on cons_set_car
/cons_set_cdr
中使用的外部(非托管(函数,以找到涉及它们的周期,但我仍然不确定如何有效地做到这一点。
由于这是一个比图中的一般循环(节点上最多两个顶点(更可控的上下文,我是否有可能在线性时间内做到这一点并避免垃圾收集(这将是我的计划 B(?
主要问题是这是任何函数式语言的核心,因此这些函数会被调用很多次(如obj_msgSend
(,它们是瓶颈。
谢谢。
换一种方法,为了简化问题:如何在基于引用计数的语言上实现一个cons单元,比如Objective-C + ARC或Vala?
我假设您打算实现的引用计数的主要目标是高效的垃圾收集(即使您说"避免垃圾收集",很明显您的目标是实现自动内存管理(。
首先,我建议您考虑是否切换到某种跟踪垃圾收集,例如大多数现代 Lisp 实现使用的方法。 它与引用计数垃圾收集之间的基本区别是与内存的正关系与负关系:使用引用计数,分配的元素被假定为活动,直到证明不是这样(通常通过图遍历算法(。 使用跟踪时,分配的元素被假定为垃圾,除非证明不是这样(通过从根对象集(例如 REPL 接口(的可访问性(。
是的,当标记和扫描算法运行时,您可能会偶尔获得显着的性能影响,但根据您对库的预期用途,这可能是值得的。 同样,如果仔细管理线程,则可以让一个核心处理垃圾回收,而另一个核心继续执行。 最有效的是混合策略,例如执行无法处理周期的"廉价"引用计数来处理高频简单情况,然后使用跟踪方法收集累积的循环垃圾。
至于如何有效地做到这一点...如果要进行引用计数,则需要为每个缺点存储一个数字。 为什么不直接将其存储在结构中?
typedef struct cons {
void *car, *cdr;
size_t reference_count;
} *cons_t;
如果采用混合策略,则可以在 O(n( 时间内处理高频操作,例如映射中的列表处理、归约和递归函数,其中 n 是要垃圾回收的元素数。