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