Schedule知识转载

NS中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_);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值