1
1
openmpi/ompi/mpi/java/java/Struct.java
Jeff Squyres 20c772e733 Cleanup language about MPI exceptions --> errors
MPI-4 is finally cleaning up its language: an MPI "exception" does not
actually exist.  The only thing that exists is an MPI "error" (and
associated handlers).  This commit replaces all relevant uses of the
word "exception" with "error".  Note that this is still applicable in
versions of the MPI standard less than MPI-4.0 (indeed, nearly all the
cases fixed in this commit are just changes to comments, anyway).

One exception to this is the Java bindings, where there's an
MPIException class.  In hindsight, it probably should have been named
MPIError, but changing it now would break anyone who is using the Java
bindings.

Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
2020-08-17 13:57:47 -04:00

803 строки
21 KiB
Java

/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
package mpi;
import java.nio.*;
import java.util.*;
/**
* Base class for defining struct data types.
*/
public abstract class Struct
{
private int extent;
private ArrayList<Field> fields = new ArrayList<Field>();
private Datatype datatype, types[];
private int offsets[], lengths[];
private static final String typeMismatch = "Type mismatch";
private void commit() throws MPIException
{
if(datatype == null)
createStruct();
}
private void createStruct() throws MPIException
{
int count = fields.size();
types = new Datatype[count];
offsets = new int[count];
lengths = new int[count];
for(int i = 0; i < count; i++)
{
Field f = fields.get(i);
types[i] = f.type instanceof Struct ? ((Struct)f.type).datatype
: (Datatype)f.type;
offsets[i] = f.offset;
lengths[i] = f.length;
}
datatype = Datatype.createStruct(lengths, offsets, types);
datatype.commit();
extent = datatype.getExtent();
}
/**
* Returns the extent of the struct data type.
* @return Extent of the struct data type.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final int getExtent() throws MPIException
{
commit();
return extent;
}
/**
* Returns the data type of the struct.
* @return The data type of the struct.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final Datatype getType() throws MPIException
{
commit();
return datatype;
}
/**
* Creates a Data object.
* @return New Data object.
*/
protected abstract Data newData();
@SuppressWarnings("unchecked")
private <T extends Data> T newData(ByteBuffer buffer, int offset)
{
Data d = newData();
d.buffer = buffer;
d.offset = offset;
return (T)d;
}
@SuppressWarnings("javadoc")
/**
* Gets a Data object in order to access to the buffer.
* @param buffer the Data object will read/write on this buffer.
* @return Data object
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final <T extends Data> T getData(ByteBuffer buffer) throws MPIException
{
commit();
return newData(buffer, 0);
}
@SuppressWarnings("javadoc")
/**
* Gets a Data object in order to access to the struct at the
* specified position of a struct array stored in a Buffer.
* @param buffer The Data object will read/write on this buffer.
* @param index Index of the struct in the buffer.
* @return Data object.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final <T extends Data> T getData(ByteBuffer buffer, int index)
throws MPIException
{
commit();
return newData(buffer, index * extent);
}
@SuppressWarnings("javadoc")
/**
* Gets a Data object in order to access to the byte array.
* @param array The Data object will read/write on this byte array.
* @return Data object.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final <T extends Data> T getData(byte[] array) throws MPIException
{
ByteBuffer buffer = ByteBuffer.wrap(array);
buffer.order(ByteOrder.nativeOrder());
return getData(buffer);
}
@SuppressWarnings("javadoc")
/**
* Gets a Data object in order to access to the struct at the
* specified position of a struct array stored in a byte array.
* @param array The Data object will read/write on this byte array.
* @param index Index of the struct in the array.
* @return Data object.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final <T extends Data> T getData(byte[] array, int index)
throws MPIException
{
ByteBuffer buffer = ByteBuffer.wrap(array);
buffer.order(ByteOrder.nativeOrder());
return getData(buffer, index);
}
private int addField(Object type, int typeExtent, int length)
{
if(datatype != null)
throw new AssertionError("The struct data type was committed.");
int offset = extent;
extent += typeExtent * length;
fields.add(new Field(type, offset, length));
return offset;
}
/**
* Sets the offset of the next field.
* <p>The offset must be greater or equal to the accumulated extent.
* @param offset offset of the next field
* @return this object in order to allow adding fields in a chained expression
*/
public final Struct setOffset(int offset)
{
if(datatype != null)
throw new AssertionError("The struct data type was committed.");
if(offset < extent)
{
throw new IllegalArgumentException(
"The offset must be greater or equal to the accumulated extent.");
}
extent = offset;
return this;
}
/**
* Adds a byte field to this struct.
* @return Offset of the new field.
*/
public final int addByte()
{
return addByte(1);
}
/**
* Adds a byte array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addByte(int length)
{
return addField(MPI.BYTE, 1, length);
}
/**
* Adds a char field to this struct.
* @return Offset of the new field.
*/
public final int addChar()
{
return addChar(1);
}
/**
* Adds a char array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addChar(int length)
{
return addField(MPI.CHAR, 2, length);
}
/**
* Adds a short field to this struct.
* @return Offset of the new field.
*/
public final int addShort()
{
return addShort(1);
}
/**
* Adds a short array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addShort(int length)
{
return addField(MPI.SHORT, 2, length);
}
/**
* Adds an int field to this struct.
* @return Offset of the new field.
*/
public final int addInt()
{
return addInt(1);
}
/**
* Adds an int array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addInt(int length)
{
return addField(MPI.INT, 4, length);
}
/**
* Adds a long field to this struct.
* @return Offset of the new field.
*/
public final int addLong()
{
return addLong(1);
}
/**
* Adds a long array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addLong(int length)
{
return addField(MPI.LONG, 8, length);
}
/**
* Adds a float field to this struct.
* @return Offset of the new field.
*/
public final int addFloat()
{
return addFloat(1);
}
/**
* Adds a float array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addFloat(int length)
{
return addField(MPI.FLOAT, 4, length);
}
/**
* Adds a double field to this struct.
* @return Offset of the new field.
*/
public final int addDouble()
{
return addDouble(1);
}
/**
* Adds a double array to this struct.
* @param length Length of the array.
* @return Offset of the new field.
*/
public final int addDouble(int length)
{
return addField(MPI.DOUBLE, 8, length);
}
/**
* Adds a struct field to this struct.
* @param struct Type of the field.
* @return Offset of the new field.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final int addStruct(Struct struct) throws MPIException
{
return addStruct(struct, 1);
}
/**
* Adds an array of structs to this struct.
* @param struct Type of the array.
* @param length Length of the array.
* @return Offset of the new field.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final int addStruct(Struct struct, int length) throws MPIException
{
struct.commit();
return addField(struct, struct.extent, length);
}
/**
* Adds a field of the specified data type.
* @param type Data type.
* @return Offset of the new field.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final int addData(Datatype type) throws MPIException
{
return addData(type, 1);
}
/**
* Adds an array of the specified data type.
* @param type Data type.
* @param length Length of the array.
* @return Offset of the new field.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
public final int addData(Datatype type, int length) throws MPIException
{
return addField(type, type.getExtent() * type.baseSize, length);
}
private boolean validType(int fieldOffset, int index, Datatype type)
{
int i = Arrays.binarySearch(offsets, fieldOffset);
return index >= 0 && index < lengths[i] && type == types[i];
}
private static class Field
{
private Object type;
private int offset, length;
private Field(Object type, int offset, int length)
{
this.type = type;
this.offset = offset;
this.length = length;
}
} // Field
/**
* Base class for reading/writing data in a struct stored in a byte buffer.
*/
public abstract class Data
{
private ByteBuffer buffer;
private int offset;
/**
* Gets the buffer where this struct data is stored.
* <p>The buffer can be used in {@code send}/{@code recv} operations.
* @return Buffer where the struct data is stored.
*/
public final ByteBuffer getBuffer()
{
return offset == 0 ? buffer : MPI.slice(buffer, offset);
}
/**
* Gets the byte value of a field.
* @param field Offset of the field.
* @return Byte value.
*/
protected final byte getByte(int field)
{
assert validType(field, 0, MPI.BYTE) : typeMismatch;
return buffer.get(offset + field);
}
/**
* Gets the byte value at the specified position of a byte array.
* @param field Offset of the byte array.
* @param index Index of the byte in the array.
* @return Byte value.
*/
protected final byte getByte(int field, int index)
{
assert validType(field, index, MPI.BYTE) : typeMismatch;
return buffer.get(offset + field + index);
}
/**
* Puts a byte value in a field.
* @param field Offset of the field.
* @param v Byte value.
*/
protected final void putByte(int field, byte v)
{
assert validType(field, 0, MPI.BYTE) : typeMismatch;
buffer.put(offset + field, v);
}
/**
* Puts a byte value at the specified position of a byte array.
* @param field Offset of the byte array.
* @param index Index of the byte in the array.
* @param v Byte value.
*/
protected final void putByte(int field, int index, byte v)
{
assert validType(field, index, MPI.BYTE) : typeMismatch;
buffer.put(offset + field + index, v);
}
/**
* Gets the char value of a field.
* @param field Offset of the field.
* @return Char value.
*/
protected final char getChar(int field)
{
assert validType(field, 0, MPI.CHAR) : typeMismatch;
return buffer.getChar(offset + field);
}
/**
* Gets the char value at the specified position of a char array.
* @param field Offset of the char array.
* @param index Index of the char in the array.
* @return Char value.
*/
protected final char getChar(int field, int index)
{
assert validType(field, index, MPI.CHAR) : typeMismatch;
return buffer.getChar(offset + field + index * 2);
}
/**
* Puts a char value in a field.
* @param field Offset of the field.
* @param v Char value.
*/
protected final void putChar(int field, char v)
{
assert validType(field, 0, MPI.CHAR) : typeMismatch;
buffer.putChar(offset + field, v);
}
/**
* Puts a char value at the specified position of a char array.
* @param field Offset of the char array.
* @param index Index of the char in the array.
* @param v Char value.
*/
protected final void putChar(int field, int index, char v)
{
assert validType(field, index, MPI.CHAR) : typeMismatch;
buffer.putChar(offset + field + index * 2, v);
}
/**
* Gets the short value of a field.
* @param field Offset of the field.
* @return Short value.
*/
protected final short getShort(int field)
{
assert validType(field, 0, MPI.SHORT) : typeMismatch;
return buffer.getShort(offset + field);
}
/**
* Gets the short value at the specified position of a short array.
* @param field Offset of the short array.
* @param index Index of the short in the array.
* @return Short value.
*/
protected final short getShort(int field, int index)
{
assert validType(field, index, MPI.SHORT) : typeMismatch;
return buffer.getShort(offset + field + index * 2);
}
/**
* Puts a short value in a field.
* @param field Offset of the field.
* @param v Short value.
*/
protected final void putShort(int field, short v)
{
assert validType(field, 0, MPI.SHORT) : typeMismatch;
buffer.putShort(offset + field, v);
}
/**
* Puts a short value at the specified position of a short array.
* @param field Offset of the short array.
* @param index Index of the short in the array.
* @param v Short value.
*/
protected final void putShort(int field, int index, short v)
{
assert validType(field, index, MPI.SHORT) : typeMismatch;
buffer.putShort(offset + field + index * 2, v);
}
/**
* Gets the int value of a field.
* @param field Offset of the field.
* @return Int value.
*/
protected final int getInt(int field)
{
assert validType(field, 0, MPI.INT) : typeMismatch;
return buffer.getInt(offset + field);
}
/**
* Gets the int value at the specified position of an int array.
* @param field Offset of the int array.
* @param index Index of the int in the array.
* @return Int value.
*/
protected final int getInt(int field, int index)
{
assert validType(field, index, MPI.INT) : typeMismatch;
return buffer.getInt(offset + field + index * 4);
}
/**
* Puts an int value in a field.
* @param field Offset of the field.
* @param v Int value.
*/
protected final void putInt(int field, int v)
{
assert validType(field, 0, MPI.INT) : typeMismatch;
buffer.putInt(offset + field, v);
}
/**
* Puts an int value at the specified position of an int array.
* @param field Offset of the int array.
* @param index Index of the int in the array.
* @param v Int value.
*/
protected final void putInt(int field, int index, int v)
{
assert validType(field, index, MPI.INT) : typeMismatch;
buffer.putInt(offset + field + index * 4, v);
}
/**
* Gets the long value of a field.
* @param field Offset of the field.
* @return Long value.
*/
protected final long getLong(int field)
{
assert validType(field, 0, MPI.LONG) : typeMismatch;
return buffer.getLong(offset + field);
}
/**
* Gets the long value at the specified position of a long array.
* @param field Offset of the long array.
* @param index Index of the long in the array.
* @return Long value.
*/
protected final long getLong(int field, int index)
{
assert validType(field, index, MPI.LONG) : typeMismatch;
return buffer.getLong(offset + field + index * 8);
}
/**
* Puts a long value in a field.
* @param field Offset of the field.
* @param v Long value.
*/
protected final void putLong(int field, long v)
{
assert validType(field, 0, MPI.LONG) : typeMismatch;
buffer.putLong(offset + field, v);
}
/**
* Puts a long value at the specified position of a long array.
* @param field Offset of the long array.
* @param index Index of the long in the array.
* @param v Long value.
*/
protected final void putLong(int field, int index, long v)
{
assert validType(field, index, MPI.LONG) : typeMismatch;
buffer.putLong(offset + field + index * 8, v);
}
/**
* Gets the float value of a field.
* @param field Offset of the field.
* @return Float value.
*/
protected final float getFloat(int field)
{
assert validType(field, 0, MPI.FLOAT) : typeMismatch;
return buffer.getFloat(offset + field);
}
/**
* Gets the float value at the specified position of a float array.
* @param field Offset of the float array.
* @param index Index of the float in the array.
* @return Float value.
*/
protected final float getFloat(int field, int index)
{
assert validType(field, index, MPI.FLOAT) : typeMismatch;
return buffer.getFloat(offset + field + index * 4);
}
/**
* Puts a float value in a field.
* @param field Offset of the field.
* @param v Float value.
*/
protected final void putFloat(int field, float v)
{
assert validType(field, 0, MPI.FLOAT) : typeMismatch;
buffer.putFloat(offset + field, v);
}
/**
* Puts a float value at the specified position of a float array.
* @param field Offset of the float array.
* @param index Index of the float in the array.
* @param v Float value.
*/
protected final void putFloat(int field, int index, float v)
{
assert validType(field, index, MPI.FLOAT) : typeMismatch;
buffer.putFloat(offset + field + index * 4, v);
}
/**
* Gets the double value of a field.
* @param field Offset of the field.
* @return Double value.
*/
protected final double getDouble(int field)
{
assert validType(field, 0, MPI.DOUBLE) : typeMismatch;
return buffer.getDouble(offset + field);
}
/**
* Gets the double value at the specified position of a double array.
* @param field Offset of the double array.
* @param index Index of the double in the array.
* @return Double value.
*/
protected final double getDouble(int field, int index)
{
assert validType(field, index, MPI.DOUBLE) : typeMismatch;
return buffer.getDouble(offset + field + index * 8);
}
/**
* Puts a double value in a field.
* @param field Offset of the field.
* @param v Double value.
*/
protected final void putDouble(int field, double v)
{
assert validType(field, 0, MPI.DOUBLE) : typeMismatch;
buffer.putDouble(offset + field, v);
}
/**
* Puts a double value at the specified position of a double array.
* @param field Offset of the double array.
* @param index Index of the double in the array.
* @param v Double value.
*/
protected final void putDouble(int field, int index, double v)
{
assert validType(field, index, MPI.DOUBLE) : typeMismatch;
buffer.putDouble(offset + field + index * 8, v);
}
@SuppressWarnings("javadoc")
/**
* Gets the struct data of a field.
* @param struct Struct type.
* @param field Offset of the field.
* @return Struct data.
*/
protected final <S extends Struct, D extends Struct.Data>
D getData(S struct, int field)
{
Struct s = (Struct)struct;
assert validType(field, 0, s.datatype) : typeMismatch;
return s.newData(buffer, offset + field);
}
@SuppressWarnings("javadoc")
/**
* Gets the struct data at the specified position of a struct array.
* @param struct Struct type.
* @param field Offset of the struct array.
* @param index Index of the struct in the array.
* @return Struct data.
*/
protected final <S extends Struct, D extends Struct.Data>
D getData(S struct, int field, int index)
{
Struct s = (Struct)struct;
assert validType(field, index, s.datatype) : typeMismatch;
return s.newData(buffer, offset + field + index * s.extent);
}
/**
* Gets the buffer of a field.
* <p>The buffer can be used in {@code send}/{@code recv} operations.
* @param type Data type of the buffer.
* @param field Offset of the field.
* @return Buffer object.
*/
protected final ByteBuffer getBuffer(Datatype type, int field)
{
assert validType(field, 0, type) : typeMismatch;
int position = offset + field;
return position == 0 ? buffer : MPI.slice(buffer, position);
}
/**
* Gets the buffer data at the specified position of a buffer array.
* <p>The buffer can be used in {@code send}/{@code recv} operations.
* @param type Data type of the buffer.
* @param field Offset of the buffer array.
* @param index Index of the buffer in the array.
* @return Buffer object.
* @throws MPIException Signals that an MPI error of some sort has occurred.
*/
protected final ByteBuffer getBuffer(Datatype type, int field, int index)
throws MPIException
{
assert validType(field, index, type) : typeMismatch;
int extent = type.getExtent() * type.baseSize,
position = offset + field + index * extent;
return position == 0 ? buffer : MPI.slice(buffer, position);
}
} // Data
} // Struct