Concurrency Coordination Reports
Wait Group Barrier Coordination Report
Record how many awaited tasks arrived at a wait-group barrier and report status.
completion barrier
A `sync.WaitGroup` tracks how many tasks a barrier still waits for. `Add` sets the expected count and each `Done` lowers it. Calling `Done` a selected number of times in one goroutine keeps the report deterministic: the barrier is released only when every expected task has arrived, so the status moves from waiting through partial to released as the pending count reaches zero.
Wait Group Barrier Coordination Report
waitgroup_barrier_coordination_report.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"sync"
)
func main() {
var arrivals = 2
expected := 3
var wg sync.WaitGroup
wg.Add(expected)
done := 0
for i := 0; i < arrivals; i++ {
wg.Done()
done++
}
pending := expected - done
var status string
if done == 0 {
status = "waiting"
} else if pending > 0 {
status = "partial"
} else {
wg.Wait()
status = "released"
}
fmt.Printf("expected=%d done=%d pending=%d %s\n", expected, done, pending, status)
}
package main
import (
"fmt"
"sync"
)
func main() {
var arrivals = 0
expected := 3
var wg sync.WaitGroup
wg.Add(expected)
done := 0
for i := 0; i < arrivals; i++ {
wg.Done()
done++
}
pending := expected - done
var status string
if done == 0 {
status = "waiting"
} else if pending > 0 {
status = "partial"
} else {
wg.Wait()
status = "released"
}
fmt.Printf("expected=%d done=%d pending=%d %s\n", expected, done, pending, status)
}
package main
import (
"fmt"
"sync"
)
func main() {
var arrivals = 3
expected := 3
var wg sync.WaitGroup
wg.Add(expected)
done := 0
for i := 0; i < arrivals; i++ {
wg.Done()
done++
}
pending := expected - done
var status string
if done == 0 {
status = "waiting"
} else if pending > 0 {
status = "partial"
} else {
wg.Wait()
status = "released"
}
fmt.Printf("expected=%d done=%d pending=%d %s\n", expected, done, pending, status)
}
arrivals ← 2, expected ← 3, wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0}
8func main() {9 var arrivals→ 2 = 2 //@arrivals=0, 310 expected→ 3 := 311 var wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0} sync.WaitGroup12 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr A⟩}, sema:0x0}.Add(expected3)13 done→ 0 := 014 for i := 0; i < arrivals; i++ {wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0}
pass 1 of 213done := 014for i0 := 0; i < arrivals2; i++ {15 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0}.Done()16 done→ 1++17}wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr C⟩}, sema:0x0}
pass 2 of 213done := 014for i1 := 0; i < arrivals2; i++ {15 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr C⟩}, sema:0x0}.Done()16 done→ 2++17}pending ← 1, status ← ""
17}18pending→ 1 := expected3 - done219var status→ "" string20if done == 0 {status ← "partial"
21 status = "waiting"22} else if pending1 > 0 {23 status→ "partial" = "partial"24} else {fmt.Printf("expected=%d done=%d pending=%d %s ", expected, done, pendi…
27 }28 fmt.Printf("expected=%d done=%d pending=%d %s\n", expected3, done2, pending1, status"partial")29}outputexpected=3 done=2 pending=1 partial
arrivals ← 0, expected ← 3, wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0}
8func main() {9 var arrivals→ 0 = 010 expected→ 3 := 311 var wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0} sync.WaitGroup12 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr A⟩}, sema:0x0}.Add(expected3)13 done→ 0 := 014 for i := 0; i < arrivals; i++ {15 wg.Done()16 done++17 }18 pending→ 3 := expected3 - done019 var status→ "" string20 if done == 0 {status ← "waiting"
19var status string20if done0 == 0 {21 status→ "waiting" = "waiting"22} else if pending > 0 {fmt.Printf("expected=%d done=%d pending=%d %s ", expected, done, pendi…
27 }28 fmt.Printf("expected=%d done=%d pending=%d %s\n", expected3, done0, pending3, status"waiting")29}outputexpected=3 done=0 pending=3 waiting
arrivals ← 3, expected ← 3, wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0}
8func main() {9 var arrivals→ 3 = 310 expected→ 3 := 311 var wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0} sync.WaitGroup12 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr A⟩}, sema:0x0}.Add(expected3)13 done→ 0 := 014 for i := 0; i < arrivals; i++ {wg ← sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0}
pass 1 of 313done := 014for i0 := 0; i < arrivals3; i++ {15 wg→ sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0}.Done()16 done→ 1++17}All 3 passes — pass 1 is the card above pass iwgdone1 0 sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr A⟩}, sema:0x0} → sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0} 0 → 1 2 1 sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr B⟩}, sema:0x0} → sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr C⟩}, sema:0x0} 1 → 2 3 2 sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:⟨addr C⟩}, sema:0x0} → sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0} 2 → 3 pending ← 0, status ← ""
17}18pending→ 0 := expected3 - done319var status→ "" string20if done == 0 {status ← "released"
23 status = "partial"24} else {25 wgsync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x0}, sema:0x0}.Wait()26 status→ "released" = "released"27}fmt.Printf("expected=%d done=%d pending=%d %s ", expected, done, pendi…
27 }28 fmt.Printf("expected=%d done=%d pending=%d %s\n", expected3, done3, pending0, status"released")29}outputexpected=3 done=3 pending=0 released