RosettaCodeData/Task/Checkpoint-synchronization/Go/checkpoint-synchronization-...

69 lines
1.7 KiB
Go

package main
import (
"log"
"math/rand"
"os"
"sync"
"time"
)
const nMech = 5
const detailsPerMech = 4
var l = log.New(os.Stdout, "", 0)
func main() {
assemble := make(chan int)
var complete sync.WaitGroup
go solicit(assemble, &complete, nMech*detailsPerMech)
for i := 1; i <= nMech; i++ {
complete.Add(detailsPerMech)
for j := 0; j < detailsPerMech; j++ {
assemble <- 0
}
// Go checkpoint feature
complete.Wait()
// checkpoint reached
l.Println("mechanism", i, "completed")
}
}
func solicit(a chan int, c *sync.WaitGroup, nDetails int) {
rand.Seed(time.Now().UnixNano())
var id int // worker id, for output
for nDetails > 0 {
// some random time to find a worker
time.Sleep(time.Duration(5e8 + rand.Int63n(5e8)))
id++
// contract to assemble a certain number of details
contract := rand.Intn(5) + 1
if contract > nDetails {
contract = nDetails
}
dword := "details"
if contract == 1 {
dword = "detail"
}
l.Println("worker", id, "contracted to assemble", contract, dword)
go worker(a, c, contract, id)
nDetails -= contract
}
}
func worker(a chan int, c *sync.WaitGroup, contract, id int) {
// some random time it takes for this worker to assemble a detail
assemblyTime := time.Duration(5e8 + rand.Int63n(5e8))
l.Println("worker", id, "enters shop")
for i := 0; i < contract; i++ {
<-a
l.Println("worker", id, "assembling")
time.Sleep(assemblyTime)
l.Println("worker", id, "completed detail")
c.Done()
}
l.Println("worker", id, "leaves shop")
}