diff --git a/cache.c b/cache.c index ea4f11c..c768752 100644 --- a/cache.c +++ b/cache.c @@ -32,7 +32,7 @@ pkg_cache_lookup(const char *id) PKG_FOREACH_LIST_ENTRY(pkg_cache, pkg) { if (!strcmp(pkg->id, id)) - return pkg; + return pkg_ref(pkg); } return NULL; @@ -47,6 +47,8 @@ pkg_cache_lookup(const char *id) void pkg_cache_add(pkg_t *pkg) { + pkg_ref(pkg); + pkg->next = pkg_cache; pkg_cache = pkg; @@ -76,3 +78,14 @@ pkg_cache_remove(pkg_t *pkg) pkg_cache = pkg->next; } } + +void +pkg_cache_free(void) +{ + pkg_t *iter, *iter2; + + PKG_FOREACH_LIST_ENTRY_SAFE(pkg_cache, iter2, iter) + { + pkg_free(iter); + } +} diff --git a/main.c b/main.c index ee5b1d5..9d41fbf 100644 --- a/main.c +++ b/main.c @@ -899,5 +899,7 @@ out_println: out: pkg_tuple_free_global(); + pkg_cache_free(); + return ret; } diff --git a/pkg.c b/pkg.c index 7070958..18a0575 100644 --- a/pkg.c +++ b/pkg.c @@ -238,7 +238,7 @@ pkg_new_from_file(const char *filename, FILE *f, unsigned int flags) } fclose(f); - return pkg; + return pkg_ref(pkg); } void @@ -283,6 +283,21 @@ pkg_free(pkg_t *pkg) free(pkg); } +pkg_t * +pkg_ref(pkg_t *pkg) +{ + pkg->refcount++; + return pkg; +} + +void +pkg_unref(pkg_t *pkg) +{ + pkg->refcount--; + if (pkg->refcount <= 0) + pkg_free(pkg); +} + static inline pkg_t * pkg_try_specific_path(const char *path, const char *name, unsigned int flags) { @@ -338,7 +353,7 @@ pkg_scan_dir(const char *path, pkg_iteration_func_t func) if (pkg != NULL) { func(pkg); - pkg_free(pkg); + pkg_unref(pkg); } } @@ -809,7 +824,7 @@ pkg_report_graph_error(pkg_t *pkg, pkg_dependency_t *node, unsigned int eflags) } if (pkg != NULL) - pkg_free(pkg); + pkg_unref(pkg); return eflags; } @@ -834,11 +849,16 @@ pkg_walk_list(pkg_dependency_t *deplist, pkgdep = pkg_verify_dependency(node, flags, &eflags); if (eflags != PKG_ERRF_OK) return pkg_report_graph_error(pkgdep, node, eflags); - if (pkgdep->flags & PKG_PROPF_CACHED) + if (pkgdep->flags & PKG_PROPF_SEEN) + { + pkg_unref(pkgdep); continue; + } + pkgdep->flags |= PKG_PROPF_SEEN; eflags = pkg_traverse(pkgdep, func, data, depth - 1, flags); - pkg_free(pkgdep); + pkgdep->flags &= ~PKG_PROPF_SEEN; + pkg_unref(pkgdep); /* optimization: if a break has been found in the depgraph, quit walking it */ if (eflags != PKG_ERRF_OK) @@ -875,12 +895,12 @@ pkg_walk_conflicts_list(pkg_t *root, pkg_dependency_t *deplist, unsigned int fla fprintf(error_msgout, "It may be possible to ignore this conflict and continue, try the\n"); fprintf(error_msgout, "PKG_CONFIG_IGNORE_CONFLICTS environment variable.\n"); - pkg_free(pkgdep); + pkg_unref(pkgdep); return PKG_ERRF_PACKAGE_CONFLICT; } - pkg_free(pkgdep); + pkg_unref(pkgdep); } } @@ -949,7 +969,6 @@ pkg_cflags(pkg_t *root, pkg_fragment_t **list, int maxdepth, unsigned int flags) int eflag; eflag = pkg_traverse(root, pkg_cflags_collect, list, maxdepth, flags); - if (eflag != PKG_ERRF_OK) { pkg_fragment_free(*list); diff --git a/pkg.h b/pkg.h index f162dbf..31518af 100644 --- a/pkg.h +++ b/pkg.h @@ -81,10 +81,12 @@ typedef struct pkg_queue_ { #define PKG_PROPF_NONE 0x0 #define PKG_PROPF_VIRTUAL 0x1 #define PKG_PROPF_CACHED 0x2 +#define PKG_PROPF_SEEN 0x4 struct pkg_ { pkg_t *prev, *next; /* for pkg_cache */ + int refcount; char *id; char *filename; char *realname; @@ -131,6 +133,8 @@ typedef void (*pkg_traverse_func_t)(pkg_t *pkg, void *data, unsigned int flags); typedef bool (*pkg_queue_apply_func_t)(pkg_t *world, void *data, int maxdepth, unsigned int flags); /* pkg.c */ +pkg_t *pkg_ref(pkg_t *pkg); +void pkg_unref(pkg_t *pkg); void pkg_free(pkg_t *pkg); pkg_t *pkg_find(const char *name, unsigned int flags); void pkg_scan(const char *search_path, pkg_iteration_func_t func); @@ -191,5 +195,6 @@ bool pkg_queue_validate(pkg_queue_t *head, int maxdepth, unsigned int flags); pkg_t *pkg_cache_lookup(const char *id); void pkg_cache_add(pkg_t *pkg); void pkg_cache_remove(pkg_t *pkg); +void pkg_cache_free(void); #endif