@@ -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