summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-09-22 20:21:12 +0200
committerDimitri Sokolyuk <demon@dim13.org>2015-09-22 20:21:12 +0200
commitf9d29de97d2f2195fca8cc762a290046191aa014 (patch)
tree762b87b19d0ccf89f48e3f9eaf01032b5574b82f
Initial import
-rw-r--r--philo.go121
1 files changed, 121 insertions, 0 deletions
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)
+ }
+}