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

queue.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) 1996-1997 The Regents of the University of California.
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Network Research
00017  *      Group at Lawrence Berkeley National Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  * 
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 #ifndef lint
00036 static const char rcsid[] =
00037     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/queue.cc,v 1.27 2003/01/28 23:31:03 sfloyd Exp $ (LBL)";
00038 #endif
00039 
00040 #include "queue.h"
00041 #include <math.h>
00042 #include <stdio.h>
00043 
00044 void PacketQueue::remove(Packet* target)
00045 {
00046         for (Packet *pp= 0, *p= head_; p; pp= p, p= p->next_) {
00047                 if (p == target) {
00048                         if (!pp) deque();
00049                         else {
00050                                 if (p == tail_) 
00051                                         tail_= pp;
00052                                 pp->next_= p->next_;
00053                                 --len_;
00054                                 bytes_ -= hdr_cmn::access(p)->size();
00055                         }
00056                         return;
00057                 }
00058         }
00059         fprintf(stderr, "PacketQueue:: remove() couldn't find target\n");
00060         abort();
00061 }
00062 
00063 /*
00064  * Remove packet pkt located after packet prev on the queue.  Either p or prev
00065  * could be NULL.  If prev is NULL then pkt must be the head of the queue.
00066  */
00067 void PacketQueue::remove(Packet* pkt, Packet *prev) //XXX: screwy
00068 {
00069         if (pkt) {
00070                 if (head_ == pkt)
00071                         PacketQueue::deque(); /* decrements len_ internally */
00072                 else {
00073                         prev->next_ = pkt->next_;
00074                         if (tail_ == pkt)
00075                                 tail_ = prev;
00076                         --len_;
00077                         bytes_ -= hdr_cmn::access(pkt)->size();
00078                 }
00079         }
00080         return;
00081 }
00082 
00083 void QueueHandler::handle(Event*)
00084 {
00085         queue_.resume();
00086 }
00087 
00088 Queue::~Queue() {
00089 }
00090 
00091 Queue::Queue() : Connector(), blocked_(0), unblock_on_resume_(1), qh_(*this),
00092         pq_(0), last_change_(0), /* temporarily NULL */
00093         old_util_(0)
00094 {
00095         bind("limit_", &qlim_);
00096         bind("util_weight_", &util_weight_);
00097         bind_bool("blocked_", &blocked_);
00098         bind_bool("unblock_on_resume_", &unblock_on_resume_);
00099 }
00100 
00101 void Queue::recv(Packet* p, Handler*)
00102 {
00103         double now = Scheduler::instance().clock();
00104         enque(p);
00105         if (!blocked_) {
00106                 /*
00107                  * We're not blocked.  Get a packet and send it on.
00108                  * We perform an extra check because the queue
00109                  * might drop the packet even if it was
00110                  * previously empty!  (e.g., RED can do this.)
00111                  */
00112                 p = deque();
00113                 if (p != 0) {
00114                         utilUpdate(last_change_, now, blocked_);
00115                         last_change_ = now;
00116                         blocked_ = 1;
00117                         target_->recv(p, &qh_);
00118                 }
00119         }
00120 }
00121 
00122 void Queue::utilUpdate(double int_begin, double int_end, int link_state) {
00123 double decay;
00124 
00125         decay = exp(-util_weight_ * (int_end - int_begin));
00126         old_util_ = link_state + (old_util_ - link_state) * decay;
00127 
00128 }
00129 
00130 double Queue::utilization(void) 
00131 {
00132         double now = Scheduler::instance().clock();
00133         
00134         utilUpdate(last_change_, now, blocked_);
00135         last_change_ = now;
00136 
00137         return old_util_;
00138                         
00139 }
00140 
00141 void Queue::updateStats(int queuesize)
00142 {
00143         double now = Scheduler::instance().clock();
00144         double newtime = now - total_time_;
00145         if (newtime > 0.0) {
00146                 double oldave = true_ave_;
00147                 double oldtime = total_time_;
00148                 double newtime = now - total_time_;
00149                 true_ave_ = (oldtime * oldave + newtime * queuesize) /now;
00150                 total_time_ = now;
00151         }
00152 }
00153 
00154 void Queue::resume()
00155 {
00156         double now = Scheduler::instance().clock();
00157         Packet* p = deque();
00158         if (p != 0) {
00159                 target_->recv(p, &qh_);
00160         } else {
00161                 if (unblock_on_resume_) {
00162                         utilUpdate(last_change_, now, blocked_);
00163                         last_change_ = now;
00164                         blocked_ = 0;
00165                 }
00166                 else {
00167                         utilUpdate(last_change_, now, blocked_);
00168                         last_change_ = now;
00169                         blocked_ = 1;
00170                 }
00171         }
00172 }
00173 
00174 void Queue::reset()
00175 {
00176         Packet* p;
00177         total_time_ = 0.0;
00178         true_ave_ = 0.0;
00179         while ((p = deque()) != 0)
00180                 drop(p);
00181 }

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