import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class Sample4 extends Applet implements AdjustmentListener {
  VBBB vb;
  Scrollbar hScroll1, hScroll2;
  public int y = 1000;
  public int w = 2000;
  public void init() {
    setLayout(new BorderLayout());
    hScroll1 = new Scrollbar(Scrollbar.HORIZONTAL,1000,100,500,3000);
    hScroll2 = new Scrollbar(Scrollbar.HORIZONTAL,2000,100,500,3000);
    add("North",hScroll1);
    add("South",hScroll2);
    hScroll1.addAdjustmentListener(this);
    hScroll2.addAdjustmentListener(this);
    vb = new VBBB(this);
    PProducer p = new PProducer(this,vb); CConsumer c = new CConsumer(this,vb);
    p.start(); c.start();
  }
  public void paint(Graphics g) {
    vb.Draw(g);
  }
  public void adjustmentValueChanged(AdjustmentEvent e)
  {
    if(e.getAdjustable() == hScroll1) {
      y = hScroll1.getValue();
      repaint();
    }
    if(e.getAdjustable() == hScroll2) {
      w = hScroll2.getValue();
      repaint();
    }
  }
}
class VBBB {
  int values[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  int inputp=0; int outputp=0;
  Semaphore isem; Semaphore osem;
  Pointer ip; Pointer op; Sample4 sp;
  VBBB(Sample4 sp) {
    isem=new Semaphore(10); osem=new Semaphore(0);
    ip=new Pointer(0,40); op=new Pointer(0,160);
    this.sp=sp;
  }
  public void input(int i) {
    isem.Wait();
    values[inputp]=i; inputp=(++inputp)%10;
    ip.inc(); sp.repaint();
    osem.Signal();
  }
  public int output() {
    osem.Wait();
    int r=values[outputp];
    values[outputp]=-1;
    outputp=(++outputp)%10;
    op.inc(); sp.repaint();
    isem.Signal();
    return r;
  }
  public void Draw(Graphics g) {
    ip.Draw(g,isem.Value()); op.Draw(g,osem.Value());
    for(int i=0;i<10;i++) { g.drawRect(50+i*40,100,40,40); }
    for(int i=0;i<10;i++)
      if(values[i]!=-1) { 
        g.fillOval(60+i*40,110,20,20);
//        g.drawString((values[i])+"",65+i*40,125);
      }
  }
}
class Pointer {
  int x, y;
  Pointer(int x,int y) {
    this.x=x; this.y=y;
  }
  public void inc() {
    x=(++x)%10;
  }
  public void Draw(Graphics g,int value) {
    int xx=50+x*40;
    g.drawLine(xx+10,y,xx+30,y);
    g.drawLine(xx+30,y,xx+30,y+20);
    g.drawLine(xx+30,y+20,xx+40,y+20);
    g.drawLine(xx+40,y+20,xx+20,y+40);
    g.drawLine(xx+20,y+40,xx,y+20);
    g.drawLine(xx,y+20,xx+10,y+20);
    g.drawLine(xx+10,y+20,xx+10,y);
    g.drawString(value+"",xx+15,y+20);
  }
}
class PProducer extends Thread {
  VBBB bbuffer; Sample4 parent;
  PProducer(Sample4 s,VBBB bbuffer) {
    this.bbuffer=bbuffer;
    this.parent=s;
  }
  public void run() {
    for(int i=1; i<=10000; i++) {
      try {
	sleep(parent.y);
      } catch (InterruptedException e) {}
        bbuffer.input(i);
    }
  }
}
class CConsumer extends Thread {
  VBBB bbuffer; Sample4 parent;
  CConsumer(Sample4 s,VBBB bbuffer) {
    this.bbuffer=bbuffer;
    this.parent=s;
  }
  public void run() {
    for(int i=0; i<10000; i++) {
      try {
	sleep(parent.w);
      } catch (InterruptedException e) {}
      bbuffer.output();
    }
  }
}
