Как правильно написать метод финализации модуля в Юлии?
Я пытаюсь найти правильный способ использовать финализаторы в Юлии
Обратитесь к документации Юлии:
финализатор (х, функция)
Зарегистрируйте функцию f(x), которая будет вызываться при отсутствии доступных для программы ссылок на x. Поведение этой функции непредсказуемо, если x имеет битовый тип.
Сначала я создал стандартный пакет TestModule с помощью TestModule.jl
#in TestModule.jl
module TestModule
end
finalizer(TestModule,(t)->println("fin"))
а также runtest.jl
#in runtest.jl
using Base.Test
using TestModule
Затем я попытался протестировать пакет, но я получил ОШИБКУ во время прохождения теста:
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
По приведенным выше тестам у меня есть несколько вопросов
- Зачем добавлять такие
finalize
метод дляTestModule
генерирует ОШИБКУ во время процесса тестирования? - Зачем
finalize
метод не был вызван, пока я очищаю ссылки Как правильно добавить
finalize
метод для модуля(OS=Ubuntu, версия Julia =0.4.0)
РЕДАКТИРОВАТЬ
как упомянул @Maciek gc()
после workspace()
Кроме того, не помогают.
Спасибо
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
не звонит finalize
, finalizer
Функция работает нормально только для пользовательских и составных типов. Это не работает для Module
или же Function
,
Обновление: я вспомнил, что workspace
переписывает предыдущий Main
модуль в LastMain
, Так что, даже если наш модуль не доступен из Main
это все еще живо внутри LastMain
область действия (то же самое работает для функции, которую я использовал выше).