resource Servant
  op getforks() {call},  # invoked by philosophers
     relforks() {call}
  op needL() {send},     # invoked by neighboring
     needR() {send},     # servants.
     passL() {send},
     passR() {send}
  op links(cap Servant l, cap Servant r)  # links to neighbors
  op forks(bool haveL, bool dirtyL, bool haveR, bool dirtyR)
	# initial fork values passed from main
body Servant(int id)
  bool  haveL, dirtyL, haveR, dirtyR
  cap Servant  l, r
  op hungry() {send}, eat() {send}

  proc getforks()  {
    send hungry() # tell server Philosopher is hungry
    receive eat() # wait for permission to eat
  }

  process server  {
    receive links(l, r)
    receive forks(haveL, dirtyL, haveR, dirtyR)
    while (true) {
      in hungry() ->
	  # ask for forks I don't have; I ask my
	  # right neighbor for his left fork,
	  # and my left neighbor for his right fork
	  if (~haveR) { send r.needL() }
	  if (~haveL) { send l.needR() }
	  # wait until I have both forks
	  while (~(haveL and haveR)) {
	    in passR() ->
		haveR = true; dirtyR = false
	    [] passL() ->
		haveL = true; dirtyL = false
	    [] needR() st dirtyR ->
		haveR = false; dirtyR = false
		send r.passL(); send r.needL()
	    [] needL() st dirtyL ->
		haveL = false; dirtyL = false
		send l.passR(); send l.needR()
	    ni
	  }
	  # let my Philosopher eat;
	  # then wait for it to finish
	  send eat(); dirtyL = true; dirtyR = true
	  receive relforks()
      [] needR() ->
	  # right neighbor needs his left fork,
	  # which is my right fork
	  haveR = false; dirtyR = false
	  send r.passL()
      [] needL() ->
	  # left neighbor needs his right fork,
	  # which is my left fork
	  haveL = false; dirtyL = false
	  send l.passR()
      ni
    }
  }
end

resource Philosopher
  import Servant
body Philosopher(cap Servant s, int id, int t)
  process phil  {
    for [ i = 1 to t ] {
      s.getforks()
      write("Philosopher", id, "is eating")   # eat
      s.relforks()
      write("Philosopher", id, "is thinking") # think
    }
  }
end

resource Main()
  import Philosopher, Servant
  int n = 5 , t= 5
  cap Servant  s[1:n]
  # create the Servants and Philosophers
  for [ i = 1 to n ] {
    s[i] = create Servant(i)
    create Philosopher(s[i], i, t)
  }
  # give each Servant capabilities for
  # its two neighboring Servants
  for [ i = 1 to n ] {
    send s[i].links(s[((i-2) mod n) + 1],
		    s[(i mod n) + 1])
  }
  # initialize each Servant's forks;
  # it is asymmetric to prevent deadlock
  send s[1].forks(true, false, true, false)
  for [ i = 2 to n-1 ] {
    send s[i].forks(false, false, true, false)
  }
  send s[n].forks(false, false, false, false)
end
