import java.io.*;

public class BakerySimulation2
{			
	public static void main(String argv[])
	{
		Buffer shelf = new Buffer(Integer.parseInt(argv[1]));
		Baker b = new Baker(Integer.parseInt(argv[0]), shelf);
		Thread bakerThread = new Thread(b);
		bakerThread.setDaemon(true);
		bakerThread.start();
		(new Thread(new BakeryDesk(b))).start();
	} //end main()
} //class BakerySimulation2
	
class BakeryDesk implements Runnable
{
	Baker b;
	public BakeryDesk(Baker b)
	{
		this.b = b;
	} //constructor
		
	public void run()
	{
		FileReader fr = new FileReader( FileDescriptor.in );	
		try
		{
			while (fr.read() != 'x')
			{
				(new Thread(new Customer(b))).start();
			} //while
		} //try
		catch (IOException ioe)
		{
			System.out.println("An IOException caught\n"+ioe.getMessage());
			ioe.printStackTrace();
			System.exit(1);
		} //catch()
	} //run()
} //class BakeryDesk
	
class Baker implements Runnable
{
	Semaphore bakerSem;
	Buffer shelf;
	public Baker(int noBakers, Buffer shelf)
	{
		bakerSem = new Semaphore(noBakers);
		this.shelf = shelf;
	} //constructor
	
	public void run()
	{
		for (;;)
		{
			try
			{
				Thread.sleep(500);
			} //try
			catch (InterruptedException ie)
			{
				System.out.println("An InterruptedException caught\n"+ie.getMessage());
				ie.printStackTrace();
				System.exit(1);
			} //catch()
			shelf.put("bread");
			System.out.println("refilling shelf ...");
		} //do forever
	} //run()
	
	public void bake()
	{
		shelf.get(); //return type is ignored here		
		System.out.println("stock size: "+shelf.getSize() );
	} //bake()
} //class Baker

class Customer implements Runnable
{
	Baker myBaker;
	
	public Customer(Baker b)
	{
		myBaker = b;
	} //constructor
	
	public void run()
	{
		//System.out.println("new customer "+Thread.currentThread().getName()+" shows up");
		long start = System.currentTimeMillis();
		myBaker.bakerSem.p();
		myBaker.bake();
		myBaker.bakerSem.v();
		System.out.println("waiting time for "+Thread.currentThread().getName()+": "+ (System.currentTimeMillis()-start));
		System.out.println("queue lenght: "+ (Thread.currentThread().activeCount()-4) );
	} //requestBread();
} //class Customer
