Dijkstra的饭桌上的哲学家

1         Embedding

namespace DiningPhilosophers

2         Model

structure Fork

index as Integer

abstract class Philosopher

var status as State = Thinking

index as Integer

abstract canMove(table as Table) as Boolean

abstract move(table as Table)

numPhilosophers as Integer  = 5

numForks as Integer  = numPhilosophers

forks as Set of Fork = {Fork(i) | i in {1..numForks}}

left(p as Philosopher) as Fork

return Fork(p.index)

right(p as Philosopher) as Fork

return Fork(p.index mod numPhilosophers + 1)

enum State

Thinking

Hungry

HungryWithLeftFork

Eating

class Table

philosophers as Set of Philosopher

class Table

var holder as Map of Fork to Philosopher = { -> }

var fed as Set of Philosopher = {}

class Table

var stepNo as Integer = 0

[EntryPoint]

Move()

choose phil in philosophers where phil.canMove(me)

phil.move(me)

stepNo := stepNo + 1

EntryPoint使得被标记的方法能够被外部世界调用，例如可以被C#调用。

2.1      Greedy Philosophers

class GreedyPhilosopher extends Philosopher

override move(table as Table)

match status

Thinking : status := Hungry

Hungry   : if not (left(me) in table.holder)

table.holder(left(me)) :=

me as Philosopher

status := HungryWithLeftFork

HungryWithLeftFork

: if not (right(me) in table.holder)

table.holder(right(me)) :=

me as Philosopher

status := Eating

add me to table.fed

Eating   : remove table.holder(left(me))

remove table.holder(right(me))

status := Thinking

canMove方法指出哲学家是否能够改变状态：

class GreedyPhilosopher

override canMove(table as Table) as Boolean

return status = Thinking

or (status = Hungry and

left(me) notin table.holder)

or (status = HungryWithLeftFork and

right(me) notin table.holder)

or status = Eating

2.2      Generous Philosophers

class GenerousPhilosopher extends Philosopher

override move(table as Table)

match status

Thinking : status := Hungry

Hungry   : if not (left(me) in table.holder)

table.holder(left(me)) :=

me as Philosopher

status := HungryWithLeftFork

HungryWithLeftFork

: if not (right(me) in table.holder)

table.holder(right(me)) :=

me as Philosopher

status := Eating

add me to table.fed

else

// someone else is holding the

// right fork

// put the left one down and

// try again another time

remove table.holder(left(me))

status := Thinking

Eating   : remove table.holder(left(me))

remove table.holder(right(me))

status := Thinking

class GenerousPhilosopher

override canMove(table as Table) as Boolean

return status = Thinking

or (status = Hungry and

left(me) notin table.holder)

or status = HungryWithLeftFork

or status = Eating

3         Providing the View

class Table

[EntryPoint]

shared InitGreedy() as Table

philosophers = { new GreedyPhilosopher(i) as Philosopher |

i in [1..numPhilosophers] }

return new Table(philosophers)

[EntryPoint]

shared InitGenerous() as Table

philosophers = { new GenerousPhilosopher(i) as Philosopher |

i in [1..numPhilosophers] }

return new Table(philosophers)

class Table

HoldsLeft(pIndex as Integer) as Boolean

return exists (i,p) in holder where p.index = pIndex and

left(p) = i

HoldsRight(pIndex as Integer) as Boolean

return exists (i,p) in holder where p.index = pIndex and

right(p) = i

IsFeeded(pIndex as Integer) as Boolean

return exists p in fed where p.index = pIndex

IsDeadlock() as Boolean

return forall p in philosophers holds not p.canMove(me)

IsGreedy() as Boolean

return exists p in philosophers where p is GreedyPhilosopher

StepNo() as Integer

return stepNo

0 0