/**
 * Describe class PC here.
 *
 *
 * Created: Fri Jun  8 14:32:29 2007
 *
 * @author <a href="mailto:mattia.monga@unimi.it">Mattia Monga</a>
 * @version 1.0
 */
import java.util.concurrent.locks.*;

class Actor extends Thread 
{
    public Actor(String nome){
        super(nome);
    }
    
    private Magazzino shared;
    public final Magazzino getShared() {
        return shared;
    }
    public final void setShared(final Magazzino newShared) {
        this.shared = newShared;
    }

}


class Produttore extends Actor {
    public Produttore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    
    public void run(){
        int i = 0;
        while(true){
            System.out.println(getName() + ": Inserisco " + i + " nel buffer");
            getShared().put(i);
            i += 1;
        }
    }
}

class Consumatore extends Actor{
    public Consumatore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    public void run(){
        while(true){
            int i = getShared().get();
            System.out.println(getName() + ": Estraggo " + i + " dal buffer");

        }
    }
}

class Magazzino{
    public final static int SIZE = 10;
    private int[] memory = new int[SIZE];
    private int quanti = 0;
    
    public final int get() {
        monitor.lock();
        int ris = -1;
        try{
            String n = Thread.currentThread().getName();
            while (isVuoto()){
                System.out.println(n + " ha tentato di leggere");
                empty.await();
            }
            ris = memory[--quanti];
            if (quanti == SIZE - 1) full.signal();
            System.out.println(n + " ha letto");
        } catch (InterruptedException e){
            System.err.println(e);
        } finally {
            monitor.unlock();
            return ris;
        }
    }

    public final void put(final int newMemory) {
        monitor.lock();
        try{
            String n = Thread.currentThread().getName();
            while (isPieno()){
                System.out.println(n + " ha tentato di scrivere");
                full.await();
            }
            memory[quanti++] = newMemory;
            if (quanti == 1) empty.signal();
            System.out.println(n + " ha scritto");
        } catch (InterruptedException e){
            System.err.println(e);
        } finally {
            monitor.unlock();
        }
    }

    public final boolean isVuoto() {
        return quanti == 0;
    }

    public final boolean isPieno() {
        return quanti == SIZE;
    }


    private static final Lock monitor = new ReentrantLock();
    private static final Condition empty = monitor.newCondition();
    private static final Condition full = monitor.newCondition();


}


public class PCMon {

    public static final void main(final String[] args) {
        Magazzino x = new Magazzino();
        Produttore a1 = new Produttore("Aldo", x);
        Produttore a2 = new Produttore("Alberto", x);
        Consumatore b = new Consumatore("Barbara", x);
        a1.start();
        b.start();
        a2.start();
    }

}


