ModelState.java

package edu.udel.cis.vsl.tass.state.impl;

import edu.udel.cis.vsl.tass.dynamic.IF.value.MessageIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ValueIF;
import edu.udel.cis.vsl.tass.model.IF.location.LocationIF;
import edu.udel.cis.vsl.tass.morph.MorphicObject;
import edu.udel.cis.vsl.tass.morph.MorphicArray;
import edu.udel.cis.vsl.tass.morph.MorphicArrayFactory;
import edu.udel.cis.vsl.tass.morph.Morphic;
import edu.udel.cis.vsl.tass.morph.MorphicVector;
import edu.udel.cis.vsl.tass.morph.MorphicVectorFactory;
import edu.udel.cis.vsl.tass.state.IF.ModelStateIF;
import edu.udel.cis.vsl.tass.state.IF.ProcessStateIF;

/**
 * Represents the state of a single MPI model. Immutable. All fields (other than
 * ID) are fixed after creation. This facilitates sharing among State objects.
 * 
 * @author siegel
 * 
 */
public class ModelState extends MorphicObject implements ModelStateIF {

	private MorphicArray<ProcessStateIF> processStates;

	/**
	 * The values of shared variables and process-global variables. These
	 * variables are indexed 0,1,.... The index of such a variable can be
	 * obtained by method index() in VariableIF.
	 */
	private MorphicArray<ValueIF> sharedValues;

	/**
	 * The buffered messages, i.e., messages which have been sent but not yet
	 * received. Order: first by source, then by destination, then by temporal
	 * order. If tag matching cannot be determined absolutely, throw exception
	 */
	private MorphicVector<MessageIF> buffer;

	private int instanceId;

	private int canonicalId = -1;

	public ModelState(int instanceId,
			MorphicArray<ProcessStateIF> processStates,
			MorphicArray<ValueIF> sharedValues, MorphicVector<MessageIF> buffer) {
		assert processStates != null;
		assert sharedValues != null;
		assert buffer != null;
		this.instanceId = instanceId;
		for (ProcessStateIF processState : processStates)
			assert processState != null;
		this.processStates = processStates;
		this.sharedValues = sharedValues;
		this.buffer = buffer;
	}

	public int canonicalId() {
		return canonicalId;
	}

	public int instanceId() {
		return instanceId;
	}

	void setCanonicalId(int id) {
		canonicalId = id;
	}

	public LocationIF[] locations() {
		int numProcs = processStates.length();
		LocationIF[] locations = new LocationIF[numProcs];

		for (int i = 0; i < numProcs; i++) {
			ProcessStateIF processState = processStates.get(i);

			if (processState.stackSize() == 0)
				locations[i] = null;
			else
				locations[i] = processState.peekStack().location();
		}
		return locations;
	}

	@Override
	public MorphicArray<ProcessStateIF> processStates() {
		return processStates;
	}

	@Override
	public ProcessStateIF processState(int pid) {
		return processStates.get(pid);
	}

	public void setProcessStates(MorphicArray<ProcessStateIF> processStates) {
		assert !isCommitted();
		this.processStates = processStates;
	}

	public void setProcessState(int index, ProcessStateIF processState) {
		processStates.set(index, processState);
	}

	@Override
	public MorphicArray<ValueIF> sharedValues() {
		return sharedValues;
	}

	@Override
	public ValueIF sharedValue(int i) {
		return sharedValues.get(i);
	}

	public void setSharedValues(MorphicArray<ValueIF> values) {
		assert !isCommitted();
		this.sharedValues = values;
	}

	public void setSharedValue(int index, ValueIF value) {
		sharedValues.set(index, value);
	}

	@Override
	public MorphicVector<MessageIF> buffer() {
		return buffer;
	}

	@Override
	public MessageIF message(int i) {
		return buffer.get(i);
	}

	public void setBuffer(MorphicVector<MessageIF> buffer) {
		assert !isCommitted();
		this.buffer = buffer;
	}

	public void setMessage(int index, MessageIF message) {
		buffer.set(index, message);
	}

	@Override
	protected boolean computeEquals(Morphic component) {
		if (component instanceof ModelState) {
			ModelState that = (ModelState) component;

			return sharedValues.equals(that.sharedValues)
					&& processStates.equals(that.processStates)
					&& buffer.equals(that.buffer);
		}
		return false;
	}

	@Override
	protected int computeHashCode() {
		return processStates.hashCode() + sharedValues.hashCode()
				+ buffer.hashCode();
	}

	@Override
	protected void commitChildren() {
		sharedValues.commit();
		processStates.commit();
		buffer.commit();
	}

	void canonicalizeChildren(MorphicArrayFactory<ValueIF> sharedValueFactory,
			MorphicArrayFactory<ProcessStateIF> processStateArrayFactory,
			MorphicVectorFactory<MessageIF> bufferFactory) {
		processStates = processStateArrayFactory.canonic(processStates);
		sharedValues = sharedValueFactory.canonic(sharedValues);
		buffer = bufferFactory.canonic(buffer);
	}

	@Override
	public String descriptor() {
		if (!isCommitted())
			return "";
		if (!isCanonic()) {
			return "(committed)";
		}
		return "(canonicID = " + canonicalId() + ")";
	}
}