?? mm1.cc
字號:
/************************************************************************ * @<title> M/M/1 Simulation written in COST/COMPC++ </title>@ * * @<h1> M/M/1 Simulation </h1>@ * To help users understand how COST facilitates the development of * simulation models, we will describe in detail the process of building an * M/M/1 system. * In an M/M/1 system, packets(or customers) arrive according * to a Poisson distribution and compete for the service in an FIFO * (First-In-First-Out) manner. The service time is also drawn from a * Poisson distribution. In practice, M/M/1 systems are useful because many * complex systems can be abstracted as compositions of simple M/M/1 systems. * Theoretically, M/M/1 system has an accurate mathematical solution * with respect to the mean arrival rate and the mean service rate. As a * result, it is well suited for validating simulation results. * * An M/M/1 system built using COST/COMPC++ is composed of four components, namely, * Source, FIFO, Server and Sink. Packets are created by Source, queued * in FIFO, served by Server, and dispatched from Sink. * * @<center><img src=mm1.png></center>@ * * @<h2> Using COST </h2>@ * To use COST, simply include the header file @cost.h@. The other file, * @deque@, is required by the FIFO component which we will describe momentarily. ************************************************************************/#include "../../common/cost.h"#include <deque>/************************************************************************ * @<h2> New Data Type </h2>@ * A new data type, @packet_t@, is created to represent the packets * that flow through the M/M/1 system. We are interested in measuring the * delay of packets, which is equal to the time spent in the * FIFO queue plus the service time. For this purpose, @packet_t@ contains * two fields, @arrival_time@ and @departure_time@, which * record the arrival time and the departure time, respectively. In * addition, to identify each packet, another field @seq_number@ is * declared to hold the sequence number (these fields are not all used * in the sample simulation, but they may be essential in other cases). ************************************************************************/ struct packet_t{ int seq_number; double arrival_time,departure_time;};/************************************************************************ * @<h2> Source </h2>@ * Now let us build our first component class @Source@, derived * from @TypeII@. @TypeII@ is the base class for all simulation components in COST. * All components in COST must be derived from @TypeII@. And the reason * it is called TypeII is that in our simulation component classification * they are Time-Aware, meaning they are aware of the existence of * simulated time but have no control over it. ***********************************************************************/component Source : public TypeII{public:/************************************************************************ * The @Source@ component creates packets randomly at an average rate * specified by the parameter @interval@. It has an outport with * an argument type @packet_t@ and return type @void@ (nothing to return), * and a timer @wait@ for scheduling the event to deliver the next packet.************************************************************************/ double interval; outport void out (packet_t&); Timer <trigger_t> wait; /************************************************************************ * A timer is defined a component. It has an outport called @to_component@ * which will be invoked once the event associated with the timer is activated. * Therefore, any component that embeds a timer component must also connect * the outport of the timer to one of its inports. The inport @create@ is declared * for this purpose, and its return type must be @void@, and it (only) argument must be * consistent with the template parameter of the timer (@trigger_t@ in this case).************************************************************************/ inport inline void create(trigger_t& t); Source(); virtual ~Source() {} void Start();private: packet_t m_packet; // for temporarily holding the outgoing packet int m_seq_number; // each packet has an unique sequence number};/************************************************************************ * Here is where we connect the outport of the timer component to the @create()@ inport ************************************************************************/Source::Source(){ connect wait.to_component,create;}/************************************************************************ * The @Start()@ function, invoked the moment the simulation just * gets started, i.e., at the simulation time zero, is where a component * can perform initialization of variables and schedule initial events * by calling the @Set()@ method of the desired timer. * @Exponential()@ is an function declared in the @TypeII@ * class to generate a Poisson distribution. ************************************************************************/void Source::Start(){ m_seq_number=0; wait.Set(Exponential(interval));}/************************************************************************ * The @create()@ function is bound to the outport of the timer @wait@, * so it is invoked every time the timer becomes activated. Upon activation, * it needs to schedule the next timer event whose timestamp represents the time * the next packet is to be generated, and deliver the current packet * to the outport @out@. * * @SimTime()@, a member function declared in the @TypeII@ class, returns * the current simulated time. ************************************************************************/void Source::create(trigger_t&){ wait.Set(SimTime()+Exponential(interval) ); m_packet.seq_number=m_seq_number++; m_packet.arrival_time = SimTime(); out(m_packet); return;}/************************************************************************ * @<h2>FIFO Queue</h2>@ * The @FIFO@ component is declared as a template class with a template * parameter specifying the type of packets that the queue can hold. When * instantiated with different packet types, this component can be * reused to handle packets of any type. ************************************************************************/ template < class DATATYPE >component FIFO : public TypeII{public: FIFO(); virtual ~FIFO(); void Start();/************************************************************************ * The parameter @queue_length@ indicates the maximum number of packets * that can be held in the queue. ************************************************************************/ unsigned int queue_length;/************************************************************************ * This component contains an inport and outport, to receive * and sent packets, of type @DATATYPE@, the template parameter, * as the parameter type, and @void@ as the return type. * Another port, named @next@, is an inport * indicating that it is time to send out the next packet. Its parameter * type is @trigger_t@, a predefined empty class. ************************************************************************/ inport inline void in(DATATYPE&); outport void out(DATATYPE&); inport inline void next();private:/************************************************************************ * A FIFO queue is usually linked to a server, and it needs to know * whether the server is busy or not, since when it receives a new packet * it must determine if it needs to pass on the packet directly or save * it in an internal queue. @m_busy@ indicates the status of the server, * and @m_queue@ is the internal queue. ************************************************************************/ bool m_busy; std::deque<DATATYPE> m_queue;};template < class DATATYPE >FIFO <DATATYPE> :: FIFO(){}template < class DATATYPE >FIFO <DATATYPE> :: ~FIFO(){}/************************************************************************ * @m_busy@ must be set to false at the beginning, since the server * is free at time 0. ************************************************************************/template < class DATATYPE >void FIFO <DATATYPE> :: Start(){ m_busy=false;}/************************************************************************ * The inport @in@ is invoked when a new packet arrives. * Packets are passed by reference to avoid copying overhead. * @m_busy@ remembers the status of the connected server. If the * server is free, simply forward the packet to the outport and update * @m_busy@ accordingly. Otherwise, append the packet to the tail of * the internal queue, if the queue is not full. ************************************************************************/template < class DATATYPE >void FIFO<DATATYPE>::in(DATATYPE& packet){ if (!m_busy) { // server is free, we can pass it through out(packet); m_busy=true; } else if (m_queue.size()<queue_length) { // queue is not full m_queue.push_back(packet); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -