[Home] DMelt member access . Java source code: edu.rit.mp.ObjectBuf
//******************************************************************************
//
// File: ObjectBuf.java
// Package: edu.rit.mp
// Unit: Class edu.rit.mp.ObjectBuf
//
// This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************
package edu.rit.mp;
import edu.rit.mp.buf.EmptyObjectBuf;
import edu.rit.mp.buf.ObjectArrayBuf;
import edu.rit.mp.buf.ObjectArrayBuf_1;
import edu.rit.mp.buf.ObjectItemBuf;
import edu.rit.mp.buf.ObjectMatrixBuf;
import edu.rit.mp.buf.ObjectMatrixBuf_1;
import edu.rit.mp.buf.SharedObjectBuf;
import edu.rit.mp.buf.SharedObjectArrayBuf;
import edu.rit.mp.buf.SharedObjectArrayBuf_1;
import edu.rit.pj.reduction.ObjectOp;
import edu.rit.pj.reduction.Op;
import edu.rit.pj.reduction.SharedObject;
import edu.rit.pj.reduction.SharedObjectArray;
import edu.rit.util.Arrays;
import edu.rit.util.Range;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
/**
* Class ObjectBuf is the abstract base class for a buffer of object items
* sent or received using the Message Protocol (MP). In a message, an object
* item is represented as a sequence of bytes using Java Object Serialization.
*
* A buffer may be used to send one or more messages at the same time in
* multiple threads. If a buffer is being used to send a message or messages,
* the buffer must not be used to receive a message at the same time.
*
* A buffer may be used to receive one message at a time. If a buffer is being
* used to receive a message, the buffer must not be used to receive another
* message in a different thread, and the buffer must not be used to send a
* message or messages.
*
* A buffer is a conduit for retrieving and storing data in some underlying data
* structure. If the underlying data structure is multiple thread safe, then one
* thread can be retrieving or storing data via the buffer at the same time as
* other threads are accessing the data structure. If the underlying data
* structure is not multiple thread safe, then other threads must not access the
* data structure while one thread is retrieving or storing data via the buffer.
*
* To create an ObjectBuf, call one of the following static factory methods:
*
* emptyBuffer()
* buffer()
* buffer (T)
* buffer (T[])
* sliceBuffer (T[], Range)
* sliceBuffers (T[], Range[])
* objectBuffer (T[])
* buffer (T[][])
* rowSliceBuffer (T[][], Range)
* rowSliceBuffers (T[][], Range[])
* colSliceBuffer (T[][], Range)
* colSliceBuffers (T[][], Range[])
* patchBuffer (T[][], Range, Range)
* patchBuffers (T[][], Range[], Range[])
* objectBuffer (T[][])
* buffer (SharedObject<T>)
* buffer (SharedObjectArray<T>)
* sliceBuffer (SharedObjectArray<T>, Range)
* sliceBuffers (SharedObjectArray<T>, Range[])
*
*
* There are two ways to create a buffer for an array of objects (type
* T[] ):
*
*
* With the buffer(T[]) , sliceBuffer(T[],Range) , and
* sliceBuffers(T[],Range[]) methods. These methods create a buffer
* that sends and receives the array elements as multiple separate objects of
* type T . The receiver must allocate an array of the proper dimension
* to receive the incoming objects and must create a buffer that receives the
* array elements as separate objects.
*
* With the objectBuffer(T[]) method. This method creates a buffer that
* sends and receives the entire array as one object of type T[] . The
* receiver must also create a buffer that receives the entire array as one
* object; the buffer's item field is automatically set to an array of
* the proper dimension.
*
*
* There are two ways to create a buffer for a matrix of objects (type
* T[][] ):
*
*
* With the buffer(T[][]) , rowSliceBuffer(T[][],Range) ,
* rowSliceBuffers(T[][],Range[]) ,
* colSliceBuffer(T[][],Range) ,
* colSliceBuffers(T[][],Range[]) , patchBuffer(T[][],Range) ,
* and patchBuffers(T[][],Range[]) methods. These methods create a
* buffer that sends and receives the matrix elements as multiple separate
* objects of type T . The receiver must allocate a matrix of the proper
* dimensions to receive the incoming objects and must create a buffer that
* receives the matrix elements as separate objects.
*
* With the objectBuffer(T[][]) method. This method creates a buffer
* that sends and receives the entire matrix as one object of type
* T[][] . The receiver must also create a buffer that receives the
* matrix as one object; the buffer's item field is automatically set
* to a matrix of the proper dimensions.
*
*
* Important Note: An ObjectBuf uses the protected field
* mySerializedItems to store the serialized representation of the
* objects in the buffer. If the buffer is used to receive a message, the
* serialized representation of the received objects is cached in
* mySerializedItems . If the buffer is used to send a message and
* mySerializedItems is empty, the objects in the buffer are
* serialized, the serialized representation is cached in
* mySerializedItems , and the serialized representation is sent in the
* message. If the buffer is used to send a message and
* mySerializedItems is not empty, the objects in the buffer are
* not serialized; rather, the cached serialized representation is sent.
* This is done to avoid re-serializing the objects if the buffer is used to
* send copies of a message to multiple destinations, or if the buffer is used
* to receive and then immediately send a message. However, if the state of any
* object in the buffer changes, the buffer's reset() method must be
* called; this tells the buffer to discard the cached serialized representation
* and re-serialize the objects in the buffer.
*
* @param Data type of the objects in the buffer.
*
* @author Alan Kaminsky
* @version 03-Jul-2008
*/
public abstract class ObjectBuf
extends Buf
{
// Hidden data members.
/**
* Byte array containing this buffer's object items in serialized form. If
* null, the object items need to be serialized.
*/
protected byte[] mySerializedItems;
// Hidden constructors.
/**
* Construct a new object buffer.
*
* @param theLength Number of items.
*
* @exception IllegalArgumentException
* (unchecked exception) Thrown if theLength < 0.
*/
protected ObjectBuf
(int theLength)
{
super (Constants.TYPE_OBJECT, theLength);
}
// Exported operations.
/**
* Create an empty buffer. The buffer's length is 0. The buffer's item type
* is Object.
*
* @return Empty buffer.
*/
public static ObjectBuf emptyBuffer()
{
return new EmptyObjectBuf();
}
/**
* Create a buffer for an object item. The item is stored in the
* item field of the buffer.
*
* @param Data type of the objects in the buffer.
*
* @return Buffer.
*/
public static ObjectItemBuf buffer()
{
return new ObjectItemBuf();
}
/**
* Create a buffer for an object item with the given initial value. The
* item is stored in the item field of the buffer.
*
* @param Data type of the objects in the buffer.
* @param item Initial value of the item field.
*
* @return Buffer.
*/
public static ObjectItemBuf buffer
(T item)
{
return new ObjectItemBuf (item);
}
/**
* Create a buffer for the entire given object array. The returned buffer
* encompasses all the elements in theArray . The array elements are
* sent and received as multiple separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null.
*/
public static ObjectBuf buffer
(T[] theArray)
{
if (theArray == null)
{
throw new NullPointerException
("ObjectBuf.buffer(): theArray is null");
}
int nr = Arrays.length (theArray);
return new ObjectArrayBuf_1 (theArray, new Range (0, nr-1));
}
/**
* Create a buffer for one slice of the given object array. The returned
* buffer encompasses theRange of elements in theArray .
* The range's stride may be 1 or greater than 1. The array elements are
* sent and received as multiple separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
* @param theRange Range of elements to include.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null or
* theRange is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theArray does not include
* all the indexes in theRange .
*/
public static ObjectBuf sliceBuffer
(T[] theArray,
Range theRange)
{
if (theArray == null)
{
throw new NullPointerException
("ObjectBuf.sliceBuffer(): theArray is null");
}
int nr = Arrays.length (theArray);
if (0 > theRange.lb() || theRange.ub() >= nr)
{
throw new IndexOutOfBoundsException
("ObjectBuf.sliceBuffer(): theArray index range = 0.." +
(nr-1) + ", theRange = " + theRange);
}
if (theRange.stride() == 1)
{
return new ObjectArrayBuf_1 (theArray, theRange);
}
else
{
return new ObjectArrayBuf (theArray, theRange);
}
}
/**
* Create an array of buffers for multiple slices of the given object
* array. The returned buffer array has the same length as
* theRanges . Each element [i ] of the returned buffer array
* encompasses the elements of theArray specified by
* theRanges[i] . Each range's stride may be 1 or greater than 1.
* The array elements are sent and received as multiple separate objects of
* type T .
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
* @param theRanges Array of ranges of elements to include.
*
* @return Array of buffers.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null or
* theRanges or any element thereof is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theArray 's allocation does
* not include any element of theRanges .
*/
public static ObjectBuf[] sliceBuffers
(T[] theArray,
Range[] theRanges)
{
int n = theRanges.length;
ObjectBuf[] result = (ObjectBuf[]) new ObjectBuf [n];
for (int i = 0; i < n; ++ i)
{
result[i] = sliceBuffer (theArray, theRanges[i]);
}
return result;
}
/**
* Create a buffer for the entire given object array. The returned buffer
* encompasses all the elements in theArray . The array is sent and
* received as a single object of type T[] .
*
* @param Data type of the objects in the buffer.
* @param theArray Array. May be null.
*
* @return Buffer.
*/
public static ObjectItemBuf objectBuffer
(T[] theArray)
{
return new ObjectItemBuf (theArray);
}
/**
* Create a buffer for the entire given object matrix. The returned
* buffer encompasses all the rows and all the columns in
* theMatrix . The matrix elements are sent and received as multiple
* separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null.
*/
public static ObjectBuf buffer
(T[][] theMatrix)
{
if (theMatrix == null)
{
throw new NullPointerException
("ObjectBuf.buffer(): theMatrix is null");
}
int nr = Arrays.rowLength (theMatrix);
int nc = Arrays.colLength (theMatrix, 0);
return new ObjectMatrixBuf_1
(theMatrix, new Range (0, nr-1), new Range (0, nc-1));
}
/**
* Create a buffer for one row slice of the given object matrix. The
* returned buffer encompasses theRowRange of rows, and all the
* columns, in theMatrix . The range's stride may be 1 or greater
* than 1. The matrix elements are sent and received as multiple separate
* objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theRowRange Range of rows to include.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null or
* theRowRange is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include theRowRange .
*/
public static ObjectBuf rowSliceBuffer
(T[][] theMatrix,
Range theRowRange)
{
if (theMatrix == null)
{
throw new NullPointerException
("ObjectBuf.rowSliceBuffer(): theMatrix is null");
}
int nr = Arrays.rowLength (theMatrix);
if (0 > theRowRange.lb() || theRowRange.ub() >= nr)
{
throw new IndexOutOfBoundsException
("ObjectBuf.rowSliceBuffer(): theMatrix row index range = 0.." +
(nr-1) + ", theRowRange = " + theRowRange);
}
int nc = Arrays.colLength (theMatrix, theRowRange.lb());
if (theRowRange.stride() == 1)
{
return new ObjectMatrixBuf_1
(theMatrix, theRowRange, new Range (0, nc-1));
}
else
{
return new ObjectMatrixBuf
(theMatrix, theRowRange, new Range (0, nc-1));
}
}
/**
* Create an array of buffers for multiple row slices of the given object
* matrix. The returned buffer array has the same length as
* theRowRanges . Each element [i ] of the returned buffer
* array encompasses the rows of theMatrix specified by
* theRowRanges[i] and all the columns of theMatrix . Each
* range's stride may be 1 or greater than 1. The matrix elements are sent
* and received as multiple separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theRowRanges Array of ranges of rows to include.
*
* @return Array of buffers.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null or
* theRowRanges or any element thereof is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include any element of theRowRanges .
*/
public static ObjectBuf[] rowSliceBuffers
(T[][] theMatrix,
Range[] theRowRanges)
{
int n = theRowRanges.length;
ObjectBuf[] result = (ObjectBuf[]) new ObjectBuf [n];
for (int i = 0; i < n; ++ i)
{
result[i] = rowSliceBuffer (theMatrix, theRowRanges[i]);
}
return result;
}
/**
* Create a buffer for one column slice of the given object matrix. The
* returned buffer encompasses all the rows, and theColRange of
* columns, in theMatrix . The range's stride may be 1 or greater
* than 1. The matrix elements are sent and received as multiple separate
* objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theColRange Range of columns to include.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null or
* theColRange is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include theColRange .
*/
public static ObjectBuf colSliceBuffer
(T[][] theMatrix,
Range theColRange)
{
if (theMatrix == null)
{
throw new NullPointerException
("ObjectBuf.colSliceBuffer(): theMatrix is null");
}
int nr = Arrays.rowLength (theMatrix);
int nc = Arrays.colLength (theMatrix, 0);
if (0 > theColRange.lb() || theColRange.ub() >= nc)
{
throw new IndexOutOfBoundsException
("ObjectBuf.colSliceBuffer(): theMatrix column index range = 0.."
+ (nc-1) + ", theColRange = " + theColRange);
}
if (theColRange.stride() == 1)
{
return new ObjectMatrixBuf_1
(theMatrix, new Range (0, nr-1), theColRange);
}
else
{
return new ObjectMatrixBuf
(theMatrix, new Range (0, nr-1), theColRange);
}
}
/**
* Create an array of buffers for multiple column slices of the given
* object matrix. The returned buffer array has the same length as
* theColRanges . Each element [i ] of the returned buffer
* array encompasses all the rows of theMatrix and the columns of
* theMatrix specified by theColRanges[i] . Each range's
* stride may be 1 or greater than 1. The matrix elements are sent and
* received as multiple separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theColRanges Array of ranges of columns to include.
*
* @return Array of buffers.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null or
* theColRanges or any element thereof is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include any element of theColRanges .
*/
public static ObjectBuf[] colSliceBuffers
(T[][] theMatrix,
Range[] theColRanges)
{
int n = theColRanges.length;
ObjectBuf[] result = (ObjectBuf[]) new ObjectBuf [n];
for (int i = 0; i < n; ++ i)
{
result[i] = colSliceBuffer (theMatrix, theColRanges[i]);
}
return result;
}
/**
* Create a buffer for one patch of the given object matrix. The returned
* buffer encompasses theRowRange of rows, and theColRange
* of columns, in theMatrix . Each range's stride may be 1 or
* greater than 1. The matrix elements are sent and received as multiple
* separate objects of type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theRowRange Range of rows to include.
* @param theColRange Range of columns to include.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null,
* theRowRange is null, or theColRange is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include theRowRange and theColRange .
*/
public static ObjectBuf patchBuffer
(T[][] theMatrix,
Range theRowRange,
Range theColRange)
{
if (theMatrix == null)
{
throw new NullPointerException
("ObjectBuf.patchBuffer(): theMatrix is null");
}
int nr = Arrays.rowLength (theMatrix);
if (0 > theRowRange.lb() || theRowRange.ub() >= nr)
{
throw new IndexOutOfBoundsException
("ObjectBuf.patchBuffer(): theMatrix row index range = 0.."
+ (nr-1) + ", theRowRange = " + theRowRange);
}
int nc = Arrays.colLength (theMatrix, theRowRange.lb());
if (0 > theColRange.lb() || theColRange.ub() >= nc)
{
throw new IndexOutOfBoundsException
("ObjectBuf.patchBuffer(): theMatrix column index range = 0.."
+ (nc-1) + ", theColRange = " + theColRange);
}
if (theRowRange.stride() == 1 && theColRange.stride() == 1)
{
return new ObjectMatrixBuf_1 (theMatrix, theRowRange, theColRange);
}
else
{
return new ObjectMatrixBuf (theMatrix, theRowRange, theColRange);
}
}
/**
* Create an array of buffers for multiple patches of the given object
* matrix. The length of the returned buffer array is equal to the length of
* theRowRanges times the length of theColRanges . Each
* element of the returned buffer array encompasses the rows given in one
* element of theRowRanges array, and the columns given in one
* element of theColRanges array, in all possible combinations, of
* theMatrix . Each range's stride may be 1 or greater than 1. The
* matrix elements are sent and received as multiple separate objects of
* type T .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix.
* @param theRowRanges Array of ranges of rows to include.
* @param theColRanges Array of ranges of columns to include.
*
* @return Array of buffers.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theMatrix is null,
* theRowRanges or any element thereof is null, or
* theColRanges or any element thereof is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theMatrix 's allocation does
* not include any element of theRowRanges or
* theColRanges .
*/
public static ObjectBuf[] patchBuffers
(T[][] theMatrix,
Range[] theRowRanges,
Range[] theColRanges)
{
int m = theRowRanges.length;
int n = theColRanges.length;
ObjectBuf[] result = (ObjectBuf[]) new ObjectBuf [m*n];
int k = 0;
for (int i = 0; i < m; ++ i)
{
Range rowrange = theRowRanges[i];
for (int j = 0; j < n; ++ j)
{
result[k++] =
patchBuffer (theMatrix, rowrange, theColRanges[j]);
}
}
return result;
}
/**
* Create a buffer for the entire given object matrix. The returned buffer
* encompasses all the rows and all the columns in theMatrix . The
* matrix is sent and received as a single object of type T[][] .
*
* @param Data type of the objects in the buffer.
* @param theMatrix Matrix. May be null.
*
* @return Buffer.
*/
public static ObjectItemBuf objectBuffer
(T[][] theMatrix)
{
return new ObjectItemBuf (theMatrix);
}
/**
* Create a buffer for a shared object item. The item is wrapped in an
* instance of class {@linkplain edu.rit.pj.reduction.SharedObject
* SharedObject}. Use the methods of the SharedObject object to access
* the actual item.
*
* @param Data type of the objects in the buffer.
* @param item SharedObject object that wraps the item.
*
* @exception NullPointerException
* (unchecked exception) Thrown if item is null.
*/
public static ObjectBuf buffer
(SharedObject item)
{
if (item == null)
{
throw new NullPointerException
("ObjectBuf.buffer(): item is null");
}
return new SharedObjectBuf (item);
}
/**
* Create a buffer for the entire given shared object array. The returned
* buffer encompasses all the elements in theArray .
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null.
*/
public static ObjectBuf buffer
(SharedObjectArray theArray)
{
if (theArray == null)
{
throw new NullPointerException
("ObjectBuf.buffer(): theArray is null");
}
int nr = theArray.length();
return new SharedObjectArrayBuf_1 (theArray, new Range (0, nr-1));
}
/**
* Create a buffer for one slice of the given shared object array. The
* returned buffer encompasses theRange of elements in
* theArray . The range's stride may be 1 or greater than 1.
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
* @param theRange Range of elements to include.
*
* @return Buffer.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null or
* theRange is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theArray does not include
* all the indexes in theRange .
*/
public static ObjectBuf sliceBuffer
(SharedObjectArray theArray,
Range theRange)
{
if (theArray == null)
{
throw new NullPointerException
("ObjectBuf.sliceBuffer(): theArray is null");
}
int nr = theArray.length();
if (0 > theRange.lb() || theRange.ub() >= nr)
{
throw new IndexOutOfBoundsException
("ObjectBuf.sliceBuffer(): theArray index range = 0.."
+ (nr-1) + ", theRange = " + theRange);
}
if (theRange.stride() == 1)
{
return new SharedObjectArrayBuf_1 (theArray, theRange);
}
else
{
return new SharedObjectArrayBuf (theArray, theRange);
}
}
/**
* Create an array of buffers for multiple slices of the given shared
* object array. The returned buffer array has the same length as
* theRanges . Each element [i ] of the returned buffer array
* encompasses the elements of theArray specified by
* theRanges[i] . Each range's stride may be 1 or greater than 1.
*
* @param Data type of the objects in the buffer.
* @param theArray Array.
* @param theRanges Array of ranges of elements to include.
*
* @return Array of buffers.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null or
* theRanges or any element thereof is null.
* @exception IndexOutOfBoundsException
* (unchecked exception) Thrown if theArray 's allocation does
* not include any element of theRanges .
*/
public static ObjectBuf[] sliceBuffers
(SharedObjectArray theArray,
Range[] theRanges)
{
int n = theRanges.length;
ObjectBuf[] result = (ObjectBuf[]) new ObjectBuf [n];
for (int i = 0; i < n; ++ i)
{
result[i] = sliceBuffer (theArray, theRanges[i]);
}
return result;
}
/**
* Obtain the given item from this buffer.
*
* The get() method must not block the calling thread; if it does,
* all message I/O in MP will be blocked.
*
* @param i Item index in the range 0 .. length() -1.
*
* @return Item at index i .
*/
public abstract T get
(int i);
/**
* Store the given item in this buffer.
*
* The put() method must not block the calling thread; if it does,
* all message I/O in MP will be blocked.
*
* @param i Item index in the range 0 .. length() -1.
* @param item Item to be stored at index i .
*/
public abstract void put
(int i,
T item);
/**
* Copy items from the given buffer to this buffer. The number of items
* copied is this buffer's length or theSrc 's length, whichever is
* smaller. If theSrc is this buffer, the copy() method
* does nothing.
*
* The default implementation of the copy() method calls the
* defaultCopy() method. A subclass can override the
* copy() method to use a more efficient algorithm.
*
* The default implementation of the copy() method also calls the
* reset() method.
*
* @param theSrc Source of items to copy into this buffer.
*
* @exception ClassCastException
* (unchecked exception) Thrown if theSrc 's item data type is
* not the same as this buffer's item data type.
*/
public void copy
(Buf theSrc)
{
if (theSrc != this)
{
defaultCopy ((ObjectBuf) theSrc, this);
reset();
}
}
/**
* Fill this buffer with the given item. The item is assigned to
* each element in this buffer.
*
* The item must be an instance of class T or a subclass thereof.
* The item may be null. Note that since item is
* assigned to every buffer element, every buffer element ends up
* referring to the same item .
*
* The fill() method calls the reset() method.
*
* @param item Item.
*
* @exception ClassCastException
* (unchecked exception) Thrown if the item 's data type is not
* the same as this buffer's item data type.
*/
public void fill
(Object item)
{
T value = (T) item;
for (int i = 0; i < myLength; ++ i)
{
put (i, value);
}
reset();
}
/**
* Create a temporary buffer with the same type of items and the same length
* as this buffer. The new buffer items are stored in a newly created array,
* separate from the storage for this buffer's items.
*/
public Buf getTemporaryBuf()
{
return buffer ((T[]) new Object [myLength]);
}
/**
* Reset this buffer. Call reset() if the state of any object in
* this buffer changes.
*/
public void reset()
{
mySerializedItems = null;
}
// Hidden operations.
/**
* Called by the I/O thread before sending message items using this buffer.
*
* @exception IOException
* Thrown if an I/O error occurred.
*/
void preSend()
throws IOException
{
if (mySerializedItems == null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream (baos);
oos.writeInt (myLength);
for (int i = 0; i < myLength; ++ i)
{
oos.writeObject (get (i));
}
oos.close();
mySerializedItems = baos.toByteArray();
myMessageLength = mySerializedItems.length;
}
}
/**
* Send as many items as possible from this buffer to the given byte
* buffer.
*
* The sendItems() method must not block the calling thread; if it
* does, all message I/O in MP will be blocked.
*
* @param i Index of first item to send, in the range 0 ..
* length -1.
* @param buffer Byte buffer.
*
* @return Number of items sent.
*/
protected int sendItems
(int i,
ByteBuffer buffer)
{
int len = Math.min (myMessageLength - i, buffer.remaining());
buffer.put (mySerializedItems, i, len);
return len;
}
/**
* Called by the I/O thread before receiving message items using this
* buffer.
*
* @param theReadLength Actual number of items in message.
*/
void preReceive
(int theReadLength)
{
mySerializedItems = new byte [theReadLength];
myMessageLength = theReadLength;
}
/**
* Receive as many items as possible from the given byte buffer to this
* buffer.
*
* The receiveItems() method must not block the calling thread; if
* it does, all message I/O in MP will be blocked.
*
* @param i Index of first item to receive, in the range 0 ..
* length -1.
* @param num Maximum number of items to receive.
* @param buffer Byte buffer.
*
* @return Number of items received.
*/
protected int receiveItems
(int i,
int num,
ByteBuffer buffer)
{
int len = num;
len = Math.min (len, myMessageLength - i);
len = Math.min (len, buffer.remaining());
buffer.get (mySerializedItems, i, len);
return len;
}
/**
* Skip as many items as possible from the given byte buffer.
*
* @param num Number of items to skip.
* @param buffer Buffer.
*
* @return Number of items actually skipped.
*/
int skipItems
(int num,
ByteBuffer buffer)
{
int n = Math.min (num, buffer.remaining());
buffer.position (buffer.position() + n);
return n;
}
/**
* Called by the I/O thread after receiving message items using this
* buffer.
*
* @param theStatus Status object that will be returned for the
* message; its contents may be altered if
* necessary.
* @param theClassLoader Alternate class loader to be used when receiving
* objects, or null.
*
* @exception IOException
* Thrown if an I/O error occurred.
*/
void postReceive
(Status theStatus,
ClassLoader theClassLoader)
throws IOException
{
try
{
byte[] savedSerializedItems = mySerializedItems;
ByteArrayInputStream bais =
new ByteArrayInputStream (mySerializedItems);
ObjectInputStream ois =
new MPObjectInputStream (bais, theClassLoader);
int nmsg = ois.readInt();
int n = Math.min (myLength, nmsg);
for (int i = 0; i < n; ++ i)
{
put (i, (T) ois.readObject());
}
ois.close();
theStatus.length = nmsg;
mySerializedItems = savedSerializedItems;
}
catch (ClassNotFoundException exc)
{
IOException exc2 =
new IOException ("ObjectBuf.postReceive(): Class not found");
exc2.initCause (exc);
throw exc2;
}
catch (ClassCastException exc)
{
IOException exc2 =
new IOException ("ObjectBuf.postReceive(): Wrong type");
exc2.initCause (exc);
throw exc2;
}
}
/**
* Copy items from the given source buffer to the given destination buffer.
* The number of items copied is theSrc 's length or
* theDst 's length, whichever is smaller. Each item is copied
* individually using the get() and put() methods. It is
* assumed that theSrc is not the same as theDst .
*
* @param Data type of the objects in the buffer.
* @param theSrc Source of items to copy.
* @param theDst Destination of items to copy.
*/
protected static void defaultCopy
(ObjectBuf theSrc,
ObjectBuf theDst)
{
int n = Math.min (theSrc.myLength, theDst.myLength);
for (int i = 0; i < n; ++ i)
{
theDst.put (i, theSrc.get (i));
}
}
}
Ads help maintain this website.