/**
 * 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.Semaphore;

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() {
        try{
            String n = Thread.currentThread().getName();
            pieno.acquire();
            mutex.acquire();
            int ris = memory[--quanti];
            mutex.release();
            vuoto.release();
        
            System.out.println(n + " ha letto");
            return ris;
        }
        catch(InterruptedException e){
            System.err.println(e);
            return -1;
        }
    }

    public final void put(final int newMemory) {
        try{
            String n = Thread.currentThread().getName();
            vuoto.acquire();
            mutex.acquire();
            memory[quanti++] = newMemory;
            mutex.release();
            pieno.release();
            System.out.println(n + " ha scritto");
        }
        catch(InterruptedException e){
            System.err.println(e);
        }
    }

    private static final Semaphore mutex = new Semaphore(1);
    private static final Semaphore pieno = new Semaphore(0);
    private static final Semaphore vuoto = new Semaphore(SIZE);

}


public class PCSem {

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

}
