next up previous contents index
Next: Performance Analysis Up: Client-Server System Previous: Server   Contents   Index


Buffer

Buffer is a concrete class derived from Atomic. This class has a single input port in, an $ n$ -vector of input ports pull and an $ n$ - vector of output ports out (in this example, $ n$ =3). As member data, phase is a string; m_Clients is a buffer keeping incoming clients whose type is tmValue; 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.
class Buffer: public Atomic {
public:
    InputPort* in;
    vector<InputPort*> pull;
    vector<OutputPort*> out;

protected:
    string m_phase;
    deque<tmValue*> m_Clients;
    vector<bool> m_OAvail;
    const int m_Osize;
    int send_index;

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 tmValue and pushes it back to the buffer m_Clients. 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.

void C1(const PortValue& x)
{
    if(x.port == in){ //receiving a client
        tmValue* client = dynamic_cast<tmValue*>(x.value);
        if(client) {
            m_Clients.push_back(client);
        } else
            THROW_DEVS_EXCEPTION("Dynamic Casting Failed!");
    }
    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 client in m_Clients 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.
bool Matched()
{
    if(m_Clients.empty() == false){
        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
                send_index = i; // remember i in send_index
                return true;
            }
        }
        return false;
    }else
        return false;
}

The function C2 creates an the output event and removes the first client from m_Clients when C2's phase is SENDTO.

void C2(PortValue& y) {
    if(m_phase == SENDTO){
        y.Set(out[send_index], m_Clients[0]);
        m_Clients.pop_front();// remove the first client
    }
}

The function init() of Buffer resets phase to IDLE, assigns m_OAvial[i]=true for all indices, and clears all clients in m_Clients.

/*virtual*/ void init()
{
    m_phase = IDLE;
    m_OAvail.clear(); // clear first
    for(int i=0; i<m_Osize; i++)
        m_OAvail.push_back(true); // add variable

    while(m_Clients.empty() == false)
    {
        tmValue* cl = m_Clients[0];
        m_Clients.pop_front();
        delete cl;
    }
}

Buffer's tau() returns $ \infty$ for IDLE and returns 2.0 for SENDTO.

/*virtual*/ Time tau() const {
    if(m_phase == IDLE)
        return DBL_MAX;
    else
        return 2.0;
}
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.
/*virtual*/ bool delta_x(const PortValue& x)
{
    C1(x);
    if(m_phase == IDLE){
        if(Matched()){
            m_phase = SENDTO;
            return true; // reschedule as active
        }
    }
    return false;
}

When the server is ready to exit the SENDTO state, it gets y by calling C2(y), if Matched() returns true, the phase stays at SENDTO. Otherwise, the phase returns to IDLE.

/*virtual*/ void delta_y(PortValue& y) {
    C2(y);
    if(Matched())
        m_phase = SENDTO;
    else
        m_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.h.


next up previous contents index
Next: Performance Analysis Up: Client-Server System Previous: Server   Contents   Index
MHHwang 2007-05-07