Go to the first, previous, next, last section, table of contents.


Example of an Event Driven Simulation

The following example shows how to program an M/M/1 queuing system simulation with CNCL events:

// -*- C++ -*-

#include <iostream.h>

#include <CNCL/QueueFIFO.h>
#include <CNCL/EventScheduler.h>
#include <CNCL/FiboG.h>
#include <CNCL/NegExp.h>
#include <CNCL/Moments.h>
#include <CNCL/Job.h>

enum { NJOBS=100000 };

enum { EV_JOB, EV_TIMER_G, EV_TIMER_S }; // Event types for M/M/1 simulation

class Server : public CNEventHandler
{
private:
    CNJob *job;             // Served job
    CNQueueFIFO queue;    // CNQueue
    CNRandom &rnd_b;      // Distribution of service time b
    CNMoments t_w, t_b;   // Evaluation tau_w, tau_b
    enum { ST_WAITING, ST_SERVING };
    
public:
    virtual void event_handler(const CNEvent *ev);

    void print_results();
    void eval_job(CNJob *job);

    Server(CNRandom &rnd) : rnd_b(rnd), job(NIL), t_w("tau_w"), t_b("tau_b")
    {
        state(ST_WAITING);
    }
};

class Generator : public CNEventHandler
{
private:
    CNRandom &rnd_a;      // Distribution of arrival time a
    Server *server;       // Connected queue/server
    long n;
    
public:
    virtual void event_handler(const CNEvent *ev);

    Generator(CNRandom &rnd,Server *serv) : rnd_a(rnd),server(serv),n(0) {}
};

void Generator::event_handler(const CNEvent *ev)
{
    if(n == NJOBS)
        // Stop simulation
        return;

    // Incoming event -> generate new Job
    send_now(new CNEvent(EV_JOB, server, new CNJob));
    // Random delay
    send_delay(new CNEvent(EV_TIMER_G), rnd_a());
    n++;
}

void Server::event_handler(const CNEvent *ev)
{
    switch(state())
    {
    case ST_SERVING:
        switch(ev->type())
        {
        case EV_JOB:
            // Incoming job, put into queue
            {
                CNJob *job;
                job = (CNJob *)ev->object();
                job->in = now();
                queue.put(job);
            }
            break;
            
        case EV_TIMER_S:
            // Timer event, service time run down
            job->out = now();
            // Evaluate job
            eval_job(job);
            delete job;
            job = NIL;
            // Get new job from queue
            if(!queue.empty())
            {
                job = (CNJob *)queue.get();
                job->start = now();
                // Random service time
                send_delay(new CNEvent(EV_TIMER_S), rnd_b());
                state(ST_SERVING);
            }
            else
                state(ST_WAITING);
            break;
        }
        break;
        
    case ST_WAITING:
        switch(ev->type())
        {
        case EV_JOB:
            // Incoming job
            job = (CNJob *)ev->object();
            job->in    = now();
            job->start = now();
            // CNRandom service time
            send_delay(new CNEvent(EV_TIMER_S), rnd_b());
            state(ST_SERVING);
            break;
        }
        break;
    }
}

void Server::eval_job(CNJob *job)
{
    t_w.put(job->start - job->in);
    t_b.put(job->out   - job->in);
}

void Server::print_results()
{
    cout << t_w << t_b;
}

main()
{
    CNRNG   *rng   = new CNFiboG;
    CNNegExp rnd_a(10, rng);
    CNNegExp rnd_b( 5, rng);

    Server           server(rnd_b);
    Generator        generator(rnd_a, &server);
    
    CNEventScheduler scheduler;
    scheduler.start(new CNEvent(EV_TIMER_G, &generator));

    server.print_results();
    
}


Go to the first, previous, next, last section, table of contents.