package producerconsumer1;

/**
 * Ein Depot fuer eine beschraenkte Anzahl von Objekten.
 * 
 * @author Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet
 *         Osnabrueck
 * @date 06.05.2007
 */
public class Depot {
	private Object[] buffer;
	private final int MAXELEMS = 3;
	
	private int counter;

	public Depot() {
		buffer = new Object[MAXELEMS];
		counter = 0;
	}

	/**
	 * Ein Element ins Depot packen. Eventuell muss man warten bis das Depot
	 * wieder Platz hat. Die Methode ist auf das Depot synchronisiert, damit
	 * nicht gleichzeitig mehrere Aenderungen vornehmen koennen.
	 * 
	 * @param data
	 *            Einzustellendes Element.
	 */
	public synchronized void put(Object data) {
		while (isFull())	// Solange voll ist weiterwarten
			try {
				wait();
			} catch (InterruptedException e) {
			}
		
		buffer[counter] = data;
		counter++;
		System.out.printf("----> %s produziert: %s%n", Thread.currentThread().getName(), data);
		notifyAll();
	}

	/**
	 * Element vom Depot holen. Eventuell muss man warten, bis das Depot etwas
	 * enthaelt. Die Methode ist auf das Depot synchronisiert, damit nicht
	 * gleichzeitig mehrere Aenderungen vornehmen koennen.
	 * 
	 * @return Element aus dem Depot
	 */
	public synchronized Object get() {
		while (empty())		// Solange leer ist weiterwarten
			try {
				wait();
			} catch (InterruptedException e) {
			}
		
		Object result = buffer[0];
		System.arraycopy(buffer, 1, buffer, 0, buffer.length-1);
		counter--;
		System.out.printf("<-- %s konsumiert: %s%n", Thread.currentThread().getName(), result);
		
		notifyAll();
		return result;
	}

	/**
	 * Depot voll?
	 * @return true wenn voll, sonst false
	 */
	public boolean isFull() {
		return counter == MAXELEMS;
	}

	/**
	 * Depot leer?
	 * @return true wenn leer, sonst false
	 */
	public boolean empty() {
		return counter == 0;
	}
}
