@@ -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,7 +79,9 @@ 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 ()
81
83
m .items [nonce ], m .cache = tx , nil
84
+ m .cacheMu .Unlock ()
82
85
}
83
86
84
87
// Forward removes all transactions from the map with a nonce lower than the
@@ -94,9 +97,11 @@ 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 ()
97
101
if m .cache != nil {
98
102
m .cache = m .cache [len (removed ):]
99
103
}
104
+ m .cacheMu .Unlock ()
100
105
return removed
101
106
}
102
107
@@ -120,7 +125,9 @@ func (m *sortedMap) reheap() {
120
125
* m .index = append (* m .index , nonce )
121
126
}
122
127
heap .Init (m .index )
128
+ m .cacheMu .Lock ()
123
129
m .cache = nil
130
+ m .cacheMu .Unlock ()
124
131
}
125
132
126
133
// filter is identical to Filter, but **does not** regenerate the heap. This method
@@ -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,9 +169,11 @@ 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 ()
163
173
if m .cache != nil {
164
174
m .cache = m .cache [:len (m .cache )- len (drops )]
165
175
}
176
+ m .cacheMu .Unlock ()
166
177
return drops
167
178
}
168
179
@@ -182,7 +193,9 @@ func (m *sortedMap) Remove(nonce uint64) bool {
182
193
}
183
194
}
184
195
delete (m .items , nonce )
196
+ m .cacheMu .Lock ()
185
197
m .cache = nil
198
+ m .cacheMu .Unlock ()
186
199
187
200
return true
188
201
}
@@ -206,7 +219,9 @@ 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 ()
209
223
m .cache = nil
224
+ m .cacheMu .Unlock ()
210
225
211
226
return ready
212
227
}
@@ -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