syncmap: release m.mu during (*RWMutexMap).Range callbacks

The mainline syncmap.Map has allowed mutations within Range callbacks
since https://golang.org/cl/37342. The reference
implementations used in map_bench_test need to do the same.

Change-Id: Id73d254fa01cc64a1f00eb1903488796e1282423
Reviewed-on: https://go-review.googlesource.com/42956
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Bryan C. Mills 2017-05-09 16:06:53 -04:00 committed by Bryan Mills
commit 57af736625
2 changed files with 12 additions and 5 deletions

View file

@ -204,12 +204,10 @@ func BenchmarkAdversarialDelete(b *testing.B) {
m.Load(i) m.Load(i)
if i%mapSize == 0 { if i%mapSize == 0 {
var key int
m.Range(func(k, _ interface{}) bool { m.Range(func(k, _ interface{}) bool {
key = k.(int) m.Delete(k)
return false return false
}) })
m.Delete(key)
m.Store(i, i) m.Store(i, i)
} }
} }

View file

@ -64,8 +64,17 @@ func (m *RWMutexMap) Delete(key interface{}) {
func (m *RWMutexMap) Range(f func(key, value interface{}) (shouldContinue bool)) { func (m *RWMutexMap) Range(f func(key, value interface{}) (shouldContinue bool)) {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() keys := make([]interface{}, 0, len(m.dirty))
for k, v := range m.dirty { for k := range m.dirty {
keys = append(keys, k)
}
m.mu.RUnlock()
for _, k := range keys {
v, ok := m.Load(k)
if !ok {
continue
}
if !f(k, v) { if !f(k, v) {
break break
} }