diff options
author | Junegunn Choi <junegunn.c@gmail.com> | 2015-01-11 23:49:12 +0900 |
---|---|---|
committer | Junegunn Choi <junegunn.c@gmail.com> | 2015-01-11 23:49:12 +0900 |
commit | 9dbf6b02d24b52ae43e36905bbb1e83087e1dfe9 (patch) | |
tree | 37e627f5bb4a3037ea769aad1033593baec4eb00 /src/matcher.go | |
parent | 1db68a3976cfb10ed7d6ab88d7b468bb1b93ee34 (diff) |
Fix race conditions
- Wait for completions of goroutines when cancelling a search
- Remove shared access to rank field of Item
Diffstat (limited to 'src/matcher.go')
-rw-r--r-- | src/matcher.go | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/src/matcher.go b/src/matcher.go index 234e7033..713b4dd6 100644 --- a/src/matcher.go +++ b/src/matcher.go @@ -4,6 +4,7 @@ import ( "fmt" "runtime" "sort" + "sync" "time" ) @@ -134,10 +135,13 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) { slices := m.sliceChunks(request.chunks) numSlices := len(slices) resultChan := make(chan partialResult, numSlices) - countChan := make(chan int, numSlices) + countChan := make(chan int, numChunks) + waitGroup := sync.WaitGroup{} for idx, chunks := range slices { + waitGroup.Add(1) go func(idx int, chunks []*Chunk) { + defer func() { waitGroup.Done() }() sliceMatches := []*Item{} for _, chunk := range chunks { var matches []*Item @@ -159,6 +163,12 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) { }(idx, chunks) } + wait := func() bool { + cancelled.Set(true) + waitGroup.Wait() + return true + } + count := 0 matchCount := 0 for matchesInChunk := range countChan { @@ -166,7 +176,7 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) { matchCount += matchesInChunk if limit > 0 && matchCount > limit { - return nil, true // For --select-1 and --exit-0 + return nil, wait() // For --select-1 and --exit-0 } if count == numChunks { @@ -174,8 +184,7 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) { } if !empty && m.reqBox.Peak(REQ_RESET) { - cancelled.Set(true) - return nil, true + return nil, wait() } if time.Now().Sub(startedAt) > PROGRESS_MIN_DURATION { |