File tree 2 files changed +93
-0
lines changed
2 files changed +93
-0
lines changed Original file line number Diff line number Diff line change @@ -1008,6 +1008,22 @@ func mapclear(t *maptype, h *hmap) {
1008
1008
1009
1009
h .flags ^= hashWriting
1010
1010
1011
+ // Mark buckets empty, so existing iterators can be terminated, see issue #59411.
1012
+ markBucketsEmpty := func (bucket unsafe.Pointer , mask uintptr ) {
1013
+ for i := uintptr (0 ); i <= mask ; i ++ {
1014
+ b := (* bmap )(add (bucket , i * uintptr (t .bucketsize )))
1015
+ for ; b != nil ; b = b .overflow (t ) {
1016
+ for i := uintptr (0 ); i < bucketCnt ; i ++ {
1017
+ b .tophash [i ] = emptyRest
1018
+ }
1019
+ }
1020
+ }
1021
+ }
1022
+ markBucketsEmpty (h .buckets , bucketMask (h .B ))
1023
+ if oldBuckets := h .oldbuckets ; oldBuckets != nil {
1024
+ markBucketsEmpty (oldBuckets , h .oldbucketmask ())
1025
+ }
1026
+
1011
1027
h .flags &^= sameSizeGrow
1012
1028
h .oldbuckets = nil
1013
1029
h .nevacuate = 0
Original file line number Diff line number Diff line change
1
+ // run
2
+
3
+ // Copyright 2023 The Go Authors. All rights reserved.
4
+ // Use of this source code is governed by a BSD-style
5
+ // license that can be found in the LICENSE file.
6
+
7
+ package main
8
+
9
+ import (
10
+ "math"
11
+ "reflect"
12
+ )
13
+
14
+ func main () {
15
+ for i := 0 ; i < 100 ; i ++ {
16
+ f ()
17
+ g ()
18
+ }
19
+ }
20
+
21
+ func f () {
22
+ // Allocate map.
23
+ m := map [float64 ]int {}
24
+ // Fill to just before a growth trigger.
25
+ const N = 13 << 4 // 6.5 * 2 * 2^k
26
+ for i := 0 ; i < N ; i ++ {
27
+ m [math .NaN ()] = i
28
+ }
29
+ // Trigger growth.
30
+ m [math .NaN ()] = N
31
+
32
+ // Iterate through map.
33
+ i := 0
34
+ for range m {
35
+ if i == 6 {
36
+ // Partway through iteration, clear the map.
37
+ clear (m )
38
+ } else if i > 6 {
39
+ // If we advance to the next iteration, that's a bug.
40
+ panic ("BAD" )
41
+ }
42
+ i ++
43
+ }
44
+ if len (m ) != 0 {
45
+ panic ("clear did not empty the map" )
46
+ }
47
+ }
48
+
49
+ func g () {
50
+ // Allocate map.
51
+ m := map [float64 ]int {}
52
+ // Fill to just before a growth trigger.
53
+ const N = 13 << 4 // 6.5 * 2 * 2^k
54
+ for i := 0 ; i < N ; i ++ {
55
+ m [math .NaN ()] = i
56
+ }
57
+ // Trigger growth.
58
+ m [math .NaN ()] = N
59
+
60
+ // Iterate through map.
61
+ i := 0
62
+ v := reflect .ValueOf (m )
63
+ iter := v .MapRange ()
64
+ for iter .Next () {
65
+ if i == 6 {
66
+ // Partway through iteration, clear the map.
67
+ v .Clear ()
68
+ } else if i > 6 {
69
+ // If we advance to the next iteration, that's a bug.
70
+ panic ("BAD" )
71
+ }
72
+ i ++
73
+ }
74
+ if v .Len () != 0 {
75
+ panic ("clear did not empty the map" )
76
+ }
77
+ }
You can’t perform that action at this time.
0 commit comments