在Julia中编写模块finalize方法的正确方式是什么?

6
我正在尝试找到在Julia中使用finalizers的正确方法。
请参阅Julia文档:

finalizer(x, function)

注册函数f(x),当没有程序可访问的引用x时调用该函数。如果x是bits类型,则该函数的行为是不可预测的。

首先,我生成了一个名为TestModule.jl的TestModule标准包。
#in TestModule.jl
module TestModule
end
finalizer(TestModule,(t)->println("fin"))

还需要一个 runtest.jl 文件

#in runtest.jl
using Base.Test
using TestModule

然后我尝试测试Package,但是虽然测试通过,但我收到了错误提示:
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

之后我安排了另一个测试用例。

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 

根据以上测试案例,我有一些问题:
  1. 为什么为 TestModule 添加这样的 finalize 方法会在测试过程中生成错误?

  2. 为什么在清除引用时没有调用 finalize 方法?

  3. 为模块添加 finalize 方法的正确方法是什么?

    (操作系统=Ubuntu,Julia版本=0.4.0)

编辑

正如 @Maciek 所提到的,在 workspace() 之后调用 gc() 也无济于事。

谢谢

1个回答

1
我个人认为,workspace 毫不留情,此外 finalizer 仅在用户定义和复合类型上运行良好。
我进行了一些测试。看看我的结果:
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")

另一个在模块作用域内定义对象的测试:

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")

关于函数(一等对象),有什么想法?
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 不会调用 finalizefinalizer 函数仅适用于用户定义和复合类型。它不适用于 ModuleFunction
更新:我记得 workspace 会将以前的 Main 模块重写为 LastMain。因此,即使我们的模块无法从 Main 访问,它仍然存在于 LastMain 范围内(对于上面使用的函数也是如此)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接