/*
   BarrierTest.java
   
   Description:
      Simple test program that uses the Barrier class

   Author:     Moggen
   Homepage:   http://www.moggen.org/
   License:    Public Domain, use as you like

   Log:
      010926   First version
*/

class BarrierTest {

   public static void main(String args[]){
      println("Main starts");
      println("Barrier 1 holds 3 threads");
      println("Barrier 2 holds 2 threads");
      Barrier theBarrier1=new Barrier(3);
      Barrier theBarrier2=new Barrier(2);
      Thread t1=new Thread(new threadclass1(theBarrier1));
      Thread t2=new Thread(new threadclass2(theBarrier1,theBarrier2));
      Thread t3=new Thread(new threadclass3(theBarrier1,theBarrier2));
      println("Main runs threads");
      try{
         t1.start();
         t2.start();
         t3.start();
      } catch(Exception e) {}
      println("Main waits for threads to complete");
      try{
         t1.join();
         t2.join();
         t3.join();
      } catch(Exception e) {}
      println("Main ends");
   }
         
   static synchronized void println(String str){
      System.out.println(str);
   }
   
   static class threadclass1 implements Runnable {
      Barrier theBarrier1;

      threadclass1(Barrier b1){
         theBarrier1=b1;
      }
      
      public void run(){
         int rc;
         BarrierTest.println("     Thread 1 starts");
         BarrierTest.println("     Thread 1 waits 2 seconds..");
         try {Thread.sleep(2000);} catch(Exception e) {}
         BarrierTest.println("     Thread 1 begins passing barrier 1..");
         theBarrier1.pass();
         BarrierTest.println("     Thread 1 has passed barrier 1");
         BarrierTest.println("     Thread 1 waits 1 second..");
         try {Thread.sleep(1000);} catch(Exception e) {}
         BarrierTest.println("     Thread 1 ends");
      }
   }

   static class threadclass2 implements Runnable {
      Barrier theBarrier1,theBarrier2;

      threadclass2(Barrier b1,Barrier b2){
         theBarrier1=b1; theBarrier2=b2;
      }
      
      public void run(){
         int rc;
         BarrierTest.println("          Thread 2 starts");
         BarrierTest.println("          Thread 2 waits 4 seconds..");
         try {Thread.sleep(4000);} catch(Exception e) {}
         BarrierTest.println("          Thread 2 begins passing barrier 1..");
         theBarrier1.pass();
         BarrierTest.println("          Thread 2 has passed barrier 1");
         BarrierTest.println("          Thread 2 waits 6 seconds..");
         try {Thread.sleep(6000);} catch(Exception e) {}
         BarrierTest.println("          Thread 2 begins passing barrier 2..");
         theBarrier2.pass();
         BarrierTest.println("          Thread 2 has passed barrier 2");
         BarrierTest.println("          Thread 2 ends");
      }
   }

   static class threadclass3 implements Runnable {
      Barrier theBarrier1,theBarrier2;

      threadclass3(Barrier b1,Barrier b2){
         theBarrier1=b1; theBarrier2=b2;
      }
      
      public void run(){
         int rc;
         BarrierTest.println("               Thread 3 starts");
         BarrierTest.println("               Thread 3 waits 6 seconds..");
         try {Thread.sleep(6000);} catch(Exception e) {}
         BarrierTest.println("               Thread 3 begins passing barrier 1..");
         theBarrier1.pass();
         BarrierTest.println("               Thread 3 has passed barrier 1");
         BarrierTest.println("               Thread 3 waits 4 seconds..");
         try {Thread.sleep(4000);} catch(Exception e) {}
         BarrierTest.println("               Thread 3 begins passing barrier 2..");
         theBarrier2.pass();
         BarrierTest.println("               Thread 3 has passed barrier 2");
         BarrierTest.println("               Thread 3 waits 2 seconds..");
         try {Thread.sleep(2000);} catch(Exception e) {}
         BarrierTest.println("               Thread 3 ends");
      }
   }
}
