Skip to content

Commit c4138ed

Browse files
committed
Reimplement parallel-letter-frequency using channels
1 parent c14facb commit c4138ed

File tree

1 file changed

+33
-22
lines changed

1 file changed

+33
-22
lines changed

parallel-letter-frequency/parallel_letter_frequency.go

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import "sync"
55
// FreqMap records the frequency of each rune in a given text.
66
type FreqMap map[rune]int
77

8+
type runeCount struct {
9+
r rune
10+
c int
11+
}
12+
813
// Frequency counts the frequency of each rune in a given text and returns this
914
// data as a FreqMap.
1015
func Frequency(s string) FreqMap {
@@ -17,35 +22,41 @@ func Frequency(s string) FreqMap {
1722

1823
// ConcurrentFrequency counts the frequency of each rune in parallel.
1924
func ConcurrentFrequency(strings []string) FreqMap {
20-
var wg sync.WaitGroup
21-
sc := safeCounter{}
22-
sc.v = make(FreqMap)
25+
var runeCounterChan = make([]chan runeCount, len(strings))
2326

24-
for _, s := range strings {
25-
wg.Add(1)
26-
go func(str string) {
27+
for i, s := range strings {
28+
runeCounterChan[i] = make(chan runeCount, 25)
29+
go func(str string, runeCounterChan chan runeCount) {
2730
smap := Frequency(str)
2831
for r, c := range smap {
29-
sc.Add(r, c)
32+
runeCounterChan <- runeCount{r: r, c: c}
3033
}
31-
defer wg.Done()
32-
}(s)
34+
close(runeCounterChan)
35+
}(s, runeCounterChan[i])
3336
}
3437

35-
wg.Wait()
38+
var wg sync.WaitGroup
39+
var merged = make(chan runeCount, 100)
40+
for i := range strings {
41+
wg.Add(1)
42+
go func(i int) {
43+
for rc := range runeCounterChan[i] {
44+
merged <- rc
45+
}
46+
defer wg.Done()
47+
}(i)
48+
}
3649

37-
return sc.v
38-
}
50+
go func() {
51+
wg.Wait()
52+
close(merged)
53+
}()
3954

40-
type safeCounter struct {
41-
v FreqMap
42-
mux sync.Mutex
43-
}
55+
fm := FreqMap{}
56+
for rc := range merged {
57+
// Process each value
58+
fm[rc.r] += rc.c
59+
}
4460

45-
// Add increases the value for the counter for the given key.
46-
func (c *safeCounter) Add(key rune, count int) {
47-
c.mux.Lock()
48-
// Lock so only one goroutine at a time can access the map c.v.
49-
c.v[key] += count
50-
c.mux.Unlock()
61+
return fm
5162
}

0 commit comments

Comments
 (0)