//======================================================================== // twolist.cpp -- Implementation for the abstract class TwoListPrioQueue //======================================================================== /* C++ version by Agustin J. Gonzalez of: twolist.cpp: The following procedures implement the enqueue and dequeue operations on a priority queue using the two list representation described by John H. Blackstone, Gary L. Hogg, and Don T. Phillips in 'A two-list synchronization procedure for discrete event simulation,' Comm. ACM 24, 12 (Dec. 81), pages 825-829. This code was written by Douglas Jones. */ #include #include // malloc #include "twolist.h" //========================= TwoListPrioQueue::TwoListPrioQueue =========================== // Constructor TwoListPrioQueue::TwoListPrioQueue () { sorted=NULL; unsorted=NULL; length=0; cutoff=1.0; delta=2.0; } //========================= TwoListPrioQueue::~TwoListPrioQueue =========================== // Destructor TwoListPrioQueue::~TwoListPrioQueue () { } //========================= TwoListPrioQueue::enqueue =========================== // Method void TwoListPrioQueue::enqueue (Event * event) { Node * n = new Node(event); if ( length == 0 ) { sorted = n; n->leftlink = NULL; cutoff = n->prio; } else { if (n->prio > cutoff) { // put new node in unsorted list n->leftlink = unsorted; unsorted = n; } else if (sorted == NULL) { // put new node in sorted list sorted = n; n->leftlink = NULL; } else if (sorted->prio > n->prio) { n->leftlink = sorted; sorted = n; } else{ // sift new node into sorted list Node * p; p = sorted; while (1) { if (p->leftlink == NULL) { p->leftlink = n; n->leftlink = NULL; break; // goto 1; } else if (p->leftlink->prio > n->prio) { n->leftlink = p->leftlink; p->leftlink = n; break; //goto 1; } else p = p->leftlink; } // while // 1: // loop exit label } } length++; } // enqueue //========================= TwoListPrioQueue::dequeue =========================== // Method Event * TwoListPrioQueue::dequeue () { Node *n, *p, *r; int moved; while (sorted == NULL) { // unsorted queue must be scanned cutoff+= delta; moved = 0; r = unsorted; unsorted = NULL; do { // scan down old unsorted list, picking out nodes to sort n = r; r = r->leftlink; if (n->prio > cutoff) { // put back on unsorted list n->leftlink = unsorted; unsorted = n; } else { // sift into sorted list if (sorted ==NULL) { sorted = n; n->leftlink = NULL; } else if (sorted->prio > n->prio) { n->leftlink = sorted; sorted = n; } else { p = sorted; while (1) { if (p->leftlink == NULL) { p->leftlink = n; n->leftlink = NULL; break; // goto 1; } else if (p->leftlink->prio > n->prio) { n->leftlink = p->leftlink; p->leftlink = n; break; // goto 1; } else p = p->leftlink; } // 1: } moved++; } } while (r != NULL); if ((moved > 0) && (length > 4)) delta*=(0.5 + 0.5*( (2*sqrt(length)) / moved )); } p = sorted; sorted = p->leftlink; Event * e = p->event; delete(p); length--; return (e); } // dequeue TwoListPrioQueue::Node * TwoListPrioQueue::Node::freelist; //============== TwoListPrioQueue::Node::operator delete =================== // override operator delete void TwoListPrioQueue::Node::operator delete(void* ptr) { Node * p = (Node*) ptr; p->leftlink = freelist; freelist = p; } //============== TwoListPrioQueue::Node::operator new =================== // override operator new void * TwoListPrioQueue::Node:: operator new (size_t sz) { if (freelist ==0) return malloc(sz); else { Node * newNode =freelist; freelist = freelist->leftlink; return(newNode); } } //============== TwoListPrioQueue::Node::freeAll =================== // free allocated memory void TwoListPrioQueue::Node::freeAll(void) { Node * p = freelist; while( freelist != 0) { freelist = freelist -> leftlink; free(p); p = freelist; } }