Chinaunix首页 | 论坛 | 博客
  • 博客访问: 160656
  • 博文数量: 16
  • 博客积分: 1456
  • 博客等级: 上尉
  • 技术积分: 214
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-14 18:30
文章分类
文章存档

2012年(1)

2011年(1)

2010年(2)

2009年(1)

2007年(11)

我的朋友

分类: 系统运维

2007-04-08 00:05:12

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_);
}


阅读(2491) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~