/**
 * 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
 */

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() {
        String n = Thread.currentThread().getName();
        synchronized(syncPC){
            while(isVuoto()){
                System.out.println(n + " ha tentato di leggere");
                try {
                    syncPC.wait();
                } catch (InterruptedException e) {
                    System.err.println(e);
                }
            }
            int ris = memory[--quanti];
            if (quanti == SIZE - 1) syncPC.notifyAll();
            System.out.println(n + " ha letto");
            return ris;
        }
    }

    public final void put(final int newMemory) {
        String n = Thread.currentThread().getName();
        synchronized(syncPC){
            while (isPieno()){
                System.out.println(n + " ha tentato di scrivere");
                try {
                    syncPC.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
            memory[quanti++] = newMemory;
            if (quanti == 1) syncPC.notifyAll();
            System.out.println(n + " ha scritto");
        }
    }

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

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

    private Object syncPC = new Object();
}


public class PC {

    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();
    }

}


