堆栈的写时复制 引用计数不可变对象

问题描述

如何在大数后缀计算中实现堆栈管理的写时复制技术?

我想针对以下操作优化我的系统:

duplicate top of stack
swap the two top elements
copy the second element on stack to the top
rotate the stack making the third element on top
apply n-ary operations on the stack 

一个典型的操作从栈顶取一些参数,并留下一些结果。

我的堆栈被实现为一个数组,其中数据从低内存增长到高内存,指针从高内存增长到低内存。

解决方法

正如我所见,问题不在于写时复制技术本身,而在于内存管理和垃圾收集。

在 Forth 中,我们不能有运算符重载,并且应该为每一类数字明确单独的一组操作。那么我们有两个选择:

    1. 对 bigint 对象(它们的处理程序)进行的一组操作,带有手动内存管理,类似于对文件、动态内存缓冲区或其他对象的操作。
    1. 一整套操作,包括单独的堆栈,例如对浮点数的操作,以及自动内存管理。

请注意,选项 (2) 在幕后包含 (1)。

引用计数

在选项 (2) 中实现自动内存管理的一种方法是使用专用堆栈(或者可能是两个堆栈)和引用计数。堆栈包含对对象(缓冲区)的引用。如果计数器大于 1,则更改数据的操作(如 b::1+)应复制缓冲区并将引用替换为新的引用(否则数据可以在该位置更改)。

将项目(引用)放入堆栈应增加其计数器,从堆栈中移除应减少其计数器。当计数器变为 0 时,应释放缓冲区。

诸如b::dupb::over之类的操作会增加计数器。 b::swap 不会改变任何计数器。 b::drop 减少计数器(如果计数器为 0,则释放缓冲区)。

将项目从堆栈移动到 bigint 变量不应更改结果中的计数器。但是应该减少变量先前值(如果有)的计数器。

如果命名变量和常量还不够(例如,拥有用户定义的数组),您可能需要在 API 中引入指向 bigint 对象的指针(一种匿名变量)或处理程序。

不可变对象

实现选项 (2) 的另一种方法是使用不可变对象和垃圾收集循环。这种方式我们不需要统计引用,但是需要维护外部指针列表(包括变量)。

这种垃圾收集的一个简单例子可以在彼得苏维埃托夫的 s 表达式的实现中找到:Функциональное программирование на языке Форт(俄语中的“Functional Programming in Forth language”,但它可以很容易翻译{{3} }).

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...