I am trying to find the right way to use finalizers in Julia
Refer to Julia documentation:
finalizer(x, function)
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.
First I genetated a TestModule standard package with a TestModule.jl
#in TestModule.jl
module TestModule
end
finalizer(TestModule,(t)->println("fin"))
and also a runtest.jl
#in runtest.jl
using Base.Test
using TestModule
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
Why adding such finalize
method for TestModule
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 Version=0.4.0)
EDIT
as @Maciek have mentioned, calling gc()
after workspace()
also, do not help.
thanks
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
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
.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With