@@ -53,9 +53,10 @@ func (h *nonceHeap) Pop() interface{} {
5353// sortedMap is a nonce->transaction hash map with a heap based index to allow
5454// iterating over the contents in a nonce-incrementing way.
5555type 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
5960}
6061
6162// newSortedMap creates a new nonce-sorted transaction map.
@@ -78,7 +79,9 @@ func (m *sortedMap) Put(tx *types.Transaction) {
7879 if m .items [nonce ] == nil {
7980 heap .Push (m .index , nonce )
8081 }
82+ m .cacheMu .Lock ()
8183 m .items [nonce ], m .cache = tx , nil
84+ m .cacheMu .Unlock ()
8285}
8386
8487// 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 {
9497 delete (m .items , nonce )
9598 }
9699 // If we had a cached order, shift the front
100+ m .cacheMu .Lock ()
97101 if m .cache != nil {
98102 m .cache = m .cache [len (removed ):]
99103 }
104+ m .cacheMu .Unlock ()
100105 return removed
101106}
102107
@@ -120,7 +125,9 @@ func (m *sortedMap) reheap() {
120125 * m .index = append (* m .index , nonce )
121126 }
122127 heap .Init (m .index )
128+ m .cacheMu .Lock ()
123129 m .cache = nil
130+ m .cacheMu .Unlock ()
124131}
125132
126133// 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
136143 }
137144 }
138145 if len (removed ) > 0 {
146+ m .cacheMu .Lock ()
139147 m .cache = nil
148+ m .cacheMu .Unlock ()
140149 }
141150 return removed
142151}
@@ -160,9 +169,11 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
160169 heap .Init (m .index )
161170
162171 // If we had a cache, shift the back
172+ m .cacheMu .Lock ()
163173 if m .cache != nil {
164174 m .cache = m .cache [:len (m .cache )- len (drops )]
165175 }
176+ m .cacheMu .Unlock ()
166177 return drops
167178}
168179
@@ -182,7 +193,9 @@ func (m *sortedMap) Remove(nonce uint64) bool {
182193 }
183194 }
184195 delete (m .items , nonce )
196+ m .cacheMu .Lock ()
185197 m .cache = nil
198+ m .cacheMu .Unlock ()
186199
187200 return true
188201}
@@ -206,7 +219,9 @@ func (m *sortedMap) Ready(start uint64) types.Transactions {
206219 delete (m .items , next )
207220 heap .Pop (m .index )
208221 }
222+ m .cacheMu .Lock ()
209223 m .cache = nil
224+ m .cacheMu .Unlock ()
210225
211226 return ready
212227}
@@ -217,6 +232,8 @@ func (m *sortedMap) Len() int {
217232}
218233
219234func (m * sortedMap ) flatten () types.Transactions {
235+ m .cacheMu .Lock ()
236+ defer m .cacheMu .Unlock ()
220237 // If the sorting was not cached yet, create and cache it
221238 if m .cache == nil {
222239 m .cache = make (types.Transactions , 0 , len (m .items ))
@@ -232,8 +249,8 @@ func (m *sortedMap) flatten() types.Transactions {
232249// sorted internal representation. The result of the sorting is cached in case
233250// it's requested again before any modifications are made to the contents.
234251func (m * sortedMap ) Flatten () types.Transactions {
235- // Copy the cache to prevent accidental modifications
236252 cache := m .flatten ()
253+ // Copy the cache to prevent accidental modification
237254 txs := make (types.Transactions , len (cache ))
238255 copy (txs , cache )
239256 return txs
0 commit comments