Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

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  * Copyright (c) 2002 University of Southern California/Information
00004  * Sciences Institute.  All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms are permitted
00007  * provided that the above copyright notice and this paragraph are
00008  * duplicated in all such forms and that any documentation, advertising
00009  * materials, and other materials related to such distribution and use
00010  * acknowledge that the software was developed by the University of
00011  * Southern California, Information Sciences Institute.  The name of the
00012  * University may not be used to endorse or promote products derived from
00013  * this software without specific prior written permission.
00014  *
00015  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
00016  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00017  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00018  *
00019  * @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/splay-scheduler.cc,v 1.5 2002/12/02 21:15:43 yuri Exp $
00020  */
00021 #ifndef lint
00022 static const char rcsid[] =
00023 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/splay-scheduler.cc,v 1.5 2002/12/02 21:15:43 yuri Exp $";
00024 #endif
00025 
00052 #include <scheduler.h>
00053 #include <assert.h>
00054 
00055 
00056 static class SplaySchedulerClass : public TclClass 
00057 {
00058 public:
00059         SplaySchedulerClass() : TclClass("Scheduler/Splay") {}
00060         TclObject* create(int /* argc */, const char*const* /* argv */) {
00061                 return (new SplayScheduler);
00062         }
00063 } class_splay_sched;
00064 
00065 #undef LEFT
00066 #undef RIGHT
00067 #define LEFT(e)                         ((e)->prev_)    
00068 #define RIGHT(e)                        ((e)->next_)
00069 
00070 #define ROTATE_RIGHT(t, x)              \
00071     do {                                \
00072         LEFT(t) = RIGHT(x);             \
00073         RIGHT(x) = (t);                 \
00074         (t) = (x);                      \
00075     } while(0)
00076 
00077 #define ROTATE_LEFT(t, x)               \
00078     do {                                \
00079         RIGHT(t)  = LEFT(x);            \
00080         LEFT(x) = (t);                  \
00081         (t) = (x);                      \
00082     } while(0)
00083 #define LINK_LEFT(l, t)                 \
00084     do {                                \
00085         RIGHT(l) = (t);                 \
00086         (l) = (t);                      \
00087         (t) = RIGHT(t);                 \
00088     } while (0)
00089 #define LINK_RIGHT(r, t)                \
00090     do {                                \
00091         LEFT(r) = (t);                  \
00092         (r) = (t);                      \
00093         (t) = LEFT(t);                  \
00094     } while (0)
00095 
00096 void
00097 SplayScheduler::insert(Event *n) 
00098 {
00099         Event *l;       // bottom right in the left tree
00100         Event *r;       // bottom left in the right tree
00101         Event *t;       // root of the remaining tree
00102         Event *x;       // current node
00103     
00104         ++qsize_;
00105 
00106         double time = n->time_;
00107     
00108         if (root_ == 0) {
00109                 LEFT(n) = RIGHT(n) = 0;
00110                 root_ = n;
00111                 //validate();
00112                 return;
00113         }
00114         t = root_;
00115         root_ = n;      // n is the new root
00116         l = n;
00117         r = n;
00118         for (;;) {
00119                 if (time < t->time_) {
00120                         x = LEFT(t);
00121                         if (x == 0) {
00122                                 LEFT(r) = t;
00123                                 RIGHT(l) = 0;
00124                                 break;
00125                         }
00126                         if (time < x->time_) {
00127                                 ROTATE_RIGHT(t, x);
00128                         }
00129                         LINK_RIGHT(r, t);
00130                         if (t == 0) {
00131                                 RIGHT(l) = 0;
00132                                 break;
00133                         }
00134                 } else {
00135                         x = RIGHT(t);
00136                         if (x == 0) {
00137                                 RIGHT(l) = t; 
00138                                 LEFT(r) = 0;
00139                                 break;  
00140                         }
00141                         if (time >= x->time_) {
00142                                 ROTATE_LEFT(t, x);
00143                         }
00144                         LINK_LEFT(l, t);
00145                         if (t == 0) {
00146                                 LEFT(r) = 0;
00147                                 break;
00148                         }
00149                         
00150                 }
00151         } /* for (;;) */
00152 
00153         // assemble:
00154         //   swap left and right children
00155         x = LEFT(n);
00156         LEFT(n) = RIGHT(n);
00157         RIGHT(n) = x;
00158         //validate();
00159 }
00160 
00161 const Event *
00162 SplayScheduler::head()
00163 {
00164         Event *t;
00165         Event *l;
00166 #if 1
00167         if (root_ == 0)
00168                 return 0;
00169         for (t = root_; (l = LEFT(t)); t = l)
00170                 ;
00171 
00172         return t;
00173 #else
00174         Event *ll;
00175         Event *lll;
00176 
00177         if (root_ == 0)
00178                 return 0;
00179 
00180         t = root_;
00181         l = LEFT(t);
00182 
00183         if (l == 0) {
00184                 return t;
00185         }
00186         for (;;) { 
00187                 ll = LEFT(l);
00188                 if (ll == 0) {
00189                         return l;
00190                 }
00191 
00192                 lll = LEFT(ll);
00193                 if (lll == 0) {
00194                         return ll;
00195                 }
00196 
00197                 // zig-zig: rotate l with ll
00198                 LEFT(t) = ll;
00199                 LEFT(l) = RIGHT(ll);
00200                 RIGHT(ll) = l;
00201 
00202                 t = ll;
00203                 l = lll;
00204         }
00205 #endif /* 1/0 */
00206 }
00207 
00208 Event *
00209 SplayScheduler::deque()
00210 {
00211         Event *t;
00212         Event *l;
00213         Event *ll;
00214         Event *lll;
00215 
00216         if (root_ == 0)
00217                 return 0;
00218 
00219         --qsize_;
00220 
00221         t = root_;
00222         l = LEFT(t);
00223 
00224         if (l == 0) {                   // root is the element to dequeue
00225                 root_ = RIGHT(t);       // right branch becomes the root
00226                 //validate();
00227                 return t;
00228         }
00229         for (;;) { 
00230                 ll = LEFT(l);
00231                 if (ll == 0) {
00232                         LEFT(t) = RIGHT(l);
00233                         //validate();
00234                         return l;
00235                 }
00236 
00237                 lll = LEFT(ll);
00238                 if (lll == 0) {
00239                         LEFT(l) = RIGHT(ll);
00240                         //validate();
00241                         return ll;
00242                 }
00243 
00244                 // zig-zig: rotate l with ll
00245                 LEFT(t) = ll;
00246                 LEFT(l) = RIGHT(ll);
00247                 RIGHT(ll) = l;
00248 
00249                 t = ll;
00250                 l = lll;
00251         }
00252 } 
00253 
00254 void 
00255 SplayScheduler::cancel(Event *e)
00256 {
00257 
00258         if (e->uid_ <= 0) 
00259                 return; // event not in queue
00260 
00261         Event **t;
00262         //validate();
00263         if (e == root_) {
00264                 t = &root_;
00265         } else {
00266                 // searching among same-time events is a real bugger,
00267                 // all because we don't have a parent pointer; use
00268                 // uid_ to resolve conflicts.
00269                 for (t = &root_; *t;) {
00270                         t = ((e->time_ > (*t)->time_) || 
00271                              ((e->time_ == (*t)->time_) && e->uid_ > (*t)->uid_))
00272                                 ? &RIGHT(*t) : &LEFT(*t);
00273                         if (*t == e)
00274                                 break;
00275                 }
00276                 if (*t == 0) {
00277                         fprintf(stderr, "did not find it\n");
00278                         abort(); // not found
00279                 }
00280         }
00281         // t is the pointer to e in the parent or to root_ if e is root_
00282         e->uid_ = -e->uid_;
00283         --qsize_;
00284 
00285         if (RIGHT(e) == 0) {
00286                 *t = LEFT(e);
00287                 LEFT(e) = 0;
00288                 //validate();
00289                 return;
00290         } 
00291         if (LEFT(e) == 0) {
00292                 *t = RIGHT(e);
00293                 RIGHT(e) = 0;
00294                 //validate();
00295                 return;
00296         }
00297 
00298         // find successor
00299         Event *p = RIGHT(e), *q = LEFT(p);
00300 
00301         if (q == 0) {
00302                 // p is the sucessor
00303                 *t = p;
00304                 LEFT(p) = LEFT(e);
00305                 //validate();
00306                 return;
00307         }
00308         for (; LEFT(q); p = q, q = LEFT(q)) 
00309                 ;
00310         // q is the successor
00311         // p is q's parent
00312         *t = q;
00313         LEFT(p) = RIGHT(q);
00314         LEFT(q) = LEFT(e);
00315         RIGHT(q) = RIGHT(e);
00316         RIGHT(e) = LEFT(e) = 0;
00317         //validate();
00318 }
00319 
00320 
00321 Event *
00322 SplayScheduler::lookup(scheduler_uid_t uid) 
00323 {
00324         lookup_uid_ = uid;
00325         return uid_lookup(root_);
00326 }
00327 
00328 Event *
00329 SplayScheduler::uid_lookup(Event *root)
00330 {
00331         if (root == 0)
00332                 return 0;
00333         if (root->uid_ == lookup_uid_)
00334                 return root;
00335 
00336         Event *res = uid_lookup(LEFT(root));
00337  
00338         if (res) 
00339                 return res;
00340 
00341         return uid_lookup(RIGHT(root));
00342 }
00343 
00344 int
00345 SplayScheduler::validate(Event *root) 
00346 {
00347         int size = 0;
00348         if (root) {
00349                 ++size;
00350                 assert(LEFT(root) == 0 || root->time_ >= LEFT(root)->time_);
00351                 assert(RIGHT(root) == 0 || root->time_ <= RIGHT(root)->time_);
00352                 size += validate(LEFT(root));
00353                 size += validate(RIGHT(root));
00354                 return size;
00355         }
00356         return 0;
00357 }

Generated on Tue Apr 20 12:14:33 2004 for NS2.26SourcesOriginal by doxygen 1.3.3