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