summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-02-25 23:32:06 +0100
committerDimitri Sokolyuk <demon@dim13.org>2017-02-25 23:32:06 +0100
commit58009b2eda80604fae86605f0b25e330bc9b190d (patch)
tree5f7d450bb3319e8b11f6eb69d1bf0eb77802cea4
parent521f75fd1c6a46c8ac7a1231c66e78526ec23ea2 (diff)
Less globals
-rw-r--r--philo.go123
1 files 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)
}