depgraph: fix data races

This commit is contained in:
Mitchell Hashimoto 2014-07-01 10:09:20 -07:00
parent d970cec8eb
commit bce5d55a85
1 changed files with 14 additions and 2 deletions

View File

@ -9,6 +9,7 @@ import (
"bytes"
"fmt"
"sort"
"sync"
"github.com/hashicorp/terraform/digraph"
)
@ -217,6 +218,7 @@ CHECK_CYCLES:
// then introduce a lock in your callback.
func (g *Graph) Walk(fn WalkFunc) error {
// Set so we don't callback for a single noun multiple times
var seenMapL sync.RWMutex
seenMap := make(map[*Noun]chan struct{})
seenMap[g.Root] = make(chan struct{})
@ -236,7 +238,9 @@ func (g *Graph) Walk(fn WalkFunc) error {
// Go through each dependency and run that first
for _, dep := range current.Deps {
if _, ok := seenMap[dep.Target]; !ok {
seenMapL.Lock()
seenMap[dep.Target] = make(chan struct{})
seenMapL.Unlock()
tovisit = append(tovisit, dep.Target)
}
}
@ -244,12 +248,20 @@ func (g *Graph) Walk(fn WalkFunc) error {
// Spawn off a goroutine to execute our callback once
// all our dependencies are satisified.
go func(current *Noun) {
defer close(seenMap[current])
seenMapL.RLock()
closeCh := seenMap[current]
seenMapL.RUnlock()
defer close(closeCh)
// Wait for all our dependencies
for _, dep := range current.Deps {
seenMapL.RLock()
ch := seenMap[dep.Target]
seenMapL.RUnlock()
select {
case <-seenMap[dep.Target]:
case <-ch:
case <-quitCh:
return
}