You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2018/11/14 17:02:24 UTC

[mynewt-newt] 01/02: resolve: Maintain reverse dependency list per-pkg

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit a1d3d2722a36e76779a929fb9c3074dfd9ea26f1
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Nov 7 09:46:18 2018 -0800

    resolve: Maintain reverse dependency list per-pkg
    
    Replace `ResolvePackage`'s reference count with a reverse dependency
    list (implemented as map).  This is less error prone, and it allows for
    package removal to be more efficient.
---
 newt/resolve/resolve.go | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/newt/resolve/resolve.go b/newt/resolve/resolve.go
index a85c97e..02d69f9 100644
--- a/newt/resolve/resolve.go
+++ b/newt/resolve/resolve.go
@@ -89,9 +89,9 @@ type ResolvePackage struct {
 
 	depsResolved bool
 
-	// Tracks this package's number of dependents.  If this number reaches 0,
-	// this package can be deleted from the resolver.
-	refCount int
+	// Tracks this package's dependents (things that depend on us).  If this
+	// map becomes empty, this package can be deleted from the resolver.
+	revDeps map[*ResolvePackage]struct{}
 }
 
 type ResolveSet struct {
@@ -169,6 +169,7 @@ func NewResolvePkg(lpkg *pkg.LocalPackage) *ResolvePackage {
 		Lpkg:      lpkg,
 		reqApiMap: map[string]resolveReqApi{},
 		Deps:      map[*ResolvePackage]*ResolveDep{},
+		revDeps:   map[*ResolvePackage]struct{}{},
 	}
 }
 
@@ -187,17 +188,17 @@ func (r *Resolver) resolveDep(dep *pkg.Dependency, depender string) (*pkg.LocalP
 // @return                      true if the package's dependency list was
 //                                  modified.
 func (rpkg *ResolvePackage) AddDep(
-	apiPkg *ResolvePackage, api string, expr string) bool {
+	depPkg *ResolvePackage, api string, expr string) bool {
 
-	if dep := rpkg.Deps[apiPkg]; dep != nil {
+	if dep := rpkg.Deps[depPkg]; dep != nil {
 		if dep.Api != "" && api == "" {
 			dep.Api = api
 		} else {
 			return false
 		}
 	} else {
-		rpkg.Deps[apiPkg] = &ResolveDep{
-			Rpkg: apiPkg,
+		rpkg.Deps[depPkg] = &ResolveDep{
+			Rpkg: depPkg,
 			Api:  api,
 			Expr: expr,
 		}
@@ -212,7 +213,8 @@ func (rpkg *ResolvePackage) AddDep(
 		rpkg.reqApiMap[api] = apiReq
 	}
 
-	apiPkg.refCount++
+	depPkg.revDeps[rpkg] = struct{}{}
+
 	return true
 }
 
@@ -339,16 +341,16 @@ func (r *Resolver) deletePkg(rpkg *ResolvePackage) error {
 	r.cfg.DeletePkg(rpkg.Lpkg)
 
 	// If the deleted package is the only depender for any other packages
-	// (i.e., if any of its dependencies have a reference count of one), delete
-	// them as well.
+	// (i.e., if any of its dependencies have only one reverse dependency),
+	// delete them as well.
 	for rdep, _ := range rpkg.Deps {
-		if rdep.refCount <= 0 {
+		if len(rdep.revDeps) == 0 {
 			return util.FmtNewtError(
-				"package %s unexpectedly has refcount <= 0",
+				"package %s unexpectedly has 0 reverse dependencies",
 				rdep.Lpkg.FullName())
 		}
-		rdep.refCount--
-		if rdep.refCount == 0 {
+		delete(rdep.revDeps, rpkg)
+		if len(rdep.revDeps) == 0 {
 			if err := r.deletePkg(rdep); err != nil {
 				return nil
 			}
@@ -406,12 +408,12 @@ func (r *Resolver) loadDepsForPkg(rpkg *ResolvePackage) (bool, error) {
 	for rdep, _ := range rpkg.Deps {
 		if _, ok := seen[rdep]; !ok {
 			delete(rpkg.Deps, rdep)
-			rdep.refCount--
+			delete(rdep.revDeps, rpkg)
 			changed = true
 
 			// If we just deleted the last reference to a package, remove the
 			// package entirely from the resolver and syscfg.
-			if rdep.refCount == 0 {
+			if len(rdep.revDeps) == 0 {
 				if err := r.deletePkg(rdep); err != nil {
 					return true, err
 				}