Skip to content

Commit

Permalink
Merge pull request #20124 from JuliaLang/sb/libgit2/refcount
Browse files Browse the repository at this point in the history
Add reference count to LibGit2 objects
  • Loading branch information
kshyatt authored Jan 21, 2017
2 parents fc4dc29 + 20e24bc commit d3bac6e
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
9 changes: 8 additions & 1 deletion base/libgit2/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export with, GitRepo, GitConfig
const GITHUB_REGEX =
r"^(?:git@|git://|https://(?:[\w\.\+\-]+@)?)github.com[:/](([^/].+)/(.+?))(?:\.git)?$"i

const REFCOUNT = Threads.Atomic{UInt}()

include("utils.jl")
include("consts.jl")
include("types.jl")
Expand Down Expand Up @@ -612,8 +614,13 @@ function __init__()

err = ccall((:git_libgit2_init, :libgit2), Cint, ())
err > 0 || throw(ErrorException("error initializing LibGit2 module"))
REFCOUNT[] = 1

atexit() do
ccall((:git_libgit2_shutdown, :libgit2), Cint, ())
if Threads.atomic_sub!(REFCOUNT, UInt(1)) == 1
# refcount zero, no objects to be finalized
ccall((:git_libgit2_shutdown, :libgit2), Cint, ())
end
end

@static if is_linux()
Expand Down
10 changes: 10 additions & 0 deletions base/libgit2/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,12 @@ for (typ, reporef, sup, cname) in [
@eval type $typ <: $sup
ptr::Ptr{Void}
function $typ(ptr::Ptr{Void},fin=true)
# fin=false should only be used when the pointer should not be free'd
# e.g. from within callback functions which are passed a pointer
@assert ptr != C_NULL
obj = new(ptr)
if fin
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(obj, Base.close)
end
return obj
Expand All @@ -464,12 +467,14 @@ for (typ, reporef, sup, cname) in [
function $typ(repo::GitRepo, ptr::Ptr{Void})
@assert ptr != C_NULL
obj = new(Nullable(repo), ptr)
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(obj, Base.close)
return obj
end
function $typ(ptr::Ptr{Void})
@assert ptr != C_NULL
obj = new(Nullable{GitRepo}(), ptr)
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(obj, Base.close)
return obj
end
Expand All @@ -481,6 +486,7 @@ for (typ, reporef, sup, cname) in [
function $typ(repo::GitRepo, ptr::Ptr{Void})
@assert ptr != C_NULL
obj = new(repo, ptr)
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(obj, Base.close)
return obj
end
Expand All @@ -490,6 +496,10 @@ for (typ, reporef, sup, cname) in [
if obj.ptr != C_NULL
ccall(($(string(cname, :_free)), :libgit2), Void, (Ptr{Void},), obj.ptr)
obj.ptr = C_NULL
if Threads.atomic_sub!(REFCOUNT, UInt(1)) == 1
# will the last finalizer please turn out the lights?
ccall((:git_libgit2_shutdown, :libgit2), Cint, ())
end
end
end
end
Expand Down

0 comments on commit d3bac6e

Please sign in to comment.