首先来一段PIL中的说明:
Life is not always that easy. Sometimes,an object needs other resources besides raw memory,such as file descriptors,window handles,and the like. (Often these resources are just memory too,but managed by some other part of the system). In such cases,when the object becomes garbage and is collected,somehow those other resources must be released too. Several OO languages provide a specific mechanism (called finalizer or destructor) for that need. Lua provides finalizers in the form of the __gc
metamethod. This metamethod only works for userdata values. When a userdatum is about to be collected and its metatable has a __gc
field,Lua calls the value of this field (which should be a function),passing as an argument the userdatum itself. This function can then release any resource associated with that userdatum.
假设现在我们需要写一个遍历目录的库,遍历文件基本流程是:
findFile -> 打开一个编译句柄
nextFile -> 遍历目录中的文件
closeFind -> 遍历完成
在lua使用遍历目录库:
for name in dir(path) do .... end
注意:dir是库中注册进去的API,支持for in 泛型语法。跟进Lua要求,需要dir返回一个迭代器(必须),可选的返回状态变量和控制变量。
如果for name in dir(path) do ... end 完全执行完毕,中间不会退出或者中断,那么不用考虑太多问题。但是如果中间会退出呢?比如说,编译某个目录,查找文件名为A的文件,如果找到了就退出。大致lua代码如下:
for name in dir(path) do
if (name == A) then
return
end
end
由于遍历需要通过findFile打开一个查询句柄,我们需要显示的释放此句柄。类似 查找进程、打开文件等等都是如此,分配的系统资源必须在不用的时候释放。
回到上面的问题,如何保证打开的查下句柄能正常释放呢?利用userdata的__gc metathod。 lua中的userdata在被回收的时候,会调用其__gc metathod方法。如是乎,我们只需要为__gc写一个metathod方法即可实现。
1、定义一个简单数据结构,用于遍历目录保存查询句柄和一些额外信息:
2、定义我们的dir函数
3、定义真正的迭代函数dir_iter
4、定义我们的清理函数
5、OK,现在可以注册dir了
6、别忘了,还有create_dir_metatable,这个主要目的是增加__gc metatable
注意,上面的宏定义使用了2中方法。
如果定义了宏RETURN_ITERFUN_AND_STATUS,dir返回迭代器dir_iter和状态变量;
如果没有定义RETURN_ITERFUN_AND_STATUS宏,dir只返回迭代器函数,参数作为迭代器函数的upvalue携带过去。
两种方式都能达到泛型遍历的效果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。