From 58009b2eda80604fae86605f0b25e330bc9b190d Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 25 Feb 2017 23:32:06 +0100 Subject: Less globals --- philo.go | 123 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 66 insertions(+), 57 deletions(-) diff --git a/philo.go b/philo.go index 6b0846f..811c698 100644 --- a/philo.go +++ b/philo.go @@ -1,97 +1,88 @@ package main import ( + "flag" "fmt" "math/rand" + "strings" "sync" "time" ) -const ( - bites = 3 - delay = 3 -) - -var philo = []string{ - "Aristotle", - "Kant", - "Spinoza", - "Marx", - "Russell", -} - type Fork struct{} type Philo struct { - Name string - LHS chan Fork - RHS chan Fork - Bites int + Name string + LHS chan Fork + RHS chan Fork + Bites int + Delay time.Duration + TimeOut time.Duration } -func rndDelay() { - n := time.Duration(rand.Intn(delay) + 1) - time.Sleep(n * time.Second) +func (p Philo) rndDelay() { + n := rand.Intn(int(p.Delay)) + time.Sleep(time.Duration(n)) } -func (p Philo) state(s string) { +func (p Philo) printState(s string) { fmt.Printf("%10s %s\n", p.Name, s) } -type stateFn func(*Philo) stateFn +type stateFn func() stateFn -func arrive(p *Philo) stateFn { - p.state("arrives") +func (p *Philo) arrive() stateFn { + p.printState("arrives") - return hungry + return p.hungry } -func hungry(p *Philo) stateFn { - p.state("is hungry") +func (p *Philo) hungry() stateFn { + p.printState("is hungry") <-p.LHS // grab left fork select { case <-p.RHS: // try to grab right fork - return eat - case <-time.After(time.Second): + return p.eat + case <-time.After(p.TimeOut): p.LHS <- Fork{} // put left fork back - return starve + return p.starve } - return eat + return p.eat } -func starve(p *Philo) stateFn { - p.state("is starving") - rndDelay() +func (p *Philo) starve() stateFn { + p.printState("is starving") + p.rndDelay() - return hungry + return p.hungry } -func eat(p *Philo) stateFn { - p.state("is eating") - rndDelay() +func (p *Philo) eat() stateFn { + p.printState("is eating") + p.rndDelay() p.LHS <- Fork{} // release left fork p.RHS <- Fork{} // release right fork if p.Bites--; p.Bites <= 0 { - return leave + return p.leave } - return think + return p.think } -func think(p *Philo) stateFn { - p.state("is thinking") - rndDelay() +func (p *Philo) think() stateFn { + p.printState("is thinking") + p.rndDelay() - return hungry + return p.hungry } -func leave(p *Philo) stateFn { - p.state("leaves") +func (p *Philo) leave() stateFn { + p.printState("leaves") return nil } @@ -107,34 +98,52 @@ func prepare(n int) []chan Fork { return forks } -func init() { - rand.Seed(time.Now().UnixNano()) +type Names []string + +func (n Names) String() string { + return fmt.Sprint(strings.Join(n, ",")) +} + +func (n *Names) Set(s string) error { + *n = Names(strings.Split(s, ",")) + return nil } func main() { - fmt.Println(len(philo), "philosophers dining") + names := Names{"Aristotle", "Kant", "Spinoza", "Marx", "Russell"} + bites := flag.Int("bites", 3, "number of rounds") + delay := flag.Duration("max delay", 3*time.Second, "delay") + timeOut := flag.Duration("timeout", time.Second, "delay") + flag.Var(&names, "names", "philospher names") + flag.Parse() + + rand.Seed(time.Now().UnixNano()) + + fmt.Println(len(names), "philosophers dining") defer fmt.Println("Table is empty") - forks := prepare(len(philo)) + forks := prepare(len(names)) wg := sync.WaitGroup{} defer wg.Wait() - for i, name := range philo { + for i, name := range names { wg.Add(1) p := &Philo{ - Name: name, - LHS: forks[i], - RHS: forks[(i+1)%len(philo)], - Bites: bites, + Name: name, + LHS: forks[i], + RHS: forks[(i+1)%len(names)], + Bites: *bites, + Delay: *delay, + TimeOut: *timeOut, } go func(p *Philo) { defer wg.Done() - for state := arrive; state != nil; { - state = state(p) + for state := p.arrive; state != nil; { + state = state() } }(p) } -- cgit v1.2.3