/*
* Copyright (c) 2006 Thomas Weise
*
* E-Mail : tweise@gmx.de
* Creation Date : 2006-07-06 15:21:01
* Original Filename: org.dgpf.gp.netvm.NetVM.java
* Version : 1.0.0
* Last modification: 2006-07-06
* by: Thomas Weise
*
* License : GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
* You should have received a copy of this license along
* with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA or download the license under
* http://www.gnu.org/copyleft/lesser.html.
*
* Warranty : This software is provided "as is" without any
* warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose.
* See the Gnu Lesser General Public License for more
* details.
*/
package org.dgpf.gp.netvm.base;
import org.dgpf.gp.vm.base.Program;
import org.dgpf.gp.vm.base.VM;
import org.dgpf.gp.vm.base.VMMemory;
/**
* The network enabled version of a virtual machine.
*
* @author Thomas Weise
*/
public class NetVM extends VM
implements INetVMInformation
{
/**
* The serial version uid.
*/
private static final long serialVersionUID = 1;
/**
* The count of messages sent.
* @see #get_successful_sends()
*/
private int m_successful_sends ;
/**
* The count of messages failed to be set.
* @see #get_failed_sends()
*/
private long m_failed_sends ;
/**
* The count of send operations not performed because the send buffer was
* empty.
* @see #get_empty_sends()
*/
private long m_empty_sends ;
/**
* true
if all vms but this have stopped executing.
*/
boolean m_last ;
/**
* The number of messages successfully delifered to this node.
*/
private long m_delivered ;
/**
* The number of messages lost at the receive method.
*/
private long m_lost_at_receive ;
/**
* The identifier of this net-vm.
*/
int m_id ;
/**
* The next message to be retrieved,
*/
private VMMemory m_msg ;
/**
* The message delay.
*/
private int m_delay ;
/**
* Create a new random access machine.
* @param p_context The memory context used.
*/
public NetVM (final NetVMContext p_context)
{
super(p_context);
}
/**
* Obtain the count of messages sent by this virtual machine.
* @return The count of messages sent by this virtual machine.
*/
public final int get_successful_sends ()
{
return this.m_successful_sends;
}
/**
* Obtain the count of messages that could not be sent because the maximum
* allowed count of messages has already been exceeded by this virtual
* machine.
* @return The count of messages that could not be sent because the maximum
* allowed count of messages has already been exceeded by this
* virtual machine.
*/
public final long get_failed_sends()
{
return this.m_failed_sends;
}
/**
* Initialize the state of this virtual machine.
* @param p_program The program to run on this machine.
*/
@Override
public void init(final Program p_program)
{
super.init(p_program);
this.m_failed_sends = 0;
this.m_successful_sends = 0;
this.m_last = false;
this.m_delivered = 0;
this.m_lost_at_receive = 0;
this.m_empty_sends = 0;
if(this.m_msg != null)
{
this.get_context().dispose_mem(this.m_msg);
this.m_msg = null;
}
this.m_delay = 0;
}
/**
* This command takes the current data stack and sends it as message over
* the network.
*/
public final void send ()
{
VMMemory l_m;
int l_i;
NetVMContext l_nvmc;
l_m = this.remove_stack();
if(l_m != null)
{
l_i = this.m_successful_sends;
l_nvmc = ((NetVMContext)(this.get_context()));
if(l_nvmc.m_max_msgs > l_i)
{
this.m_successful_sends = (l_i+1);
l_nvmc.deliver(this, l_m);
}
else
{
this.m_failed_sends++;
l_nvmc.dispose_mem(l_m);
}
}
else this.m_empty_sends++;
}
/**
* Obtain the count of send operations failed because the send buffer was
* empty.
* @return The count of send operations failed because the send buffer was
* empty.
*/
public final long get_empty_sends ()
{
return this.m_empty_sends;
}
/**
* This method returns true
if and only if this vm is the
* last virtual machine in the virtual network still running actively.
* @return true
if and only if this vm is the
* last virtual machine in the virtual network still running.
*/
public final boolean is_last()
{
return this.m_last;
}
/**
* Receive a message. When calling this method, the interrupt assigned
* to message handling is invoked.
* @param p_parameters The message data.
* @param p_delay The message latency.
* @return true
if and only if the interrupt call needed for
* message processing was successful.
*/
public final boolean receive(final VMMemory p_parameters,
final int p_delay)
{
if(this.m_msg != null)
{
this.m_lost_at_receive++;
return false;
}
this.m_msg = p_parameters;
this.m_delay = p_delay;
return true;
}
/**
* Obtain the count of messages successfully delivered.
* @return The count of messages successfully delivered.
*/
public final long get_delivered()
{
return this.m_delivered;
}
/**
* Obtain the count of messages lost due to busyness at the receiving node.
* @return The count of messages lost due to busyness at the receiving node.
*/
public final long get_lost_at_receive()
{
return this.m_lost_at_receive;
}
/**
* Obtain the identifier of this vm.
* @return The identifier of this vm.
*/
public final int get_id()
{
return this.m_id;
}
/**
* Perform a single clock tick.
* @return true
if and only if the program wasn't terminated
* yet and an instruction was executed.
*/
@Override
public boolean tick ()
{
if( (this.m_msg != null) && ((--this.m_delay) <= 0) )
{
if(this.interrupt(1, this.m_msg))
{
this.m_delivered++;
}
else
{
this.m_lost_at_receive++;
this.get_context().dispose_mem(this.m_msg);
}
this.m_msg = null;
}
return super.tick();
}
}