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