package main
import (
"sync"
"sync/atomic"
"time"
)
type GetNumFn func() int
type ConditionFn func() bool
type IncrementalNumGetter struct {
num atomic.Int32
}
func (g *IncrementalNumGetter) GetAndIncrease() int {
return int(g.num.Add(1))
}
func (g *IncrementalNumGetter) IsOdd() bool {
return g.num.Load()%2 == 1
}
func (g *IncrementalNumGetter) IsEven() bool {
return g.num.Load()%2 == 0
}
type StopFn func() bool
var neverStop StopFn = func() bool {
return false
}
func main() {
var (
wg sync.WaitGroup
mu sync.Mutex
condA = sync.NewCond(&mu)
condB = sync.NewCond(&mu)
)
wg.Add(2)
var numGetter IncrementalNumGetter
go PrintNum(&wg, condA, condB, numGetter.GetAndIncrease, numGetter.IsOdd, neverStop)
go PrintNum(&wg, condB, condA, numGetter.GetAndIncrease, numGetter.IsEven, neverStop)
condA.Signal()
wg.Wait()
}
func PrintNum(wg *sync.WaitGroup, cond *sync.Cond, anotherCond *sync.Cond, getNum GetNumFn, conditionFn ConditionFn, stopFn StopFn) {
defer wg.Done()
for !stopFn() {
cond.L.Lock()
for !conditionFn() {
cond.Wait()
}
num := getNum()
println(num)
time.Sleep(200 * time.Millisecond)
cond.L.Unlock()
anotherCond.Signal()
}
}