splay-scheduler.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * splay-scheduler.cc
00005  * Copyright (C) 2002 by the University of Southern California
00006  * $Id: splay-scheduler.cc,v 1.6 2005/08/25 18:58:02 johnh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 // @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/splay-scheduler.cc,v 1.6 2005/08/25 18:58:02 johnh Exp $
00049 
00050 #ifndef lint
00051 static const char rcsid[] =
00052 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/splay-scheduler.cc,v 1.6 2005/08/25 18:58:02 johnh Exp $";
00053 #endif
00054 
00082 #include <scheduler.h>
00083 #include <assert.h>
00084 
00085 
00086 static class SplaySchedulerClass : public TclClass 
00087 {
00088 public:
00089         SplaySchedulerClass() : TclClass("Scheduler/Splay") {}
00090         TclObject* create(int /* argc */, const char*const* /* argv */) {
00091                 return (new SplayScheduler);
00092         }
00093 } class_splay_sched;
00094 
00095 #undef LEFT
00096 #undef RIGHT
00097 #define LEFT(e)             ((e)->prev_)    
00098 #define RIGHT(e)            ((e)->next_)
00099 
00100 #define ROTATE_RIGHT(t, x)      \
00101     do {                \
00102         LEFT(t) = RIGHT(x);     \
00103         RIGHT(x) = (t);         \
00104         (t) = (x);          \
00105     } while(0)
00106 
00107 #define ROTATE_LEFT(t, x)       \
00108     do {                \
00109         RIGHT(t)  = LEFT(x);        \
00110         LEFT(x) = (t);          \
00111         (t) = (x);          \
00112     } while(0)
00113 #define LINK_LEFT(l, t)         \
00114     do {                \
00115     RIGHT(l) = (t);         \
00116     (l) = (t);          \
00117     (t) = RIGHT(t);         \
00118     } while (0)
00119 #define LINK_RIGHT(r, t)        \
00120     do {                \
00121     LEFT(r) = (t);          \
00122     (r) = (t);          \
00123     (t) = LEFT(t);          \
00124     } while (0)
00125 
00126 void
00127 SplayScheduler::insert(Event *n) 
00128 {
00129     Event *l;   // bottom right in the left tree
00130     Event *r;   // bottom left in the right tree
00131     Event *t;   // root of the remaining tree
00132     Event *x;       // current node
00133     
00134     ++qsize_;
00135 
00136     double time = n->time_;
00137     
00138     if (root_ == 0) {
00139         LEFT(n) = RIGHT(n) = 0;
00140         root_ = n;
00141         //validate();
00142         return;
00143     }
00144     t = root_;
00145     root_ = n;  // n is the new root
00146     l = n;
00147     r = n;
00148     for (;;) {
00149         if (time < t->time_) {
00150             x = LEFT(t);
00151             if (x == 0) {
00152                 LEFT(r) = t;
00153                 RIGHT(l) = 0;
00154                 break;
00155             }
00156             if (time < x->time_) {
00157                 ROTATE_RIGHT(t, x);
00158             }
00159             LINK_RIGHT(r, t);
00160             if (t == 0) {
00161                 RIGHT(l) = 0;
00162                 break;
00163             }
00164         } else {
00165             x = RIGHT(t);
00166             if (x == 0) {
00167                 RIGHT(l) = t; 
00168                 LEFT(r) = 0;
00169                 break;  
00170             }
00171             if (time >= x->time_) {
00172                 ROTATE_LEFT(t, x);
00173             }
00174             LINK_LEFT(l, t);
00175             if (t == 0) {
00176                 LEFT(r) = 0;
00177                 break;
00178             }
00179             
00180         }
00181     } /* for (;;) */
00182 
00183     // assemble:
00184     //   swap left and right children
00185     x = LEFT(n);
00186     LEFT(n) = RIGHT(n);
00187     RIGHT(n) = x;
00188     //validate();
00189 }
00190 
00191 const Event *
00192 SplayScheduler::head()
00193 {
00194     Event *t;
00195     Event *l;
00196 #if 1
00197     if (root_ == 0)
00198         return 0;
00199     for (t = root_; (l = LEFT(t)); t = l)
00200         ;
00201 
00202     return t;
00203 #else
00204     Event *ll;
00205     Event *lll;
00206 
00207     if (root_ == 0)
00208         return 0;
00209 
00210     t = root_;
00211     l = LEFT(t);
00212 
00213     if (l == 0) {
00214         return t;
00215     }
00216     for (;;) { 
00217         ll = LEFT(l);
00218         if (ll == 0) {
00219             return l;
00220         }
00221 
00222         lll = LEFT(ll);
00223         if (lll == 0) {
00224             return ll;
00225         }
00226 
00227         // zig-zig: rotate l with ll
00228         LEFT(t) = ll;
00229         LEFT(l) = RIGHT(ll);
00230         RIGHT(ll) = l;
00231 
00232         t = ll;
00233         l = lll;
00234     }
00235 #endif /* 1/0 */
00236 }
00237 
00238 Event *
00239 SplayScheduler::deque()
00240 {
00241     Event *t;
00242     Event *l;
00243     Event *ll;
00244     Event *lll;
00245 
00246     if (root_ == 0)
00247         return 0;
00248 
00249     --qsize_;
00250 
00251     t = root_;
00252     l = LEFT(t);
00253 
00254     if (l == 0) {           // root is the element to dequeue
00255         root_ = RIGHT(t);   // right branch becomes the root
00256         //validate();
00257         return t;
00258     }
00259     for (;;) { 
00260         ll = LEFT(l);
00261         if (ll == 0) {
00262             LEFT(t) = RIGHT(l);
00263             //validate();
00264             return l;
00265         }
00266 
00267         lll = LEFT(ll);
00268         if (lll == 0) {
00269             LEFT(l) = RIGHT(ll);
00270             //validate();
00271             return ll;
00272         }
00273 
00274         // zig-zig: rotate l with ll
00275         LEFT(t) = ll;
00276         LEFT(l) = RIGHT(ll);
00277         RIGHT(ll) = l;
00278 
00279         t = ll;
00280         l = lll;
00281     }
00282 } 
00283 
00284 void 
00285 SplayScheduler::cancel(Event *e)
00286 {
00287 
00288     if (e->uid_ <= 0) 
00289         return; // event not in queue
00290 
00291     Event **t;
00292     //validate();
00293     if (e == root_) {
00294         t = &root_;
00295     } else {
00296         // searching among same-time events is a real bugger,
00297         // all because we don't have a parent pointer; use
00298         // uid_ to resolve conflicts.
00299         for (t = &root_; *t;) {
00300             t = ((e->time_ > (*t)->time_) || 
00301                  ((e->time_ == (*t)->time_) && e->uid_ > (*t)->uid_))
00302                 ? &RIGHT(*t) : &LEFT(*t);
00303             if (*t == e)
00304                 break;
00305         }
00306         if (*t == 0) {
00307             fprintf(stderr, "did not find it\n");
00308             abort(); // not found
00309         }
00310     }
00311     // t is the pointer to e in the parent or to root_ if e is root_
00312     e->uid_ = -e->uid_;
00313     --qsize_;
00314 
00315     if (RIGHT(e) == 0) {
00316         *t = LEFT(e);
00317         LEFT(e) = 0;
00318         //validate();
00319         return;
00320     } 
00321     if (LEFT(e) == 0) {
00322         *t = RIGHT(e);
00323         RIGHT(e) = 0;
00324         //validate();
00325         return;
00326     }
00327 
00328     // find successor
00329     Event *p = RIGHT(e), *q = LEFT(p);
00330 
00331     if (q == 0) {
00332         // p is the sucessor
00333         *t = p;
00334         LEFT(p) = LEFT(e);
00335         //validate();
00336         return;
00337     }
00338     for (; LEFT(q); p = q, q = LEFT(q)) 
00339         ;
00340     // q is the successor
00341     // p is q's parent
00342     *t = q;
00343     LEFT(p) = RIGHT(q);
00344     LEFT(q) = LEFT(e);
00345     RIGHT(q) = RIGHT(e);
00346     RIGHT(e) = LEFT(e) = 0;
00347     //validate();
00348 }
00349 
00350 
00351 Event *
00352 SplayScheduler::lookup(scheduler_uid_t uid) 
00353 {
00354     lookup_uid_ = uid;
00355     return uid_lookup(root_);
00356 }
00357 
00358 Event *
00359 SplayScheduler::uid_lookup(Event *root)
00360 {
00361     if (root == 0)
00362         return 0;
00363     if (root->uid_ == lookup_uid_)
00364         return root;
00365 
00366     Event *res = uid_lookup(LEFT(root));
00367  
00368     if (res) 
00369         return res;
00370 
00371     return uid_lookup(RIGHT(root));
00372 }
00373 
00374 int
00375 SplayScheduler::validate(Event *root) 
00376 {
00377     int size = 0;
00378     if (root) {
00379         ++size;
00380         assert(LEFT(root) == 0 || root->time_ >= LEFT(root)->time_);
00381         assert(RIGHT(root) == 0 || root->time_ <= RIGHT(root)->time_);
00382         size += validate(LEFT(root));
00383         size += validate(RIGHT(root));
00384         return size;
00385     }
00386     return 0;
00387 }

Generated on Tue Mar 6 16:47:51 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6