// CyclicBarrier4.java   multiple uses of threads with await()

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
 
public class CyclicBarrier4
{
  int matrix[][] = { { 1 }, 
                     { 2, 2 }, 
                     { 3, 3, 3 },
                     { 4, 4, 4, 4 }, 
                     { 5, 5, 5, 5, 5 } };
  int results[];
  CyclicBarrier barrier;
 
  CyclicBarrier4()
  {
    final int rows = matrix.length;
    results = new int[rows];
    Merger my_merger = new Merger(rows);

    // public CyclicBarrier(int parties,Runnable barrierAction)
    // Creates a new CyclicBarrier that will trip when the given number
    // of parties (threads) are waiting upon it, and which will execute 
    // the Merger task when the barrier is tripped, performed 
    // by the last thread entering the barrier.

    barrier = new CyclicBarrier(rows, my_merger);
    for (int i = 0; i < rows; i++)
    {
      new Summer(i).start();
    }
    System.out.println("CyclicBarrier4 constructor finished");
  } // end constructor CyclicBarrier4

  class Summer extends Thread
  {
    int row;
 
    Summer(int row)
    {
      this.row = row;
    } // end constructor summer
 
    public void run()
    {
      int columns = matrix[row].length;
      int sum = 0;
      for (int i = 0; i < columns; i++)
      {
        sum += matrix[row][i];
      }
      results[row] = sum;
      System.out.println("Results for row " + row + " are : " + sum);
      // wait for others
      try
      {
        barrier.await();
        // can do more processing
        sum = 0;
        for (int i=0; i<columns-1; i++) // short
        {
          sum += matrix[row][i];
        }
        results[row] = sum;
        System.out.println("Results short row "+row+" are : "+sum);
        barrier.await(); // we are done, but need last merge
      }
      catch (InterruptedException ex)
      {
	System.out.println("InterruptedException");
      }
      catch (BrokenBarrierException ex)
      {
	System.out.println("BrokenBarrierException");
      } // end try
    } // end run
  } // end class summer

  class Merger implements Runnable // very time all reach await()
  {
    int rows;
    Merger(int arows)
    {
      rows = arows;
    }
    public void run()
    {
      int sum = 0;
      for (int i = 0; i < rows; i++)
      {
        sum += results[i];
      }
      System.out.println("my_merge results are: " + sum);
    } // end run
  } // end Merger
 
  public static void main(String args[])
  {
    new CyclicBarrier4();
    System.out.println("CyclicBarrier4 main finished");
  } // end main
} // end CyclicBarrier4

