1 /*
   2  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
  13  *                         reserved.
  14  * Copyright (c) 2018      FUJITSU LIMITED.  All rights reserved.
  15  * $COPYRIGHT$
  16  *
  17  * Additional copyrights may follow
  18  *
  19  * $HEADER$
  20  *
  21  *
  22  * This file is almost a complete re-write for Open MPI compared to the
  23  * original mpiJava package. Its license and copyright are listed below.
  24  * See <path to ompi/mpi/java/README> for more information.
  25  *
  26  *
  27  *  Licensed under the Apache License, Version 2.0 (the "License");
  28  *  you may not use this file except in compliance with the License.
  29  *  You may obtain a copy of the License at
  30  *
  31  *     http://www.apache.org/licenses/LICENSE-2.0
  32  *
  33  *  Unless required by applicable law or agreed to in writing, software
  34  *  distributed under the License is distributed on an "AS IS" BASIS,
  35  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  36  *  See the License for the specific language governing permissions and
  37  *  limitations under the License.
  38  *
  39  * File         : Request.java
  40  * Author       : Sang Lim, Xinying Li, Bryan Carpenter
  41  * Created      : Thu Apr  9 12:22:15 1998
  42  * Revision     : $Revision: 1.11 $
  43  * Updated      : $Date: 2001/08/07 16:36:25 $
  44  * Copyright: Northeast Parallel Architectures Center
  45  *            at Syracuse University 1998
  46  *
  47  *
  48  *
  49  * Note: in a send request for a buffer containing objects, the primary
  50  * `MPI_Request' referenced by `handle' is the request to send the data.
  51  * The request to send the header is in the secondary field, `hdrReq'.
  52  * Conversely, in a *receive* request for a buffer containing objects
  53  * the primary `MPI_Request' is the request to send the header.
  54  * The receive of the data is not initiated until a `wait' or `test'
  55  * operation succeeds.
  56  *
  57  *
  58  *
  59  * Probably `Request' should be an abstract class, and there should
  60  * be several concrete subclasses.  At the moment requests are created
  61  * in a few different ways, and the differently constructed requests are
  62  * typically using different subsets of fields.  DBC 7/12/01
  63  */
  64 
  65 package mpi;
  66 
  67 import java.nio.Buffer;
  68 
  69 /**
  70  * Request object.
  71  */
  72 public class Request implements Freeable
  73 {
  74         protected long handle;
  75         protected Buffer sendBuf;
  76         protected Buffer recvBuf;
  77 
  78         static
  79         {
  80                 init();
  81         }
  82 
  83         private static native void init();
  84 
  85         protected static native long getNull();
  86 
  87         protected Request(long handle)
  88         {
  89                 this.handle = handle;
  90         }
  91 
  92         /**
  93          * Set the request object to be void.
  94          * Java binding of the MPI operation {@code MPI_REQUEST_FREE}.
  95          */
  96         @Override public void free() throws MPIException
  97         {
  98                 if(!isNull())
  99                 {
 100                         MPI.check();
 101                         handle = free(handle);
 102                 }
 103         }
 104 
 105         private native long free(long req) throws MPIException;
 106 
 107         /**
 108          * Mark a pending nonblocking communication for cancellation.
 109          * Java binding of the MPI operation {@code MPI_CANCEL}.
 110          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 111          */
 112         public final void cancel() throws MPIException
 113         {
 114                 MPI.check();
 115                 cancel(handle);
 116         }
 117 
 118         private native void cancel(long request) throws MPIException;
 119 
 120         /**
 121          * Adds a receive buffer to this Request object.  This method
 122          * should be called by the internal api whenever a persistent
 123          * request is created and any time a request object, that has
 124          * an associated buffer, is returned from an operation to protect
 125          * the buffer from getting prematurely garbage collected.
 126          * @param buf buffer to add to the array list
 127          */
 128         protected final void addRecvBufRef(Buffer buf)
 129         {
 130                 this.recvBuf = buf;
 131         }
 132 
 133         /**
 134          * Adds a send buffer to this Request object.  This method
 135          * should be called by the internal api whenever a persistent
 136          * request is created and any time a request object, that has
 137          * an associated buffer, is returned from an operation to protect
 138          * the buffer from getting prematurely garbage collected.
 139          * @param buf buffer to add to the array list
 140          */
 141         protected final void addSendBufRef(Buffer buf)
 142         {
 143                 this.sendBuf = buf;
 144         }
 145 
 146         /**
 147          * Test if request object is null.
 148          * @return true if the request object is null, false otherwise
 149          */
 150         public final boolean isNull()
 151         {
 152                 return handle == 0 || handle == MPI.REQUEST_NULL.handle;
 153         }
 154 
 155         /**
 156          * Blocks until the operation identified by the request is complete.
 157          * <p>Java binding of the MPI operation {@code MPI_WAIT}.
 158          * <p>After the call returns, the request object becomes inactive.
 159          * @return status object
 160          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 161          */
 162         public final Status waitStatus() throws MPIException
 163         {
 164                 MPI.check();
 165                 Status status = new Status();
 166                 handle = waitStatus(handle, status.data);
 167                 return status;
 168         }
 169 
 170         private native long waitStatus(long request, long[] stat) throws MPIException;
 171 
 172         /**
 173          * Blocks until the operation identified by the request is complete.
 174          * <p>Java binding of the MPI operation {@code MPI_WAIT}.
 175          * <p>After the call returns, the request object becomes inactive.
 176          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 177          */
 178         public final void waitFor() throws MPIException
 179         {
 180                 MPI.check();
 181                 handle = waitFor(handle);
 182         }
 183 
 184         private native long waitFor(long request) throws MPIException;
 185 
 186         /**
 187          * Returns a status object if the operation identified by the request
 188          * is complete, or a null reference otherwise.
 189          * <p>Java binding of the MPI operation {@code MPI_TEST}.
 190          * <p>After the call, if the operation is complete (ie, if the return
 191          * value is non-null), the request object becomes inactive.
 192          * @return status object
 193          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 194          */
 195         public final Status testStatus() throws MPIException
 196         {
 197                 MPI.check();
 198                 return testStatus(handle);
 199         }
 200 
 201         private native Status testStatus(long request) throws MPIException;
 202 
 203         /**
 204          * Returns a status object if the operation identified by the request
 205          * is complete, or a null reference otherwise.
 206          * <p>Java binding of the MPI operation {@code MPI_REQUEST_GET_STATUS}.
 207          * <p>After the call, if the operation is complete (ie, if the return
 208          * value is non-null), the request object remains active.
 209          * @return status object
 210          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 211          */
 212         public final Status getStatus() throws MPIException
 213         {
 214                 MPI.check();
 215                 return getStatus(handle);
 216         }
 217 
 218         private native Status getStatus(long request) throws MPIException;
 219 
 220         /**
 221          * Returns true if the operation identified by the request
 222          * is complete, or false otherwise.
 223          * <p>Java binding of the MPI operation {@code MPI_TEST}.
 224          * <p>After the call, if the operation is complete (ie, if the return
 225          * value is true), the request object becomes inactive.
 226          * @return true if the operation identified by the request, false otherwise
 227          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 228          */
 229         public final boolean test() throws MPIException
 230         {
 231                 MPI.check();
 232                 return test(handle);
 233         }
 234 
 235         private native boolean test(long handle) throws MPIException;
 236 
 237         /**
 238          * Blocks until one of the operations associated with the active
 239          * requests in the array has completed.
 240          * <p>Java binding of the MPI operation {@code MPI_WAITANY}.
 241          * <p>The index in array of {@code requests} for the request that
 242          * completed can be obtained from the returned status object through
 243          * the {@code Status.getIndex()} method. The corresponding element
 244          * of array of {@code requests} becomes inactive.
 245          * @param requests array of requests
 246          * @return status object
 247          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 248          */
 249         public static Status waitAnyStatus(Request[] requests) throws MPIException
 250         {
 251                 MPI.check();
 252                 long[] r = getHandles(requests);
 253                 Status status = new Status();
 254                 waitAnyStatus(r, status.data);
 255                 setHandles(requests, r);
 256                 return status;
 257         }
 258 
 259         private static native void waitAnyStatus(long[] requests, long[] status)
 260                         throws MPIException;
 261 
 262         /**
 263          * Blocks until one of the operations associated with the active
 264          * requests in the array has completed.
 265          * <p>Java binding of the MPI operation {@code MPI_WAITANY}.
 266          * <p>The request that completed becomes inactive.
 267          * @param requests array of requests
 268          * @return The index in array of {@code requests} for the request that
 269          * completed. If all of the requests are MPI_REQUEST_NULL, then index
 270          * is returned as {@code MPI.UNDEFINED}.
 271          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 272          */
 273         public static int waitAny(Request[] requests) throws MPIException
 274         {
 275                 MPI.check();
 276                 long[] r = getHandles(requests);
 277                 int index = waitAny(r);
 278                 setHandles(requests, r);
 279                 return index;
 280         }
 281 
 282         private static native int waitAny(long[] requests) throws MPIException;
 283 
 284         /**
 285          * Tests for completion of either one or none of the operations
 286          * associated with active requests.
 287          * <p>Java binding of the MPI operation {@code MPI_TESTANY}.
 288          * <p>If some request completed, the index in array of {@code requests}
 289          * for that request can be obtained from the returned status object.
 290          * The corresponding element in array of {@code requests} becomes inactive.
 291          * If no request completed, {@code testAnyStatus} returns {@code null}.
 292          * @param requests array of requests
 293          * @return status object if one request completed, {@code null} otherwise.
 294          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 295          */
 296         public static Status testAnyStatus(Request[] requests) throws MPIException
 297         {
 298                 MPI.check();
 299                 long[] r = getHandles(requests);
 300                 Status status = testAnyStatus(r);
 301                 setHandles(requests, r);
 302                 return status;
 303         }
 304 
 305         private static native Status testAnyStatus(long[] requests) throws MPIException;
 306 
 307         /**
 308          * Tests for completion of either one or none of the operations
 309          * associated with active requests.
 310          * <p>Java binding of the MPI operation {@code MPI_TESTANY}.
 311          * <p>If some request completed, it becomes inactive.
 312          * @param requests array of requests
 313          * @return index of operation that completed, or {@code MPI.UNDEFINED}
 314          * if none completed.
 315          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 316          */
 317         public static int testAny(Request[] requests) throws MPIException
 318         {
 319                 MPI.check();
 320                 long[] r = getHandles(requests);
 321                 int index = testAny(r);
 322                 setHandles(requests, r);
 323                 return index;
 324         }
 325 
 326         private static native int testAny(long[] requests) throws MPIException;
 327 
 328         /**
 329          * Blocks until all of the operations associated with the active
 330          * requests in the array have completed.
 331          * <p>Java binding of the MPI operation {@code MPI_WAITALL}.
 332          * <p>On exit, requests become inactive.  If the <em>input</em> value of
 333          * array of {@code requests} contains inactive requests, corresponding
 334          * elements of the status array will contain null status references.
 335          * @param requests array of requests
 336          * @return array of statuses
 337          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 338          */
 339         public static Status[] waitAllStatus(Request[] requests) throws MPIException
 340         {
 341                 MPI.check();
 342                 long[] r = getHandles(requests);
 343                 Status[] status = waitAllStatus(r);
 344                 setHandles(requests, r);
 345                 return status;
 346         }
 347 
 348         private static native Status[] waitAllStatus(long[] requests)
 349                         throws MPIException;
 350 
 351         /**
 352          * Blocks until all of the operations associated with the active
 353          * requests in the array have completed.
 354          * <p>Java binding of the MPI operation {@code MPI_WAITALL}.
 355          * @param requests array of requests
 356          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 357          */
 358         public static void waitAll(Request[] requests) throws MPIException
 359         {
 360                 MPI.check();
 361                 long[] r = getHandles(requests);
 362                 waitAll(r);
 363                 setHandles(requests, r);
 364         }
 365 
 366         private static native void waitAll(long[] requests) throws MPIException;
 367 
 368         /**
 369          * Tests for completion of <em>all</em> of the operations associated
 370          * with active requests.
 371          * <p>Java binding of the MPI operation {@code MPI_TESTALL}.
 372          * <p>If all operations have completed, the exit value of the argument array
 373          * is as for {@code waitAllStatus}.
 374          * @param requests array of requests
 375          * @return array of statuses if all operations have completed,
 376          *         {@code null} otherwise.
 377          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 378          */
 379         public static Status[] testAllStatus(Request[] requests) throws MPIException
 380         {
 381                 MPI.check();
 382                 long[] r = getHandles(requests);
 383                 Status[] status = testAllStatus(r);
 384                 setHandles(requests, r);
 385                 return status;
 386         }
 387 
 388         private static native Status[] testAllStatus(long[] requests)
 389                         throws MPIException;
 390 
 391         /**
 392          * Tests for completion of <em>all</em> of the operations associated
 393          * with active requests.
 394          * <p>Java binding of the MPI operation {@code MPI_TESTALL}.
 395          * @param requests array of requests
 396          * @return {@code true} if all operations have completed,
 397          *         {@code false} otherwise.
 398          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 399          */
 400         public static boolean testAll(Request[] requests) throws MPIException
 401         {
 402                 MPI.check();
 403                 long[] r = getHandles(requests);
 404                 boolean completed = testAll(r);
 405                 setHandles(requests, r);
 406                 return completed;
 407         }
 408 
 409         private static native boolean testAll(long[] requests) throws MPIException;
 410 
 411         /**
 412          * Blocks until at least one of the operations associated with the active
 413          * requests in the array has completed.
 414          * <p>Java binding of the MPI operation {@code MPI_WAITSOME}.
 415          * <p>The size of the result array will be the number of operations that
 416          * completed. The index in array of {@code requests} for each request that
 417          * completed can be obtained from the returned status objects through the
 418          * {@code Status.getIndex()} method. The corresponding element in
 419          * array of {@code requests} becomes inactive.
 420          * @param requests array of requests
 421          * @return array of statuses or {@code null} if the number of operations
 422          *         completed is {@code MPI_UNDEFINED}.
 423          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 424          */
 425         public static Status[] waitSomeStatus(Request[] requests) throws MPIException
 426         {
 427                 MPI.check();
 428                 long[] r = getHandles(requests);
 429                 Status[] status = waitSomeStatus(r);
 430                 setHandles(requests, r);
 431                 return status;
 432         }
 433 
 434         private static native Status[] waitSomeStatus(long[] requests)
 435                         throws MPIException;
 436 
 437         /**
 438          * Blocks until at least one of the operations associated with the active
 439          * active requests in the array has completed.
 440          * <p>Java binding of the MPI operation {@code MPI_WAITSOME}.
 441          * <p>The size of the result array will be the number of operations that
 442          * completed. The corresponding element in array of {@code requests} becomes
 443          * inactive.
 444          * @param requests array of requests
 445          * @return array of indexes of {@code requests} that completed or {@code null}
 446          *         if the number of operations completed is {@code MPI_UNDEFINED}.
 447          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 448          */
 449         public static int[] waitSome(Request[] requests) throws MPIException
 450         {
 451                 MPI.check();
 452                 long[] r = getHandles(requests);
 453                 int[] indexes = waitSome(r);
 454                 setHandles(requests, r);
 455                 return indexes;
 456         }
 457 
 458         private static native int[] waitSome(long[] requests) throws MPIException;
 459 
 460         /**
 461          * Behaves like {@code waitSome}, except that it returns immediately.
 462          * <p>Java binding of the MPI operation {@code MPI_TESTSOME}.
 463          * <p>If no operation has completed, {@code testSome} returns an array of
 464          * length zero, otherwise the return value are as for {@code waitSome}.
 465          * @param requests array of requests
 466          * @return array of statuses
 467          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 468          */
 469         public static Status[] testSomeStatus(Request[] requests) throws MPIException
 470         {
 471                 MPI.check();
 472                 long[] r = getHandles(requests);
 473                 Status[] status = testSomeStatus(r);
 474                 setHandles(requests, r);
 475                 return status;
 476         }
 477 
 478         private static native Status[] testSomeStatus(long[] requests)
 479                         throws MPIException;
 480 
 481         /**
 482          * Behaves like {@code waitSome}, except that it returns immediately.
 483          * <p>Java binding of the MPI operation {@code MPI_TESTSOME}.
 484          * <p>If no operation has completed, {@code testSome} returns an array of
 485          * length zero, otherwise the return value are as for {@code waitSome}.
 486          * @param requests array of requests
 487          * @return array of indexes of {@code requests} that completed.
 488          * @throws MPIException Signals that an MPI exception of some sort has occurred.
 489          */
 490         public static int[] testSome(Request[] requests) throws MPIException
 491         {
 492                 MPI.check();
 493                 long[] r = getHandles(requests);
 494                 int[] indexes = testSome(r);
 495                 setHandles(requests, r);
 496                 return indexes;
 497         }
 498 
 499         private static native int[] testSome(long[] requests) throws MPIException;
 500 
 501         protected static long[] getHandles(Request[] r)
 502         {
 503                 long[] h = new long[r.length];
 504 
 505                 for(int i = 0; i < r.length; i++) {
 506                         if(r[i] != null)
 507                                 h[i] = r[i].handle;
 508                         else
 509                                 h[i] = 0;
 510                 }
 511 
 512                 return h;
 513         }
 514 
 515         protected static void setHandles(Request[] r, long[] h)
 516         {
 517                 for(int i = 0; i < r.length; i++)
 518                         r[i].handle = h[i];
 519         }
 520 
 521 } // Request