@@ -53,9 +53,10 @@ func (h *nonceHeap) Pop() interface{} {
53
53
// sortedMap is a nonce->transaction hash map with a heap based index to allow
54
54
// iterating over the contents in a nonce-incrementing way.
55
55
type sortedMap struct {
56
- items map [uint64 ]* types.Transaction // Hash map storing the transaction data
57
- index * nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
58
- cache types.Transactions // Cache of the transactions already sorted
56
+ items map [uint64 ]* types.Transaction // Hash map storing the transaction data
57
+ index * nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
58
+ cache types.Transactions // Cache of the transactions already sorted
59
+ cacheMu sync.Mutex // Mutex covering the cache
59
60
}
60
61
61
62
// newSortedMap creates a new nonce-sorted transaction map.
@@ -78,6 +79,8 @@ func (m *sortedMap) Put(tx *types.Transaction) {
78
79
if m .items [nonce ] == nil {
79
80
heap .Push (m .index , nonce )
80
81
}
82
+ m .cacheMu .Lock ()
83
+ defer m .cacheMu .Unlock ()
81
84
m .items [nonce ], m .cache = tx , nil
82
85
}
83
86
@@ -94,6 +97,8 @@ func (m *sortedMap) Forward(threshold uint64) types.Transactions {
94
97
delete (m .items , nonce )
95
98
}
96
99
// If we had a cached order, shift the front
100
+ m .cacheMu .Lock ()
101
+ defer m .cacheMu .Unlock ()
97
102
if m .cache != nil {
98
103
m .cache = m .cache [len (removed ):]
99
104
}
@@ -120,6 +125,8 @@ func (m *sortedMap) reheap() {
120
125
* m .index = append (* m .index , nonce )
121
126
}
122
127
heap .Init (m .index )
128
+ m .cacheMu .Lock ()
129
+ defer m .cacheMu .Unlock ()
123
130
m .cache = nil
124
131
}
125
132
@@ -136,7 +143,9 @@ func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transacti
136
143
}
137
144
}
138
145
if len (removed ) > 0 {
146
+ m .cacheMu .Lock ()
139
147
m .cache = nil
148
+ m .cacheMu .Unlock ()
140
149
}
141
150
return removed
142
151
}
@@ -160,6 +169,8 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
160
169
heap .Init (m .index )
161
170
162
171
// If we had a cache, shift the back
172
+ m .cacheMu .Lock ()
173
+ defer m .cacheMu .Unlock ()
163
174
if m .cache != nil {
164
175
m .cache = m .cache [:len (m .cache )- len (drops )]
165
176
}
@@ -182,6 +193,8 @@ func (m *sortedMap) Remove(nonce uint64) bool {
182
193
}
183
194
}
184
195
delete (m .items , nonce )
196
+ m .cacheMu .Lock ()
197
+ defer m .cacheMu .Unlock ()
185
198
m .cache = nil
186
199
187
200
return true
@@ -206,6 +219,8 @@ func (m *sortedMap) Ready(start uint64) types.Transactions {
206
219
delete (m .items , next )
207
220
heap .Pop (m .index )
208
221
}
222
+ m .cacheMu .Lock ()
223
+ defer m .cacheMu .Unlock ()
209
224
m .cache = nil
210
225
211
226
return ready
@@ -217,6 +232,8 @@ func (m *sortedMap) Len() int {
217
232
}
218
233
219
234
func (m * sortedMap ) flatten () types.Transactions {
235
+ m .cacheMu .Lock ()
236
+ defer m .cacheMu .Unlock ()
220
237
// If the sorting was not cached yet, create and cache it
221
238
if m .cache == nil {
222
239
m .cache = make (types.Transactions , 0 , len (m .items ))
@@ -232,8 +249,8 @@ func (m *sortedMap) flatten() types.Transactions {
232
249
// sorted internal representation. The result of the sorting is cached in case
233
250
// it's requested again before any modifications are made to the contents.
234
251
func (m * sortedMap ) Flatten () types.Transactions {
235
- // Copy the cache to prevent accidental modifications
236
252
cache := m .flatten ()
253
+ // Copy the cache to prevent accidental modification
237
254
txs := make (types.Transactions , len (cache ))
238
255
copy (txs , cache )
239
256
return txs
0 commit comments