在Julia中编写模块finalize方法的正确方法是什么?
我正在尝试找到在Julia中使用 finalizers 的正确方法
I am trying to find the right way to use finalizers in Julia
请参阅Julia文档:
Refer to Julia documentation:
finalizer(x,函数)
finalizer(x, function)
注册没有对x的程序可访问引用时要调用的函数f(x).如果x是位类型,则此函数的行为不可预测.
Register a function f(x) to be called when there are no program-accessible references to x. The behavior of this function is unpredictable if x is of a bits type.
首先,我使用TestModule.jl生成了一个TestModule标准包
First I genetated a TestModule standard package with a TestModule.jl
#in TestModule.jl
module TestModule
end
finalizer(TestModule,(t)->println("fin"))
以及runtest.jl
and also a runtest.jl
#in runtest.jl
using Base.Test
using TestModule
然后我尝试测试Package,但在通过测试时收到错误消息:
then I tried to test Package but I received ERROR while the test was passed:
julia> Pkg.test("TestModule")
INFO: Testing TestModule
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
jl_uv_writecb() ERROR: bad file descriptor EBADF
INFO: TestModule tests passed
之后,我安排了另一个测试用例
after that I arranged another test case
julia> workspace() # new workspace
julia> typeof(TestModule) # make sure *there are no program-accessible references to `TestModule`*
ERROR: UndefVarError: TestModule not defined
julia> using TestModule
julia> finalize(TestModule)
fin # finalize method is working
julia> typeof(TestModule)
Module # make sure *there is program-accessible reference to `TestModule`*
julia> workspace() # force clear references
julia> typeof(TestModule) # check that *there are no program-accessible references*
ERROR: UndefVarError: TestModule not defined
根据上述测试用例,我有一些疑问
According to above test cases I have some questions
- 为什么在测试过程中为
TestModule
添加这种finalize
方法会产生错误? - 为什么在清除引用时未调用
finalize
方法 -
为模块添加
finalize
方法的正确方法是什么
- Why adding such
finalize
method forTestModule
generates ERROR during test process? - Why
finalize
method was not called while I clear references What is the right way to add
finalize
method for a module
(OS = Ubuntu,Julia版本= 0.4.0)
(OS=Ubuntu , Julia Version=0.4.0)
编辑
,在workspace()
之后也调用gc()
也是没有帮助的.
as @Maciek have mentioned, calling gc()
after workspace()
also, do not help.
谢谢
恕我直言,workspace
没有任何障碍,并且finalizer
仅在用户定义的类型和复合类型上有效.
IMHO, workspace
takes no prisoners and in addition the finalizer
works well only on user-defined and composite types.
我已经进行了一些测试.看看我的结果:
I've performed some tests. Have a look at my results:
julia> type Foo
x
Foo(x) = begin obj = new(x); finalizer(obj,(o) -> println("The end.")); return obj end
end
julia> Foo(1)
julia> workspace()
julia> gc()
Module the end.error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer")
The end.error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer")
另一个对象定义在模块范围内的测试:
Another test with object defined inside module scope:
julia> module FinMod
type T
x::Int
end
finalizer(T(1), (t) -> println("Module the end."))
end
FinMod
julia> FinMod
FinMod
julia> workspace()
julia> gc()
Module the end.error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer")
函数(一流的对象)呢?
What about functions(first-class objects)?
julia> function foo() println("I'm foo") end
foo (generic function with 1 method)
julia> finalizer(foo, (f) -> println("foo function is dead now."))
julia> foo
foo (generic function with 1 method)
julia> workspace()
julia> foo
ERROR: UndefVarError: foo not defined
julia> gc()
julia> #nothing happened
因此,总结一下:我认为workspace
不会调用finalize
. finalizer
函数仅对用户定义的类型和复合类型有效.它不适用于Module
或Function
.
So, to summarize: In my opinion workspace
doesn't call finalize
. The finalizer
function works OK only for user-defined and composite types. It does not work for Module
or Function
.
更新:我记得workspace
将以前的Main
模块重写为LastMain
.因此,即使我们的模块不能从Main
进入,也仍然可以在LastMain
范围内使用(与我上面使用的功能相同).
Update: I remembered that workspace
rewrites previous Main
module into LastMain
. So even if our module is not accesible from Main
it's is still alive inside LastMain
scope (the same works for the function which I used above).