package utp;

public class Cell<T> {
	private T value = null;

	
	private boolean query = false;
	private boolean result = false;
	
	private boolean stop = false;

	public Cell() {}

	public synchronized void put(T val) throws StopException {
		while (true) {
			if (stop == true) {
				throw new StopException();
			}
			if (query == true) {
				break;
			}
			try {
				this.wait();
			} catch (InterruptedException e) {}
		}
		
		query = false;
		this.notifyAll();
		
		while (true) {
			if (stop == true) {
				throw new StopException();
			}
			if (result == false) {
				break;
			}
			try {
				this.wait();
			} catch (InterruptedException e) {}
		}	
		
		value = val;
		result = true;
		this.notifyAll();
		
	}

	public synchronized T get() throws StopException {
		while (true) {
			if (query == false) {
				break;
			}
			if (stop == true) {
				throw new StopException();
			}
			try {
				this.wait();
			} catch (InterruptedException e) {}
		}
		
		query = true;
		this.notifyAll();
		
		while (true) {
			if (result == true) {
				break;
			}
			if (stop == true) {
				throw new StopException();
			}
			try {
				this.wait();
			} catch (InterruptedException e) {}
		}
		
		T val = value;
		value = null;
		result = false;
		this.notifyAll();

		return val;
	}

	public synchronized void stop() {
		this.stop = true;
		this.notifyAll();
	}
}