diff --git a/hyphae/iteration.go b/hyphae/iteration/iteration.go similarity index 61% rename from hyphae/iteration.go rename to hyphae/iteration/iteration.go index b0d20d5..90b4071 100644 --- a/hyphae/iteration.go +++ b/hyphae/iteration/iteration.go @@ -1,26 +1,26 @@ -package hyphae +// Package iteration provides a handy API for making multiple checks on all hyphae in one go. +package iteration import ( + "github.com/bouncepaw/mycorrhiza/hyphae" "sync" ) -// Iteration represents an iteration over all hyphae in the storage. You may use it instead of directly iterating using hyphae.YieldExistingHyphae when you want to do n checks at once instead of iterating n times. +// Iteration represents an iteration over all existing hyphae in the storage. Iteration is done on all existing hyphae. The order of hyphae is not specified. For all hyphae, checks are made. type Iteration struct { sync.Mutex - iterator func() chan ExistingHypha - checks []func(h Hypha) CheckResult + checks []func(h hyphae.Hypha) CheckResult } // NewIteration constructs an iteration without checks. func NewIteration() *Iteration { return &Iteration{ - iterator: YieldExistingHyphae, - checks: make([]func(h Hypha) CheckResult, 0), + checks: make([]func(h hyphae.Hypha) CheckResult, 0), } } -// AddCheck adds the check to the iteration. It is concurrent-safe. -func (i7n *Iteration) AddCheck(check func(h Hypha) CheckResult) { +// AddCheck adds the check to the iteration. It is concurrent-safe. Checks are meant to have side-effects. +func (i7n *Iteration) AddCheck(check func(h hyphae.Hypha) CheckResult) { i7n.Lock() i7n.checks = append(i7n.checks, check) i7n.Unlock() @@ -32,8 +32,10 @@ func (i7n *Iteration) removeCheck(i int) { } // Ignite does the iteration by walking over all hyphae yielded by the iterator used and calling all checks on the hypha. Ignited iterations are not concurrent-safe. +// +// After ignition, you should not use the same Iteration again. func (i7n *Iteration) Ignite() { - for h := range i7n.iterator() { + for h := range hyphae.YieldExistingHyphae() { for i, check := range i7n.checks { if res := check(h); res == CheckForgetMe { i7n.removeCheck(i) diff --git a/tree/tree.go b/tree/tree.go index 6d05e8d..97b519e 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -2,6 +2,7 @@ package tree import ( "fmt" + "github.com/bouncepaw/mycorrhiza/hyphae/iteration" "path" "sort" "strings" @@ -18,11 +19,11 @@ func findSiblings(hyphaName string) []*sibling { } var ( siblingsMap = make(map[string]bool) - siblingCheck = func(h hyphae.Hypha) hyphae.CheckResult { + siblingCheck = func(h hyphae.Hypha) iteration.CheckResult { switch { case h.CanonicalName() == hyphaName, // NonEmptyHypha is no sibling of itself h.CanonicalName() == parentHyphaName: // Parent hypha is no sibling of its child - return hyphae.CheckContinue + return iteration.CheckContinue } if (parentHyphaName != "" && strings.HasPrefix(h.CanonicalName(), parentHyphaName+"/")) || (parentHyphaName == "") { @@ -39,10 +40,10 @@ func findSiblings(hyphaName string) []*sibling { siblingsMap[h.CanonicalName()] = true } } - return hyphae.CheckContinue + return iteration.CheckContinue } - i7n = hyphae.NewIteration() + i7n = iteration.NewIteration() ) siblingsMap[hyphaName] = true @@ -63,19 +64,19 @@ func findSiblings(hyphaName string) []*sibling { func countSubhyphae(siblings []*sibling) { var ( - subhyphaCheck = func(h hyphae.Hypha) hyphae.CheckResult { + subhyphaCheck = func(h hyphae.Hypha) iteration.CheckResult { for _, s := range siblings { if path.Dir(h.CanonicalName()) == s.name { s.directSubhyphaeCount++ - return hyphae.CheckContinue + return iteration.CheckContinue } else if strings.HasPrefix(h.CanonicalName(), s.name+"/") { s.indirectSubhyphaeCount++ - return hyphae.CheckContinue + return iteration.CheckContinue } } - return hyphae.CheckContinue + return iteration.CheckContinue } - i7n = hyphae.NewIteration() + i7n = iteration.NewIteration() ) i7n.AddCheck(subhyphaCheck) i7n.Ignite()