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 {
	// Puffer fuer die Objekte
	private Object[] buffer;

	// Maximale Anzahl von Elemnten
	private final int MAXELEMS = 3;

	// Aktuell enthalten
	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) {
		if (isFull()) // Falls Depot voll
			try {
				wait(); // warten bis jemand mich aufweckt
			} catch (InterruptedException e) {
			}

		// Element einstellen
		buffer[counter] = data;
		counter++;
		System.out.println("----> Produziert: " + data);
		
		// anderen Thread bescheid geben
		notify();
	}

	/**
	 * 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() {
		if (empty()) // Falls leer
			try {
				wait(); // warten
			} catch (InterruptedException e) {
			}

		// Element rausholen
		Object result = buffer[0];
		// Rest von rechts nach links ruecken lassen
		System.arraycopy(buffer, 1, buffer, 0, buffer.length - 1);
		counter--;
		System.out.println("<-- Konsumiert: " + result);

		// Anderen Thread bescheid geben
		notify();
		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;
	}
}
