From f9d29de97d2f2195fca8cc762a290046191aa014 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 22 Sep 2015 20:21:12 +0200 Subject: Initial import --- philo.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 philo.go diff --git a/philo.go b/philo.go new file mode 100644 index 0000000..1e26799 --- /dev/null +++ b/philo.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "math/rand" + "sync" + "time" +) + +const ( + bites = 3 + delay = 3 +) + +var philo = []string{ + "Aristotle", + "Kant", + "Spinoza", + "Marx", + "Russell", +} + +type Philo struct { + Name string + LHS chan bool + RHS chan bool + Bites int +} + +func rndDelay() { + n := time.Duration(rand.Intn(delay) + 1) + time.Sleep(n * time.Second) +} + +func (p Philo) state(s string) { + fmt.Printf("%10s %s\n", p.Name, s) +} + +type stateFn func(*Philo) stateFn + +func arrive(p *Philo) stateFn { + p.state("arrives") + + return hungry +} + +func hungry(p *Philo) stateFn { + p.state("is hungry") + + <-p.LHS // grab a fork + <-p.RHS // grab a fork + + return eat +} + +func eat(p *Philo) stateFn { + p.state("is eating") + rndDelay() + + p.LHS <- true // release a fork + p.RHS <- true // release a fork + + if p.Bites -= 1; p.Bites <= 0 { + return leave + } + + return think +} + +func think(p *Philo) stateFn { + p.state("is thinking") + rndDelay() + + return hungry +} + +func leave(p *Philo) stateFn { + p.state("leaves") + + return nil +} + +func prepare(n int) []chan bool { + forks := make([]chan bool, n) + + for i := range forks { + forks[i] = make(chan bool, 1) + forks[i] <- true // put a fork + } + + return forks +} + +func main() { + fmt.Println(len(philo), "philosophers dining") + defer fmt.Println("Table is empty") + + forks := prepare(len(philo)) + + wg := sync.WaitGroup{} + defer wg.Wait() + + for i, name := range philo { + wg.Add(1) + + p := &Philo{ + Name: name, + LHS: forks[i], + RHS: forks[(i+1)%len(philo)], + Bites: bites, + } + + go func(p *Philo) { + defer wg.Done() + + for state := arrive; state != nil; { + state = state(p) + } + }(p) + } +} -- cgit v1.2.3