Buffer defined in DEVSsharp/ModelBase/Buffer.cs is a
concrete class derived from Atomic. This class has a single
input port in, an pull and
an out (in this example,
phase is a string; m_Jobs is
a buffer keeping incoming clients whose type is Job class;
m_OAvail is a vector of boolean values tracking the
availability of servers; m_OSzie stores the number of
connected servers; and send_index is an int which
tracks the server index to which Buffer will send output.
public class Buffer: Atomic
{
public InputPort iin;
public List<InputPort> pull;
public List<OutputPort> oout;
private List<Job> m_Jobs; // FIFO Buffer
protected enum PHASE { Idle, SendTo, Ask };
protected PHASE m_phase;
protected List<bool> m_OAvail;//check availability of next resource
protected int m_Osize; // size of output
protected int m_send_index; // index to which it will send
protected double m_send_time;
The function C1 updates member data as a function of an
input event x. If x comes through the input port
in, C1 casts the value of x to Job and
pushes it back to the buffer m_Jobs. Otherwise, x
comes through one of pull ports. So C1 searches the
server index i, checking the identity of pull[i] and
the incoming event's port, and updates m_OAvail[i]=true
which marks the i-th server as being available.
virtual protected void C1(PortValue x)
{
if(x.port == iin){ //receiving a client
if(x.value is Job) {
Job client = (Job)x.value;
if(client != null)
m_Jobs.Add(client);
}
else
throw new Exception("Invalid Input!");
}
else // receiving a pull signal
{
for(int i=0; i<m_Osize; i++) {
if(x.port == pull[i]) {
m_OAvail[i]= true; // server_i is available
break;
}
}
}
}
The function Matched() first checks to see if there is a
waiting job in m_Jobs and then checks to see if there
exists an available server from 0 to m_Osize-1. If a match
is found, the function sets m_OAvail[i]=false, remembers
the index i at send_index, then returns true.
Otherwise it returns false which means no match.
private bool Matched()
{
if(m_Jobs.Count > 0){
for(int i=0; i < m_Osize; i++){// select server
if(m_OAvail[i] == true){// server i is available
m_OAvail[i]=false;//Mark server_i non-available
m_send_index = i; // remember i in m_send_index
return true;
}
}
return false;
}else
return false;
}
The function C2 creates an the output event and removes the
first job from m_Jobs when C2's phase is
SendTo.
virtual protected void C2(ref PortValue y)
{
if(m_phase == PHASE.SendTo){
Job job = m_Jobs[0];
y.Set(oout[m_send_index], job);
m_Jobs.RemoveAt(0);// remove the first client
}
}
The function init() of Buffer resets phase to
Idle, assigns m_OAvial[i]=true for all indices, and
clears all jobs in m_Jobs.
public override void init()
{
m_phase = PHASE.Idle;
m_Jobs.Clear();
m_send_index = 0;
m_OAvail.Clear();
for (int i = 0; i < m_Osize; i++)
m_OAvail.Add(true); // add variable
}
Buffer's tau() returns
for Idle and
returns 2.0 for SendTo.
public override double tau()
{
if (m_phase == PHASE.Idle)
return double.MaxValue;
else
return m_send_time;
}
The input transition function delta_x of Buffer
updates member data by calling C1(x) and then, if the phase
of the server is Idle, checks the returning value of
Matched(). If the value is true, the phase of the
server changes into SendTo.
public override bool delta_x(PortValue x)
{
C1(x);
if (m_phase == PHASE.Idle)
{
if (Matched())
{
m_phase = PHASE.SendTo;//
return true; // reschedule as active
}
}
return false;
}
When the server is ready to exit the state SendTo, it gets
y by calling C2(y), if Matched() returns
true, the phase stays at SendTo. Otherwise, the
phase returns to Idle.
public override void delta_y(ref PortValue y)
{
C2(ref y);
if (Matched())
m_phase = PHASE.SendTo;
else
m_phase = PHASE.Idle;
}
Recall that Buffer class contains the overriding
Get_Statistics_s() and GetPerformance(), which were
investigated in Section 4.2.3. For the
codes of Buffer::Get_s(), the reader should refer to
Buffer.cs.