3

lua 5.4 可能会增加 to-be-closed 特性

 3 years ago
source link: https://blog.codingnow.com/2018/12/lua_54_to_be_closed.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

云风的 BLOG

思绪来得快去得也快,偶尔会在这里停留

« 惰性编译资源仓库中的源文件 | 返回首页 | 一种 16 倍抗锯齿字体渲染的方法 »

lua 5.4 可能会增加 to-be-closed 特性

如果你有关注 lua 在 github 上的仓库,就会发现,最近一段时间增加了一个新特性:to-be-closed 的 local 变量。

鉴于历史上 lua 每次的大版本开发过程中都会增加很多有趣的特性,却无法保持到版本正式发布。本文也只是介绍一下这个有趣的特性,并不保证它一定会被纳入语言标准。正式的发布版中即使有这个特性,语法上也可能有所不同。

我认为 Lua 加入这个特性的动机是它缺乏 RAII 机制。过去,我们必须用 pcall 来确保一段代码运行完毕,然后再清理相关的资源。这会导致代码实现繁琐,几乎无法正确实施。比如,如果你用 C 函数申请了一块资源,期望在使用完毕后可以清除干净,过去就只能依赖 __gc 方法。但 gc 的时机不可控,往往无法及时清理。如果你把释放过程放在运行过程的末尾,是很难确定整个运行过程中没有异常跳出的可能,那样就无法执行最后的释放流程。

lua 5.4 预计要增加的 to-be-closed 特性,是允许给堆栈上的 local 变量添加一个 to-be-closed 属性。有了这个属性的 local 变量,一旦超出它的作用域,就立刻运行一段相关的代码。这很像是结合了 golang 的 defer 和 C++ 的析构函数。

在 lua 代码中,我们可以使用 local *toclose c = function(errobj) ... end 来将一个 local 变量 c 定义成 to-be-closed 的。这里 c 是一个 function ,在 c 出了作用域后,它就会被调用。这很像 golang 的 defer 。

如果正常出作用域:比如是通过 goto break return 等,函数的参数为 nil ;如果是通过 error 异常跳出,那么 error 对象就会作为第一个参数传入。

这里的 to-be-closed 变量 c 也可以是非 function 类型,这时,触发的就是它的 __close 元方法。这很接近 C++ 的析构函数的行为。不过它并不等价于析构函数,因为对象还可以继续被使用。

触发 __close 时,会多传一个参数是对象本身。有了这个机制,我们就不再担心 io.open 这种临时打开的文件无法即使关闭了,因为 FILE 对象默认会加上 __close 方法,你需要做的是在需要的地方加上 *toclose 声明。

有了 to-be-closed 后,for 迭代器就可以实现的更完备了。for 会将迭代器声明为 to-be-closed 的,像 lfs.dir 这种操作系统目录迭代器,你就不会担心是否能及时关闭目录对象了。因为无论任何原因跳出 for 循环,迭代器的 __close 方法都会被调用。

你也有方法阻止 __close 方法调用,那就是使用 coroutine 来包装一个运行过程。如果使用 yield 跳出,是不会处罚 __close 方法的。新的 coroutine 库增加了 kill 方法来一次性触发所有挂起的 __close 并可以让线程对象可复用。

to-be-closed 也可以通过 C API lua_toclose 声明。有了这个,我们可以更放心的在 C 代码中申请临时资源,而不必担心某个 api 调用会抛出 error ,导致临时资源没有释放干净。在过去,我们通常是利用 lua_newuserdata 来申请临时内存,这往往无法及时回收。

云风 提交于 December 18, 2018 10:15 AM | 固定链接

Comments

新项目似乎没有任何选旧版本的理由。

Posted by: Cloud | (7) September 8, 2021 09:57 AM

请教一下云风:
一个linux下的c++项目中引入lua,应该怎么选取lua的版本?
5.1、5.2、5.3、5.4?
云风有什么建议?

Posted by: 花乎乎的小能 | (6) September 7, 2021 11:29 AM

最新lua 5.4 beta版的to-be-closed变量的用法,大概是这样。
function test2()
local t = {x=1};
setmetatable(t, {__close=function(...) print('close') end});
local tc<close> = t;--t必须要提前指定了__close元方法
end

test2();

Posted by: babypapa | (5) October 24, 2019 06:54 PM

lua真的很需要这个东东,之前项目用到很多,还特地在lua 5.1里加了个defer的语法。。
https://github.com/peete-q/lua-defer 有需要的可以拿走

Posted by: alon | (4) February 12, 2019 08:35 PM

不错的特性,希望Lua越来越强大,能加入更多实用的功能

Posted by: najoast | (3) December 19, 2018 11:32 PM

用了两年的lua,云风大佬的各种库帮我解决了很多问题,万分感谢,最近在研究pbc,想实现3.0版的pb

Posted by: Anonymous | (2) December 19, 2018 10:03 AM

偶尔来云大BLOG瞅瞅,终于更新了。

Posted by: 沧海一粟 | (1) December 18, 2018 11:02 AM

Post a comment

非这个主题相关的留言请到:留言本

名字:

Email 地址:

为了验证您是人类,请将六加一的结果(阿拉伯数字七)填写在下面:

URL:

记住我的信息?

留言:
(不欢迎在留言中粘贴程序代码)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK