resource bounded_buffer
   import SRanimator
   op deposit(pid: int; item : real), fetch(cid: int) returns item : real
body bounded_buffer(size : int)
   var buf[0:size-1] : real
   var count : int := 0, take_out : int := 0, put_in : int := 0
   sem elements := 0, spaces := size, mutex := 1
   sem p_mutex := 1, c_mutex := 1

   write("bounded buffer resource with", size, "slots is alive")

   proc deposit(pid, item)
      P(spaces)
      P(p_mutex)

# Move the producer to the slot.
      call A_stepjumpto(2000+pid, 7000+put_in, 5, 100)
# Change a full buffer slot's symbol to be solid black.
      call A_fill(put_in, "solid")

      buf[put_in] := item
      put_in := (put_in + 1) % size
      V(p_mutex)

# Move the producer back to its original position.
      call A_stepjumpto(2000+pid, 4000+pid, 5, 100)
# Change producer's symbol to an outline black circle.
      call A_fill(2000+pid, "outline")
      call A_color(2000+pid, "black")

      P(mutex)
      count++
      write("                               count++ =", count)
      V(mutex)
      V(elements)
   end deposit

   proc fetch(cid) returns item
      P(elements)
      P(c_mutex)

# Move the consumer to the slot.
      call A_stepjumpto(3000+cid, 7000+take_out, 5, 100)
# Change an empty buffer slot's symbol to an outline black circle.
      call A_fill(take_out, "outline")

      item := buf[take_out]
      take_out := (take_out + 1) % size
      V(c_mutex)

# Move the consumer back to its original position.
      call A_stepjumpto(3000+cid, 5000+cid, 5, 100)
# Change consumers's symbol to an outline black circle.
      call A_fill(3000+cid, "outline")
      call A_color(3000+cid, "black")

      P(mutex)
      count--
      write("                               count-- =", count)
      V(mutex)
      V(spaces)
   end fetch
end bounded_buffer
