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