resource user()
   import MPDanimator
   import bounded_buffer
   cap bounded_buffer  bb 
   int slots = 15, pnum = 7, cnum = 5, pnap = 3, cnap = 2, runtime = 60
   getarg(1, slots); getarg(2, pnum); getarg(3, cnum)
   getarg(4, pnap); getarg(5, cnap); getarg(6, runtime)

   write("main user resource alive, slots=", slots, "pnum=", pnum,
      "cnum==", cnum, "pnap==", pnap, "cnap==", cnap, "runtime==", runtime)
   bb = create bounded_buffer(slots)

# Change coordinates so 0,0 is the center, then create a big black outline
# circle to be the bounded buffer.
   call A_coords(-1.7, -1.7, 1.5, 1.5)
   call A_circle(1001, 0.0, 0.0, 1.0, "black", "outline")
# Put some annotated symbols on the screen.
   call A_circle(1002, -1.6, -1.6, 0.05, "blue", "solid")
   call A_text(1003, -1.5, -1.625, 0, "black", "consumer wants to fetch")
   call A_circle(1004, -1.6, -1.4, 0.05, "green", "solid")
   call A_text(1005, -1.5, -1.425, 0, "black", "producer wants to deposit")
   call A_circle(1006, -1.6, -1.1, 0.1, "black", "outline")
   call A_text(1007, -1.4, -1.125, 0, "black", "empty buffer slot")
   call A_circle(1008, -1.6, -0.8, 0.1, "black", "solid")
   call A_text(1009, -1.4, -0.825, 0, "black", "full buffer slot")
# Put some producers, small black outline circles, near the buffer.
# Also put a point for each producer to move back to after depositing.
   call A_text(1016, -0.5+0.12*(pnum+1), -1.61, 0, "black", "producers")
   for [ i = 1 to pnum ] {
      call A_circle(2000+i, -0.5+0.12*i, -1.6, 0.05, "black", "outline")
      call A_circle(4000+i, -0.5+0.12*i, -1.6, 0.001, "black", "outline")
   }
# Put some consumers, small black outline circles, near the buffer.
# Also put a point for each consumer to move back to after fetching.
   call A_text(1017, -0.5+0.12*(cnum+1), -1.41, 0, "black", "consumers")
   for [ i = 1 to cnum ] {
      call A_circle(3000+i, -0.5+0.12*i, -1.4, 0.05, "black", "outline")
      call A_circle(5000+i, -0.5+0.12*i, -1.4, 0.001, "black", "outline")
   }
# Put the buffer slots, black outline circles, around the buffer.
   const real TWO_PI = 2.0*acos(-1.0)
   for [ i = 0 to slots-1 ] {
      call A_circle(i, sin(i*(TWO_PI/slots)), cos(i*(TWO_PI/slots)),
	 0.1, "black", "outline")
# Number the buffer slots.
      call A_text(6000+i, 0.85*sin(i*(TWO_PI/slots)),
	 0.85*cos(i*(TWO_PI/slots)), 1, "black", string(i))
# Put nearly invisible circles (points) near each buffer slot to be places
# the producers and consumers can be moved to when they to deposit into or
# fetch from the buffer.
      call A_circle(7000+i, 1.15*sin(i*(TWO_PI/slots)),
	 1.15*cos(i*(TWO_PI/slots)), 0.001, "black", "outline")
   }

   process producer [ pid = 1 to pnum ] {
      real it
      int napping 

      while (true) {
	 napping = int(random(1000*pnap))
	 write("age=", age(), "PRODUCER", pid, "napping for", napping, "ms")
	 nap(napping)
	 it = random()
	 write("age=", age(), "PRODUCER", pid, "produced item", it)

# Change a wants-to-deposit producers's symbol to be solid green.
	 call A_color(2000+pid, "green")
	 call A_fill(2000+pid, "solid")

	 bb.deposit(pid, it)
	 write("age=", age(), "PRODUCER", pid, "deposited item", it)
      }
   }

   process consumer [ cid = 1 to cnum ] {
      real it
      int napping

      while (true) {
	 napping = int(random(1000*cnap))
	 write("age=", age(), "consumer", cid, "napping for", napping, "ms")
	 nap(napping)
	 write("age=", age(), "consumer", cid, "wants to consume ...")

# Change a wants-to-fetch consumer's symbol to be solid blue.
	 call A_color(3000+cid, "blue")
	 call A_fill(3000+cid, "solid")

	 it = bb.fetch(cid)
	 write("age=", age(), "consumer", cid, "fetched item ", it)
      }
   }

   nap(1000*runtime); write("must stop now"); call A_end(); stop
end user
