diff options
author | Vicent Marti <tanoku@gmail.com> | 2011-02-28 16:51:17 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-03-03 20:23:52 +0200 |
commit | 48c27f86bbe9678c7e01a90a2cec7a30327b0e90 (patch) | |
tree | 0156ea823de82477792ad4778378200eee28aee3 /src/object.c | |
parent | 86d7e1ca6f54161a9e4d1ebe7a2f8e4802dc9639 (diff) | |
download | libgit2-48c27f86bbe9678c7e01a90a2cec7a30327b0e90.tar.gz |
Implement reference counting for git_objects
All `git_object` instances looked up from the repository are reference
counted. User is expected to use the new `git_object_close` when an
object is no longer needed to force freeing it.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src/object.c')
-rw-r--r-- | src/object.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/src/object.c b/src/object.c index c9809c52a..e23271442 100644 --- a/src/object.c +++ b/src/object.c @@ -166,8 +166,12 @@ static int write_back(git_object *object) if ((error = git_odb_write(&new_id, object->repo->db, &object->source.raw)) < GIT_SUCCESS) return error; - if (!object->in_memory) + if (object->in_memory) { + int idx = git_vector_search(&object->repo->memory_objects, object); + git_vector_remove(&object->repo->memory_objects, idx); + } else { git_hashtable_remove(object->repo->objects, &object->id); + } git_oid_cpy(&object->id, &new_id); git_hashtable_insert(object->repo->objects, &object->id, object); @@ -257,6 +261,7 @@ int git_object_new(git_object **object_out, git_repository *repo, git_otype type object->source.raw.type = type; + object->refcount++; *object_out = object; return GIT_SUCCESS; } @@ -317,13 +322,14 @@ int git_object_lookup(git_object **object_out, git_repository *repo, const git_o } if (error < GIT_SUCCESS) { - git_object_free(object); + git_object__free(object); return error; } git_object__source_close(object); git_hashtable_insert(repo->objects, &object->id, object); + object->refcount++; *object_out = object; return GIT_SUCCESS; } @@ -371,13 +377,18 @@ int git_object_write(git_object *object) return write_back(object); } -void git_object_free(git_object *object) +void git_object__free(git_object *object) { - if (object == NULL) - return; + assert(object); git_object__source_close(object); - git_hashtable_remove(object->repo->objects, &object->id); + + if (object->in_memory) { + int idx = git_vector_search(&object->repo->memory_objects, object); + git_vector_remove(&object->repo->memory_objects, idx); + } else { + git_hashtable_remove(object->repo->objects, &object->id); + } switch (object->source.raw.type) { case GIT_OBJ_COMMIT: @@ -402,6 +413,15 @@ void git_object_free(git_object *object) } } +void git_object_close(git_object *object) +{ + if (object == NULL) + return; + + if (--object->refcount <= 0) + git_object__free(object); +} + const git_oid *git_object_id(const git_object *obj) { assert(obj); |