69 lines
1.7 KiB
Go
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")
|
|
}
|