package stm import ( "flag" ) const maxTokens = 25 var nFlag = flag.Int( "n", 1_000, "The number of iterations to execute", ) func MainTest() { flag.Parse() n := *nFlag for i := 0; i < n; i++ { continue // FIXME done := NewBuiltinEqVar(false) tokens := NewBuiltinEqVar(0) pending := NewVar(NewSet[*Var[bool]]()) for i := 0; i < 1000; i++ { ready := NewVar(false) Atomically(VoidOperation(func(tx *Tx) { pending.Set(tx, pending.Get(tx).Add(ready)) })) go func() { Atomically(VoidOperation(func(tx *Tx) { tx.Assert(ready.Get(tx)) set := pending.Get(tx) if !set.Contains(ready) { panic("couldn't find ourselves in pending") } pending.Set(tx, set.Delete(ready)) })) //b.Log("waiter finished") }() } go func() { for Atomically(func(tx *Tx) bool { if done.Get(tx) { return false } tx.Assert(tokens.Get(tx) < maxTokens) tokens.Set(tx, tokens.Get(tx)+1) return true }) { } }() go func() { for Atomically(func(tx *Tx) bool { tx.Assert(tokens.Get(tx) > 0) tokens.Set(tx, tokens.Get(tx)-1) pending.Get(tx).Range(func(ready *Var[bool]) bool { if !ready.Get(tx) { ready.Set(tx, true) return false } return true }) return !done.Get(tx) }) { } }() Atomically(VoidOperation(func(tx *Tx) { tx.Assert(pending.Get(tx).(Lenner).Len() == 0) })) AtomicSet(done, true) } }