@@ -2,13 +2,12 @@ package conflict
22
33import (
44 "fmt"
5- "math/rand"
65 "sync"
76 "sync/atomic"
87
8+ "github.com/iotaledger/goshimmer/packages/protocol/engine/ledger/mempool/newconflictdag/reentrantmutex"
99 "github.com/iotaledger/goshimmer/packages/protocol/engine/ledger/mempool/newconflictdag/weight"
1010 "github.com/iotaledger/hive.go/ds/shrinkingmap"
11- "github.com/iotaledger/hive.go/ds/types"
1211 "github.com/iotaledger/hive.go/runtime/event"
1312 "github.com/iotaledger/hive.go/runtime/syncutils"
1413 "github.com/iotaledger/hive.go/stringify"
@@ -17,7 +16,7 @@ import (
1716// SortedSet is a set of Conflicts that is sorted by their weight.
1817type SortedSet [ConflictID , ResourceID IDType ] struct {
1918 // HeaviestPreferredMemberUpdated is triggered when the heaviest preferred member of the SortedSet changes.
20- HeaviestPreferredMemberUpdated * event.Event2 [* Conflict [ConflictID , ResourceID ], TriggerContext [ ConflictID ] ]
19+ HeaviestPreferredMemberUpdated * event.Event2 [* Conflict [ConflictID , ResourceID ], reentrantmutex. ThreadID ]
2120
2221 // owner is the Conflict that owns this SortedSet.
2322 owner * Conflict [ConflictID , ResourceID ]
@@ -47,17 +46,18 @@ type SortedSet[ConflictID, ResourceID IDType] struct {
4746 isShutdown atomic.Bool
4847
4948 // mutex is used to synchronize access to the SortedSet.
50- mutex sync. RWMutex
49+ mutex * reentrantmutex. ReEntrantMutex
5150}
5251
5352// NewSortedSet creates a new SortedSet that is owned by the given Conflict.
5453func NewSortedSet [ConflictID , ResourceID IDType ](owner * Conflict [ConflictID , ResourceID ]) * SortedSet [ConflictID , ResourceID ] {
5554 s := & SortedSet [ConflictID , ResourceID ]{
56- HeaviestPreferredMemberUpdated : event .New2 [* Conflict [ConflictID , ResourceID ], TriggerContext [ ConflictID ] ](),
55+ HeaviestPreferredMemberUpdated : event .New2 [* Conflict [ConflictID , ResourceID ], reentrantmutex. ThreadID ](),
5756 owner : owner ,
5857 members : shrinkingmap .New [ConflictID , * sortedSetMember [ConflictID , ResourceID ]](),
5958 pendingWeightUpdates : shrinkingmap .New [ConflictID , * sortedSetMember [ConflictID , ResourceID ]](),
6059 pendingWeightUpdatesCounter : syncutils .NewCounter (),
60+ mutex : reentrantmutex .New (owner .ID ().String ()),
6161 }
6262 s .pendingWeightUpdatesSignal = sync .NewCond (& s .pendingWeightUpdatesMutex )
6363
@@ -70,9 +70,13 @@ func NewSortedSet[ConflictID, ResourceID IDType](owner *Conflict[ConflictID, Res
7070}
7171
7272// Add adds the given Conflict to the SortedSet.
73- func (s * SortedSet [ConflictID , ResourceID ]) Add (conflict * Conflict [ConflictID , ResourceID ]) {
74- s .mutex .Lock ()
75- defer s .mutex .Unlock ()
73+ func (s * SortedSet [ConflictID , ResourceID ]) Add (conflict * Conflict [ConflictID , ResourceID ], optThreadID ... reentrantmutex.ThreadID ) {
74+ if len (optThreadID ) == 0 {
75+ optThreadID = []reentrantmutex.ThreadID {reentrantmutex .NewThreadID ()}
76+ }
77+
78+ s .mutex .Lock (optThreadID [0 ])
79+ defer s .mutex .UnLock (optThreadID [0 ])
7680
7781 newMember , isNew := s .members .GetOrCreate (conflict .id , func () * sortedSetMember [ConflictID , ResourceID ] {
7882 return newSortedSetMember [ConflictID , ResourceID ](s , conflict )
@@ -119,17 +123,21 @@ func (s *SortedSet[ConflictID, ResourceID]) Add(conflict *Conflict[ConflictID, R
119123 }
120124 }
121125
122- if conflict .IsPreferred () && newMember .Compare (s .heaviestPreferredMember ) == weight .Heavier {
126+ if conflict .IsPreferred (optThreadID [ 0 ] ) && newMember .Compare (s .heaviestPreferredMember ) == weight .Heavier {
123127 s .heaviestPreferredMember = newMember
124128
125- s .HeaviestPreferredMemberUpdated .Trigger (conflict , NewTriggerContext ( conflict . ID ()) )
129+ s .HeaviestPreferredMemberUpdated .Trigger (conflict , optThreadID [ 0 ] )
126130 }
127131}
128132
129133// ForEach iterates over all Conflicts of the SortedSet and calls the given callback for each of them.
130- func (s * SortedSet [ConflictID , ResourceID ]) ForEach (callback func (* Conflict [ConflictID , ResourceID ]) error ) error {
131- s .mutex .RLock ()
132- defer s .mutex .RUnlock ()
134+ func (s * SortedSet [ConflictID , ResourceID ]) ForEach (callback func (* Conflict [ConflictID , ResourceID ]) error , optThreadID ... reentrantmutex.ThreadID ) error {
135+ if len (optThreadID ) == 0 {
136+ optThreadID = []reentrantmutex.ThreadID {reentrantmutex .NewThreadID ()}
137+ }
138+
139+ s .mutex .RLock (optThreadID [0 ])
140+ defer s .mutex .RUnlock (optThreadID [0 ])
133141
134142 for currentMember := s .heaviestMember ; currentMember != nil ; currentMember = currentMember .lighterMember {
135143 if err := callback (currentMember .Conflict ); err != nil {
@@ -141,9 +149,13 @@ func (s *SortedSet[ConflictID, ResourceID]) ForEach(callback func(*Conflict[Conf
141149}
142150
143151// HeaviestConflict returns the heaviest Conflict of the SortedSet.
144- func (s * SortedSet [ConflictID , ResourceID ]) HeaviestConflict () * Conflict [ConflictID , ResourceID ] {
145- s .mutex .RLock ()
146- defer s .mutex .RUnlock ()
152+ func (s * SortedSet [ConflictID , ResourceID ]) HeaviestConflict (optThreadID ... reentrantmutex.ThreadID ) * Conflict [ConflictID , ResourceID ] {
153+ if len (optThreadID ) == 0 {
154+ optThreadID = []reentrantmutex.ThreadID {reentrantmutex .NewThreadID ()}
155+ }
156+
157+ s .mutex .RLock (optThreadID [0 ])
158+ defer s .mutex .RUnlock (optThreadID [0 ])
147159
148160 if s .heaviestMember == nil {
149161 return nil
@@ -153,14 +165,16 @@ func (s *SortedSet[ConflictID, ResourceID]) HeaviestConflict() *Conflict[Conflic
153165}
154166
155167// HeaviestPreferredConflict returns the heaviest preferred Conflict of the SortedSet.
156- func (s * SortedSet [ConflictID , ResourceID ]) HeaviestPreferredConflict () * Conflict [ConflictID , ResourceID ] {
157- a := rand .Float64 ()
168+ func (s * SortedSet [ConflictID , ResourceID ]) HeaviestPreferredConflict (optThreadID ... reentrantmutex.ThreadID ) * Conflict [ConflictID , ResourceID ] {
169+ if len (optThreadID ) == 0 {
170+ optThreadID = []reentrantmutex.ThreadID {reentrantmutex .NewThreadID ()}
171+ }
158172
159- fmt .Println ("HeaviestPreferreConflict" , s .owner .ID (), a )
160- defer fmt .Println ("unlocked HeaviestPreferreConflict" , s .owner .ID (), a )
173+ fmt .Println ("HeaviestPreferreConflict" , s .owner .ID (), optThreadID [ 0 ] )
174+ defer fmt .Println ("unlocked HeaviestPreferreConflict" , s .owner .ID (), optThreadID [ 0 ] )
161175
162- s .mutex .RLock ()
163- defer s .mutex .RUnlock ()
176+ s .mutex .RLock (optThreadID [ 0 ] )
177+ defer s .mutex .RUnlock (optThreadID [ 0 ] )
164178
165179 if s .heaviestPreferredMember == nil {
166180 return nil
@@ -200,17 +214,17 @@ func (s *SortedSet[ConflictID, ResourceID]) notifyPendingWeightUpdate(member *so
200214}
201215
202216// notifyPreferredInsteadUpdate notifies the SortedSet about a member that changed its preferred instead flag.
203- func (s * SortedSet [ConflictID , ResourceID ]) notifyPreferredInsteadUpdate (member * sortedSetMember [ConflictID , ResourceID ], preferred bool , visitedConflicts TriggerContext [ ConflictID ] ) {
204- fmt .Println ("Write-Lock" , s .owner .ID (), "notifyPreferredInsteadUpdate(" , member .ID (), "," , preferred , "," , visitedConflicts , ")" )
205- defer fmt .Println ("Write-Unlock" , s .owner .ID (), "notifyPreferredInsteadUpdate(" , member .ID (), "," , preferred , "," , visitedConflicts , ")" )
217+ func (s * SortedSet [ConflictID , ResourceID ]) notifyPreferredInsteadUpdate (member * sortedSetMember [ConflictID , ResourceID ], preferred bool , threadID reentrantmutex. ThreadID ) {
218+ fmt .Println ("Write-Lock" , s .owner .ID (), "notifyPreferredInsteadUpdate(" , member .ID (), "," , preferred , "," , threadID , ")" )
219+ defer fmt .Println ("Write-Unlock" , s .owner .ID (), "notifyPreferredInsteadUpdate(" , member .ID (), "," , preferred , "," , threadID , ")" )
206220
207- s .mutex .Lock ()
208- defer s .mutex .Unlock ( )
221+ s .mutex .Lock (threadID )
222+ defer s .mutex .UnLock ( threadID )
209223
210224 if preferred {
211225 if member .Compare (s .heaviestPreferredMember ) == weight .Heavier {
212226 s .heaviestPreferredMember = member
213- s .HeaviestPreferredMemberUpdated .Trigger (member .Conflict , visitedConflicts )
227+ s .HeaviestPreferredMemberUpdated .Trigger (member .Conflict , threadID )
214228 }
215229
216230 return
@@ -221,12 +235,12 @@ func (s *SortedSet[ConflictID, ResourceID]) notifyPreferredInsteadUpdate(member
221235 }
222236
223237 currentMember := member .lighterMember
224- for currentMember .Conflict != s .owner && ! currentMember .IsPreferred () && currentMember .PreferredInstead () != member .Conflict {
238+ for currentMember .Conflict != s .owner && ! currentMember .IsPreferred (threadID ) && currentMember .PreferredInstead (threadID ) != member .Conflict {
225239 currentMember = currentMember .lighterMember
226240 }
227241
228242 s .heaviestPreferredMember = currentMember
229- s .HeaviestPreferredMemberUpdated .Trigger (currentMember .Conflict , visitedConflicts )
243+ s .HeaviestPreferredMemberUpdated .Trigger (currentMember .Conflict , threadID )
230244}
231245
232246// nextPendingWeightUpdate returns the next member that needs to be updated (or nil if the shutdown flag is set).
@@ -260,21 +274,24 @@ func (s *SortedSet[ConflictID, ResourceID]) fixMemberPositionWorker() {
260274
261275// fixMemberPosition fixes the position of the given member in the SortedSet.
262276func (s * SortedSet [ConflictID , ResourceID ]) fixMemberPosition (member * sortedSetMember [ConflictID , ResourceID ]) {
277+ threadID := reentrantmutex .NewThreadID ()
278+
263279 fmt .Println ("Write-Lock" , s .owner .ID (), "fixMemberPosition(" , member .ID (), ")" )
264280 defer fmt .Println ("Write-Unlock" , s .owner .ID (), "fixMemberPosition(" , member .ID (), ")" )
265281
266- s .mutex .Lock ()
267- defer s .mutex .Unlock ( )
282+ s .mutex .Lock (threadID )
283+ defer s .mutex .UnLock ( threadID )
268284
269- preferredMember := s . preferredInstead ( member )
285+ preferredMember := member . PreferredInstead ( threadID )
270286
271287 // the member needs to be moved up in the list
272288 for currentMember := member .heavierMember ; currentMember != nil && currentMember .Compare (member ) == weight .Lighter ; currentMember = member .heavierMember {
273289 s .swapNeighbors (member , currentMember )
274290
275291 if currentMember .ID () == preferredMember .ID () {
276292 s .heaviestPreferredMember = member
277- s .HeaviestPreferredMemberUpdated .Trigger (member .Conflict , NewTriggerContext (s .owner .ID ()))
293+ fmt .Println ("TRIGGER1" , threadID )
294+ s .HeaviestPreferredMemberUpdated .Trigger (member .Conflict , threadID )
278295 }
279296 }
280297
@@ -283,27 +300,16 @@ func (s *SortedSet[ConflictID, ResourceID]) fixMemberPosition(member *sortedSetM
283300 for currentMember := member .lighterMember ; currentMember != nil && currentMember .Compare (member ) == weight .Heavier ; currentMember = member .lighterMember {
284301 s .swapNeighbors (currentMember , member )
285302
286- if memberIsHeaviestPreferred && s . isPreferred ( currentMember ) {
303+ if memberIsHeaviestPreferred && currentMember . IsPreferred ( threadID ) {
287304 s .heaviestPreferredMember = currentMember
288- s .HeaviestPreferredMemberUpdated .Trigger (currentMember .Conflict , TriggerContext [ConflictID ]{s .owner .ID (): types .Void })
305+ fmt .Println ("TRIGGER2" , threadID )
306+ s .HeaviestPreferredMemberUpdated .Trigger (currentMember .Conflict , threadID )
289307
290308 memberIsHeaviestPreferred = false
291309 }
292310 }
293311}
294312
295- func (s * SortedSet [ConflictID , ResourceID ]) preferredInstead (member * sortedSetMember [ConflictID , ResourceID ]) * Conflict [ConflictID , ResourceID ] {
296- if member .Conflict == s .owner {
297- return s .heaviestPreferredMember .Conflict
298- }
299-
300- return member .PreferredInstead ()
301- }
302-
303- func (s * SortedSet [ConflictID , ResourceID ]) isPreferred (member * sortedSetMember [ConflictID , ResourceID ]) bool {
304- return s .preferredInstead (member ) == member .Conflict
305- }
306-
307313// swapNeighbors swaps the given members in the SortedSet.
308314func (s * SortedSet [ConflictID , ResourceID ]) swapNeighbors (heavierMember , lighterMember * sortedSetMember [ConflictID , ResourceID ]) {
309315 if heavierMember .lighterMember != nil {
0 commit comments