package main import ( "fmt" "math/rand" "time" ) func init() { rand.Seed(time.Now().UnixNano()) } type Philo struct { Name string Left Fork Right Fork Rounds int MaxDelay time.Duration TimeOut time.Duration } func (p Philo) Delay() { n := rand.Intn(int(p.MaxDelay)) time.Sleep(time.Duration(n)) } func (p Philo) Print(s string) { fmt.Printf("%10s %s\n", p.Name, s) } func (p Philo) Arrive() stateFn { p.Print("arrives") return p.Hungry } func (p Philo) Hungry() stateFn { p.Print("is hungry") p.Left.Get() if ok := p.Right.TryGet(p.TimeOut); ok { return p.Eat } p.Left.Put() return p.Starve } func (p Philo) Starve() stateFn { p.Print("is starving") p.Delay() return p.Hungry } func (p *Philo) Eat() stateFn { p.Print("is eating") p.Delay() p.Left.Put() p.Right.Put() if p.Rounds--; p.Rounds <= 0 { return p.Leave } return p.Think } func (p Philo) Think() stateFn { p.Print("is thinking") p.Delay() return p.Hungry } func (p Philo) Leave() stateFn { p.Print("leaves") return nil } type stateFn func() stateFn func (p Philo) Dine() { for state := p.Arrive; state != nil; { state = state() } }