/*
 * File         : Prequest.java
 * Author       : Sang Lim, Xinying Li, Bryan Carpenter
 * Created      : Thu Apr  9 12:22:15 1998
 * Revision     : $Revision: 1.8 $
 * Updated      : $Date: 1999/09/14 20:50:18 $
 * Copyright: Northeast Parallel Architectures Center
 *            at Syracuse University 1998
 */

package mpi;

public class Prequest extends Request {

  protected final static int MODE_STANDARD    = 3;
  protected final static int MODE_BUFFERED    = 4;
  protected final static int MODE_SYNCHRONOUS = 5;
  protected final static int MODE_READY       = 6;

  protected Prequest() {}

  /**
   * Constructor used by `Send_init', etc.
   */

  protected Prequest(int mode, 
                     Object buf, int offset, int count, Datatype type,
                     int dest, int tag, Comm comm,
                     int [] length_buf, Prequest hdrReq) {

    opTag  = Request.OP_SEND_OBJECT ;

    this.mode   = mode ;

    this.buf    = buf;
    this.offset = offset;
    this.count  = count;
    this.type   = type;
    this.dest   = dest;
    this.tag    = tag;
    this.comm   = comm ;

    this.length_buf = length_buf;

    this.hdrReq = hdrReq ;
  }

  /**
   * Constructor used by `Recv_init'.
   */

  protected Prequest(Object buf, int offset, int count, Datatype type,
                     int source, int tag, Comm comm,
                     int [] length_buf) {

    opTag  = Request.OP_RECV_OBJECT ;

    this.buf    = buf;
    this.offset = offset;
    this.count  = count;
    this.type   = type;
    this.src    = source;
    this.tag    = tag;
    this.comm   = comm;

    this.length_buf = length_buf;
  }


  /**
   * Activate a persistent communication request.
   * Java binding of the MPI operation <tt>MPI_START</tt>.
   * The communication is completed by using the request in
   * one of the <tt>wait</tt> or <tt>test</tt> operations.
   * On successful completion the request becomes inactive again.
   * It can be reactivated by a further call to <tt>Start</tt>.
   */

  public void Start() throws MPIException {
    byte [] byte_buf ;
    switch (opTag) {
      case OP_NORMAL :
	start();

	break;
      case OP_SEND_OBJECT :
        byte_buf = comm.Object_Serialize(buf,offset,count,type);

        length_buf[0] = byte_buf.length;
        length_buf[1] = count ;

        ((Prequest) hdrReq).start() ;
         
        switch(mode) {
          case MODE_STANDARD :
	    comm.Isend(byte_buf, 0, byte_buf.length,
		       MPI.BYTE, dest, tag, this);
            break;
          case MODE_BUFFERED :
            comm.Ibsend(byte_buf, 0, byte_buf.length, 
                        MPI.BYTE, dest, tag, this);
            break;
          case MODE_SYNCHRONOUS :
	    comm.Isend(byte_buf, 0, byte_buf.length,
		       MPI.BYTE, dest, tag, this);
            break;
          case MODE_READY :
            comm.Isend(byte_buf, 0, byte_buf.length, 
                       MPI.BYTE, dest, tag, this);
            break;
        }

        break ;
      case OP_RECV_OBJECT :
        start() ;

        break ;
      default : 
        System.out.println("Unknown Tag..."+opTag);
        break;
    }   	   
  }

  private native void start();

  /**
   * Activate a list of communication requests.
   * <p>
   * <table>
   * <tr><td><tt> array_of_requests </tt></td><td> array of requests </tr>
   * </table>
   * <p>
   * Java binding of the MPI operation <tt>MPI_STARTALL</tt>.
   */

  public static void Startall(Prequest [] array_of_request)
                                                       throws MPIException {
    int req_length = array_of_request.length ;

    boolean allNormal = true ;
    for (int i = 0; i<req_length; i++)
      allNormal = allNormal && array_of_request[i].opTag == OP_NORMAL ;

    if (allNormal)
      startall(array_of_request) ;
    else
      for (int i = 0; i<req_length; i++)
        array_of_request[i].Start() ;
  }

  private static native void startall(Prequest [] array_of_request);

}

