// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ // See page 234. // Package cake provides a simulation of // a concurrent cake shop with numerous parameters. // // Use this command to run the benchmarks: // $ go test -bench=. gopl.io/ch8/cake package cake import ( "fmt" "math/rand" "time" ) type Shop struct { Verbose bool Cakes int // number of cakes to bake BakeTime time.Duration // time to bake one cake BakeStdDev time.Duration // standard deviation of baking time BakeBuf int // buffer slots between baking and icing NumIcers int // number of cooks doing icing IceTime time.Duration // time to ice one cake IceStdDev time.Duration // standard deviation of icing time IceBuf int // buffer slots between icing and inscribing InscribeTime time.Duration // time to inscribe one cake InscribeStdDev time.Duration // standard deviation of inscribing time } type cake int func (s *Shop) baker(baked chan<- cake) { for i := 0; i < s.Cakes; i++ { c := cake(i) if s.Verbose { fmt.Println("baking", c) } work(s.BakeTime, s.BakeStdDev) baked <- c } close(baked) } func (s *Shop) icer(iced chan<- cake, baked <-chan cake) { for c := range baked { if s.Verbose { fmt.Println("icing", c) } work(s.IceTime, s.IceStdDev) iced <- c } } func (s *Shop) inscriber(iced <-chan cake) { for i := 0; i < s.Cakes; i++ { c := <-iced if s.Verbose { fmt.Println("inscribing", c) } work(s.InscribeTime, s.InscribeStdDev) if s.Verbose { fmt.Println("finished", c) } } } // Work runs the simulation 'runs' times. func (s *Shop) Work(runs int) { for run := 0; run < runs; run++ { baked := make(chan cake, s.BakeBuf) iced := make(chan cake, s.IceBuf) go s.baker(baked) for i := 0; i < s.NumIcers; i++ { go s.icer(iced, baked) } s.inscriber(iced) } } // work blocks the calling goroutine for a period of time // that is normally distributed around d // with a standard deviation of stddev. func work(d, stddev time.Duration) { delay := d + time.Duration(rand.NormFloat64()*float64(stddev)) time.Sleep(delay) }