From a3dc4ac72900c169e96625e64031720ac04e956c Mon Sep 17 00:00:00 2001 From: KristofferC Date: Wed, 20 Jan 2021 15:57:06 +0100 Subject: [PATCH] add a warning if objects are finalized withoutbeing destroyed --- src/AMGX.jl | 8 ++------ src/Config.jl | 7 ++++++- src/Matrix.jl | 8 +++++++- src/Resources.jl | 8 +++++++- src/Solver.jl | 8 +++++++- src/Vector.jl | 8 +++++++- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/AMGX.jl b/src/AMGX.jl index 618f6ed..3ca4f47 100644 --- a/src/AMGX.jl +++ b/src/AMGX.jl @@ -116,12 +116,8 @@ end inc_refcount!(x::AMGXObject) = x.ref_count[] += 1 dec_refcount!(x::AMGXObject) = x.ref_count[] -= 1 -function with(f, object::AMGXObject) - try - f(object) - finally - close(object) - end +function warn_not_destroyed_on_finalize(x::AMGXObject) + !(x.handle == C_NULL) && @async @warn("AMGX: likely memory leak: a `$(typeof(x))` was finalized without having been `close`d") end diff --git a/src/Config.jl b/src/Config.jl index 2bdf5f1..fa7521e 100644 --- a/src/Config.jl +++ b/src/Config.jl @@ -1,6 +1,11 @@ Base.@kwdef mutable struct Config <: AMGXObject - handle::API.AMGX_config_handle = C_NULL + handle::API.AMGX_config_handle = API.AMGX_config_handle(C_NULL) ref_count::Threads.Atomic{Int} = Threads.Atomic{Int}(0) + function Config(handle::API.AMGX_config_handle, ref_count::Threads.Atomic{Int}) + config = new(handle, ref_count) + finalizer(warn_not_destroyed_on_finalize, config) + return config + end end get_api_destroy_call(::Type{Config}) = API.AMGX_config_destroy dec_refcount_parents(config::Config) = nothing diff --git a/src/Matrix.jl b/src/Matrix.jl index 7d3f67c..0f502eb 100644 --- a/src/Matrix.jl +++ b/src/Matrix.jl @@ -1,9 +1,15 @@ # TODO: Add support for uploading a CuSparseMatrixBSR Base.@kwdef mutable struct AMGXMatrix <: AMGXObject - handle::API.AMGX_matrix_handle = C_NULL + handle::API.AMGX_matrix_handle = API.AMGX_matrix_handle(C_NULL) mode::Union{Mode, Nothing} = nothing resources::Union{Resources, Nothing} = nothing + function AMGXMatrix(handle::API.AMGX_matrix_handle, mode::Union{Mode, Nothing}, + resources::Union{Resources, Nothing}) + m = new(handle, mode, resources) + finalizer(warn_not_destroyed_on_finalize, m) + return m + end end get_api_destroy_call(::Type{AMGXMatrix}) = API.AMGX_matrix_destroy function dec_refcount_parents(m::AMGXMatrix) diff --git a/src/Resources.jl b/src/Resources.jl index a2d8bd4..8e2034b 100644 --- a/src/Resources.jl +++ b/src/Resources.jl @@ -1,7 +1,13 @@ Base.@kwdef mutable struct Resources <: AMGXObject - handle::API.AMGX_resources_handle = C_NULL + handle::API.AMGX_resources_handle = API.AMGX_resources_handle(C_NULL) ref_count::Threads.Atomic{Int} = Threads.Atomic{Int}(0) cfg::Union{Config, Nothing} = nothing + function Resources(handle::API.AMGX_resources_handle, ref_count::Threads.Atomic{Int}, + cfg::Union{Config, Nothing}) + resources = new(handle, ref_count, cfg) + finalizer(warn_not_destroyed_on_finalize, resources) + return resources + end end get_api_destroy_call(::Type{Resources}) = API.AMGX_resources_destroy function dec_refcount_parents(resources::Resources) diff --git a/src/Solver.jl b/src/Solver.jl index db4590b..9f49988 100644 --- a/src/Solver.jl +++ b/src/Solver.jl @@ -1,8 +1,14 @@ Base.@kwdef mutable struct Solver <: AMGXObject - handle::API.AMGX_solver_handle = C_NULL + handle::API.AMGX_solver_handle = API.AMGX_solver_handle(C_NULL) resources::Union{Resources, Nothing} = nothing config::Union{Config, Nothing} = nothing bound_matrix::Union{AMGXMatrix, Nothing} = nothing + function Solver(handle::API.AMGX_solver_handle, resources::Union{Resources, Nothing}, + config::Union{Config, Nothing}, bound_matrix::Union{AMGXMatrix, Nothing}) + solver = new(handle, resources, config, bound_matrix) + finalizer(warn_not_destroyed_on_finalize, solver) + return solver + end end function dec_refcount_parents(solver::Solver) dec_refcount!(solver.resources) diff --git a/src/Vector.jl b/src/Vector.jl index 8b04472..fd7b238 100644 --- a/src/Vector.jl +++ b/src/Vector.jl @@ -1,7 +1,13 @@ Base.@kwdef mutable struct AMGXVector <: AMGXObject - handle::API.AMGX_vector_handle = C_NULL + handle::API.AMGX_vector_handle = API.AMGX_vector_handle(C_NULL) mode::Union{Mode, Nothing} = nothing resources::Union{Resources, Nothing} = nothing + function AMGXVector(handle::API.AMGX_vector_handle, mode::Union{Mode, Nothing}, + resources::Union{Resources, Nothing}) + v = new(handle, mode, resources) + finalizer(warn_not_destroyed_on_finalize, v) + return v + end end get_api_destroy_call(::Type{AMGXVector}) = API.AMGX_vector_destroy function dec_refcount_parents(v::AMGXVector)