// I am not sure why this code sometimes deadlocks, but sometimes it doesn't.
// Hopefully someone will have some suggestions
package main
// ??? sometimes deadlocks
import (
"fmt"
"sync"
"time"
)
type Button struct {
Clicked *sync.Cond
}
func main() {
button := Button{
Clicked: sync.NewCond(&sync.Mutex{}),
}
// running on goroutine every function that passed/registered
// and wait, not exit until that goroutine is confirmed to be running
subscribe := func(c *sync.Cond, param string, fn func(s string)) {
var goroutineRunning sync.WaitGroup
var cnt = 0
cnt = cnt + 1
fmt.Println("cnt:", cnt)
goroutineRunning.Add(1)
go func(p string) {
goroutineRunning.Done()
c.L.Lock() // critical section
defer c.L.Unlock()
fmt.Println("Registered and wait ... ")
// HANG SPOT: can hang here
c.Wait()
fmt.Println("afer goroutine wait for:", param)
fn(p)
}(param)
fmt.Println("call wait before goroutine exit")
goroutineRunning.Wait()
fmt.Println("after wait, subscribe exits")
}
var clickRegistered sync.WaitGroup
for _, v := range []string{
"Maximizing window.",
"Displaying annoying dialog box!",
"Mouse clicked."} {
clickRegistered.Add(1)
subscribe(button.Clicked, v, func(s string) {
fmt.Println(s, "****************************")
clickRegistered.Done()
})
}
fmt.Println("broadcast")
// is supposed to get the goroutines past HANG SPOT
button.Clicked.Broadcast()
time.Sleep(4000 * time.Millisecond)
clickRegistered.Wait()
}