implement dependency refcounting

master
Ariadne Conill 2021-10-06 11:48:13 -06:00
parent d87114068f
commit 4144d506bb
2 changed files with 53 additions and 4 deletions

View File

@ -92,7 +92,7 @@ add_or_replace_dependency_node(const pkgconf_client_t *client, pkgconf_dependenc
{
PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf, dep);
free(dep);
pkgconf_dependency_unref(dep->owner, dep);
return NULL;
}
else if (dep2->flags && dep->flags == 0)
@ -100,7 +100,7 @@ add_or_replace_dependency_node(const pkgconf_client_t *client, pkgconf_dependenc
PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf2, dep2);
pkgconf_node_delete(&dep2->iter, list);
free(dep2);
pkgconf_dependency_unref(dep2->owner, dep2);
}
else
/* If both dependencies have equal strength, we keep both, because of situations like:
@ -115,7 +115,7 @@ add_or_replace_dependency_node(const pkgconf_client_t *client, pkgconf_dependenc
PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags);
pkgconf_node_insert_tail(&dep->iter, dep, list);
return dep;
return pkgconf_dependency_ref(dep->owner, dep);
}
static inline pkgconf_dependency_t *
@ -131,6 +131,8 @@ pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list,
dep->compare = compare;
dep->flags = flags;
dep->owner = client;
dep->refcount = 0;
return add_or_replace_dependency_node(client, dep, list);
}
@ -202,6 +204,48 @@ pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
free(dep);
}
/*
* !doc
*
* .. c:function:: pkgconf_dependency_t *pkgconf_dependency_ref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
*
* Increases a dependency node's refcount.
*
* :param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
* :param pkgconf_dependency_t* dep: The dependency to increase the refcount of.
* :return: the dependency node on success, else NULL
*/
pkgconf_dependency_t *
pkgconf_dependency_ref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
{
if (client != dep->owner)
return NULL;
dep->refcount++;
return dep;
}
/*
* !doc
*
* .. c:function:: void pkgconf_dependency_unref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
*
* Decreases a dependency node's refcount and frees it if necessary.
*
* :param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
* :param pkgconf_dependency_t* dep: The dependency to decrease the refcount of.
* :return: nothing
*/
void
pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
{
if (client != dep->owner)
return;
if (--dep->refcount <= 0)
pkgconf_dependency_free_one(dep);
}
/*
* !doc
*
@ -222,7 +266,7 @@ pkgconf_dependency_free(pkgconf_list_t *list)
pkgconf_dependency_t *dep = node->data;
pkgconf_node_delete(&dep->iter, list);
pkgconf_dependency_free_one(dep);
pkgconf_dependency_unref(dep->owner, dep);
}
}

View File

@ -100,6 +100,9 @@ struct pkgconf_dependency_ {
pkgconf_pkg_t *match;
unsigned int flags;
int refcount;
pkgconf_client_t *owner;
};
struct pkgconf_tuple_ {
@ -322,6 +325,8 @@ PKGCONF_API void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_depende
PKGCONF_API void pkgconf_dependency_free(pkgconf_list_t *list);
PKGCONF_API void pkgconf_dependency_free_one(pkgconf_dependency_t *dep);
PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags);
PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_ref(pkgconf_client_t *client, pkgconf_dependency_t *dep);
PKGCONF_API void pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep);
/* argvsplit.c */
PKGCONF_API int pkgconf_argv_split(const char *src, int *argc, char ***argv);