timers.cc

Go to the documentation of this file.
00001 //
00002 // timers.cc       : Timer Management Class
00003 // authors         : John Heidemann, Fabio Silva and Alefiya Hussain 
00004 //
00005 // Copyright (C) 2000-2002 by the University of Southern California
00006 // $Id: timers.cc,v 1.4 2005/09/13 04:53:50 tomh 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 // Linking this file statically or dynamically with other modules is making
00022 // a combined work based on this file.  Thus, the terms and conditions of
00023 // the GNU General Public License cover the whole combination.
00024 //
00025 // In addition, as a special exception, the copyright holders of this file
00026 // give you permission to combine this file with free software programs or
00027 // libraries that are released under the GNU LGPL and with code included in
00028 // the standard release of ns-2 under the Apache 2.0 license or under
00029 // otherwise-compatible licenses with advertising requirements (or modified
00030 // versions of such code, with unchanged license).  You may copy and
00031 // distribute such a system following the terms of the GNU GPL for this
00032 // file and the licenses of the other code concerned, provided that you
00033 // include the source code of that other code when and as the GNU GPL
00034 // requires distribution of source code.
00035 //
00036 // Note that people who make modified versions of this file are not
00037 // obligated to grant this special exception for their modified versions;
00038 // it is their choice whether to do so.  The GNU General Public License
00039 // gives permission to release a modified version without this exception;
00040 // this exception also makes it possible to release a modified version
00041 // which carries forward this exception.
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 #include "timers.hh"
00047 
00048 // Creates the Timer Management class. Creates the eventqueue The
00049 // eventqueue is used by the Timer class only.  Use the nextTimer and
00050 // executeNextTimer functions to access the event queue
00051 
00052 TimerManager::TimerManager()
00053 {
00054   struct timeval tv;
00055 
00056   // Initialize basic stuff
00057   next_handle_ = 1;
00058   GetTime(&tv);
00059   SetSeed(&tv);
00060 
00061   // Initialize event queue
00062 #ifdef NS_DIFFUSION
00063   eq_ = new DiffEventQueue(this);
00064 #else
00065   eq_ = new EventQueue;
00066 #endif // NS_DIFFUSION
00067 
00068 #ifdef USE_THREADS
00069   queue_mtx_ = new pthread_mutex_t;
00070   pthread_mutex_init(queue_mtx_, NULL);
00071 #endif // USE_THREADS
00072 }
00073 
00074 // This function adds a timer to the event queue. The timeout provided
00075 // should be in milliseconds. cb specifies the function that will be
00076 // called.
00077 
00078 handle TimerManager::addTimer(int timeout, TimerCallback *cb)
00079 {
00080   TimerEntry *entry;
00081 
00082 #ifdef USE_THREADS
00083   pthread_mutex_lock(queue_mtx_);
00084 #endif // USE_THREADS
00085   entry = new TimerEntry(next_handle_, timeout, cb);
00086   eq_->eqAddAfter(next_handle_, entry, timeout);
00087   next_handle_++;
00088 
00089 #ifdef USE_THREADS
00090   pthread_mutex_unlock(queue_mtx_);
00091 #endif // USE_THREADS
00092   return entry->hdl_;
00093 }
00094 
00095 // Applications can use this function to remove from the eventqueue a
00096 // previously scheduled timer (the handle should be the one returned
00097 // by the AddTimer function)
00098 
00099 bool TimerManager::removeTimer(handle hdl)
00100 {
00101 #ifdef NS_DIFFUSION
00102   if (eq_->eqRemove(hdl) == false){
00103     fprintf(stderr, "Error: Can't remove event from queue !\n");
00104     return false;
00105   }
00106   return true;
00107 #else
00108   QueueEvent *e = NULL;
00109   TimerEntry *entry;
00110 
00111 #ifdef USE_THREADS
00112   pthread_mutex_lock(queue_mtx_);
00113 #endif // USE_THREADS
00114 
00115   // Find the timer in the queue
00116   e = eq_->eqFindEvent(hdl);
00117 
00118   // If timer found, remove it from the queue
00119   if (e){
00120     entry = (TimerEntry *) e->payload_;
00121     if (eq_->eqRemove(hdl) == false){
00122       fprintf(stderr, "Error: Can't remove event from queue !\n");
00123       exit(-1);
00124     }
00125 
00126     // Call the application provided delete function
00127 
00128     delete entry;
00129     delete e;
00130   }
00131   else{
00132 #ifdef USE_THREADS
00133     pthread_mutex_unlock(queue_mtx_);
00134 #endif // USE_THREADS
00135     return false;
00136   }
00137 
00138 #ifdef USE_THREADS
00139   pthread_mutex_unlock(queue_mtx_);
00140 #endif // USE_THREADS
00141   return true;
00142 #endif // NS_DIFFUSION
00143 }
00144 
00145 // Returns the expiration value for the first timer on the queue
00146 void TimerManager::nextTimerTime(struct timeval *tv)
00147 {
00148 #ifdef USE_THREADS
00149   pthread_mutex_lock(queue_mtx_);
00150 #endif // USE_THREADS
00151   eq_->eqNextTimer(tv);
00152 #ifdef USE_THREADS
00153   pthread_mutex_unlock(queue_mtx_);
00154 #endif // USE_THREADS
00155 }
00156 
00157 // Executes the first timer callback in the queue 
00158 #ifdef NS_DIFFUSION
00159 void TimerManager::diffTimeout(DiffEvent *e)
00160 {
00161   TimerEntry *entry = (TimerEntry *) e->payload();
00162 
00163   // run it
00164   int new_timeout = entry->cb_->expire();
00165 
00166   if (new_timeout >= 0){
00167     if (new_timeout > 0){
00168       // Change the timer's timeout
00169       entry->timeout_ = new_timeout;
00170     }
00171     eq_->eqAddAfter(entry->hdl_, (TimerEntry *) entry, entry->timeout_);
00172   }
00173   else{
00174     delete entry;
00175   }
00176   delete e;
00177 }
00178 #else
00179 void TimerManager::executeNextTimer()
00180 {
00181 #ifdef USE_THREADS
00182   pthread_mutex_lock(queue_mtx_);
00183 #endif // USE_THREADS
00184   QueueEvent *e = eq_->eqPop();
00185   TimerEntry *entry = (TimerEntry *) e->payload_;
00186 
00187 #ifdef USE_THREADS
00188   pthread_mutex_unlock(queue_mtx_);
00189 #endif // USE_THREADS
00190   // run it
00191   int new_timeout = entry->cb_->expire();
00192 
00193   if (new_timeout >= 0){
00194     if (new_timeout > 0){
00195       // Change the timer's timeout
00196       entry->timeout_ = new_timeout;
00197     }
00198 #ifdef USE_THREADS
00199     pthread_mutex_lock(queue_mtx_);
00200 #endif // USE_THREADS
00201     eq_->eqAddAfter(entry->hdl_, (TimerEntry *) entry, entry->timeout_);
00202 #ifdef USE_THREADS
00203     pthread_mutex_unlock(queue_mtx_);
00204 #endif // USE_THREADS
00205   }
00206   else{
00207     delete entry;
00208   }
00209   delete e;
00210 }
00211 
00212 void TimerManager::executeAllExpiredTimers()
00213 {
00214   struct timeval tv;
00215 
00216   // Get next timer's timeout
00217   nextTimerTime(&tv);
00218 
00219   // Remove all expired timers from the top of the queue, calling
00220   // expire() for each one of them
00221   while (tv.tv_sec == 0 && tv.tv_usec == 0){
00222     // Timer at the head of the queue has expired
00223     executeNextTimer();
00224     nextTimerTime(&tv);
00225   }
00226 }
00227 #endif // NS_DIFFUSION

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