summaryrefslogtreecommitdiff
path: root/src/object.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-02-28 16:51:17 +0200
committerVicent Marti <tanoku@gmail.com>2011-03-03 20:23:52 +0200
commit48c27f86bbe9678c7e01a90a2cec7a30327b0e90 (patch)
tree0156ea823de82477792ad4778378200eee28aee3 /src/object.c
parent86d7e1ca6f54161a9e4d1ebe7a2f8e4802dc9639 (diff)
downloadlibgit2-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.c32
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);