Skip to content

Commit 4f9defb

Browse files
authored
Guard concurrent groupnames computation (#67)
1 parent 5950d6b commit 4f9defb

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

concurrency_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,20 @@ func TestConcurrency(t *testing.T) {
3131

3232
wg.Wait()
3333
}
34+
35+
func TestConcurrenctSubgroupNames(t *testing.T) {
36+
r := MustCompile("(?P<foo>foo)(?P<bar>bar)(?P<baz>baz)")
37+
38+
wg := &sync.WaitGroup{}
39+
for i := 0; i < 20; i++ {
40+
wg.Add(1)
41+
go func() {
42+
defer wg.Done()
43+
if len(r.SubexpNames()) != 4 {
44+
t.Error("wrong number of subgroup names")
45+
}
46+
}()
47+
}
48+
49+
wg.Wait()
50+
}

internal/re2.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"runtime"
66
"strconv"
77
"strings"
8+
"sync"
89
"sync/atomic"
910
"unicode"
1011
"unicode/utf8"
@@ -17,8 +18,9 @@ type Regexp struct {
1718

1819
expr string
1920

20-
numMatches int
21-
groupNames []string
21+
numMatches int
22+
groupNames []string
23+
groupNamesOnce sync.Once
2224

2325
abi *libre2ABI
2426

@@ -698,9 +700,9 @@ func (re *Regexp) Split(s string, n int) []string {
698700
// Since the Regexp as a whole cannot be named, names[0] is always
699701
// the empty string. The slice should not be modified.
700702
func (re *Regexp) SubexpNames() []string {
701-
if re.groupNames == nil {
703+
re.groupNamesOnce.Do(func() {
702704
re.groupNames = subexpNames(re.abi, re.ptr, re.numMatches)
703-
}
705+
})
704706
return re.groupNames
705707
}
706708

0 commit comments

Comments
 (0)