NS中Scheduler类的工作机制简述

本文解析了事件调度机制的核心组件,包括Event、Handler和Scheduler类。介绍了Event类的成员变量及作用,Handler类作为事件处理基类,以及Scheduler类提供的调度接口和内部实现细节。



                               
Scheduler调度的对象是一个个Event对象,比如Packet类就是Event类的派生类。先看Event类有什么:
class Event {
public:
    Event* next_;        /* event list */
    Event* prev_;
    Handler* handler_;    /* handler to call when event ready */
    double time_;        /* time at which event is ready */
    scheduler_uid_t uid_;    /* unique ID */
    Event() : time_(0), uid_(0) {}
};
可见,该类只有5个成员变量,最重要的是后面的三个。
Handler类是所有事件Handler的基类,当事件的调度时间到达时,该事件被传递给必须处理它的Handler。
class Handler {
public:
    virtual ~Handler () {}
    virtual void handle(Event* event) = 0;
};
可见该类只有一个纯虚函数的虚基类,子类继承该类,使用handle()处理到时的事件。
现在看Scheduler类本身:
class Scheduler : public TclObject {
public:
    static Scheduler& instance() {
        return (*instance_);        // general access to scheduler
    }
    void schedule(Handler*, Event*, double delay);    // sched later event
    virtual void run();            // execute the simulator
    virtual void cancel(Event*) = 0;    // cancel event
    virtual void insert(Event*) = 0;    // schedule event
    virtual Event* lookup(scheduler_uid_t uid) = 0;    // look for event
    virtual Event* deque() = 0;        // next event (removes from q)
    virtual const Event* head() = 0;    // next event (not removed from q)
    double clock() const {            // simulator virtual time
        return (clock_);
    }
    virtual void sync() {};
    virtual double start() {        // start time
        return SCHED_START;
    }
    virtual void reset();
protected:
    void dumpq();    // for debug: remove + print remaining events
    void dispatch(Event*);    // execute an event
    void dispatch(Event*, double);    // exec event, set clock_
    Scheduler();
    virtual ~Scheduler();
    int command(int argc, const char*const* argv);
    double clock_;
    int halted_;
    static Scheduler* instance_;
    static scheduler_uid_t uid_;
};
该类成员变量只有4个:
uid_用来给Event分配uid,在scheduler.cc文件的一开始,该变量被初始化为1:
scheduler_uid_t Scheduler::uid_ = 1;
clock_和halted_在构造函数里被初始化为0:Scheduler::Scheduler() : clock_(SCHED_START), halted_(0) {}
宏SCHED_START在scheduler.h中定义为0:#define    SCHED_START    0.0    /* start time (secs) */
提供为外界的接口schedule()函数的主要部分:
void Scheduler::schedule(Handler* h, Event* e, double delay) {
    ...... // a lot of checking
    e->uid_ = uid_++;            // 给该Event分配id
    e->handler_ = h;             // 给其指定处理者h,到时调用处理者h的handle()函数
    e->time_ = clock_ + delay;   // 指定该事件的触发时间,即时间戳
    insert(e);                   // 将该事件插入列表中,使用什么样的列表,由Scheduler类的派生类来决定。
}
Scheduler调度机制的引擎:
void Scheduler::run() {
    instance_ = this;
    Event *p;
    while (!halted_ && (p = deque())) {
        dispatch(p, p->time_);
    }
}
不断从列表中取出Event事件,调用dispatch()执行事件:
void Scheduler::dispatch(Event* p, double t) {
    if (t  clock_) {
        fprintf(stderr, "ns: scheduler going backwards in time from %f to %f./n", clock_, t);
        abort();
    }
    clock_ = t;                // 将系统的虚拟时钟设置为该事件的时间戳
    p->uid_ = -p->uid_;        // 将该Event的id变为相反数以标记它已被dispatch
    p->handler_->handle(p);    // 具体将Event交给Handler来处理
}
void Scheduler::dispatch(Event* p) {
    dispatch(p, p->time_);
}
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点: http://blog.chinaunix.net/u1/33444/showart_272923.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值