libassa 3.5.0
|
00001 // -*- c++ -*- 00002 //------------------------------------------------------------------------------ 00003 // TimerQueue.cpp 00004 //------------------------------------------------------------------------------ 00005 // Copyright (c) 2000,2005 by Vladislav Grinchenko 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Library General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2 of the License, or (at your option) any later version. 00011 // 00012 //------------------------------------------------------------------------------ 00013 // Created: 07/28/99 00014 //------------------------------------------------------------------------------ 00015 00016 #include "assa/TimerQueue.h" 00017 using namespace ASSA; 00018 00019 TimerQueue:: 00020 ~TimerQueue () 00021 { 00022 trace_with_mask("TimerQueue::~TimerQueue",REACTTRACE); 00023 00024 while (m_queue.size ()) { 00025 delete m_queue.pop (); 00026 } 00027 } 00028 00029 int 00030 TimerQueue:: 00031 remove (EventHandler* eh_) 00032 { 00033 // Like STL iterators, after deletion of an element, 00034 // queue structure and indexing might drastically change 00035 // and there is no guarantee that elements we haven't seen 00036 // yet will not be moved past the iterator. Therefore, 00037 // we must start scanning from the beginning after each deletion :-( 00038 00039 trace_with_mask("TimerQueue::remove(eh_)",REACTTRACE); 00040 00041 register size_t i; 00042 int cnt = 0; 00043 bool f = true; // changed flag 00044 register Timer* tmr; 00045 00046 DL((REACT,"Searching for Timer: 0x%x\n", dynamic_cast<void*> (eh_))); 00047 00048 while (f) { 00049 f = false; 00050 DL((REACT,"Queue size: %d\n", m_queue.size())); 00051 for (i = 0; i < m_queue.size (); i++) { 00052 if (m_queue[i]->getHandler() == eh_) { 00053 DL((REACT,"Found Timer: 0x%x in slot: %d\n", 00054 dynamic_cast<void*>(eh_), i)); 00055 tmr = m_queue[i]; 00056 m_queue.remove (tmr); 00057 delete tmr; 00058 cnt++; 00059 f = true; 00060 } 00061 } 00062 } 00063 return cnt; 00064 } 00065 00066 bool 00067 TimerQueue:: 00068 remove (TimerId tid_) 00069 { 00070 trace_with_mask("TimerQueue::remove(tid)",REACTTRACE); 00071 register size_t i; 00072 00073 DL((REACTTRACE,"Queue size before remove: %d\n", m_queue.size())); 00074 00075 for (i = 0; i < m_queue.size (); i++) { 00076 if (m_queue[i] == (Timer*) tid_) { 00077 Timer* tmr = m_queue[i]; 00078 int ret = m_queue.remove (tmr); 00079 delete tmr; 00080 DL((REACTTRACE,"Queue size after remove: %d\n", m_queue.size())); 00081 return ret; 00082 } 00083 } 00084 return false; 00085 } 00086 00087 int 00088 TimerQueue:: 00089 expire (const TimeVal& tv_) 00090 { 00091 trace_with_mask("TimerQueue::expire",REACTTRACE); 00092 00093 register Timer* tp = (Timer*) NULL; 00094 register int cnt = 0; 00095 00096 while (m_queue.size () && (tp = m_queue.top ()) != (Timer*) NULL) { 00097 if (tp->getExpirationTime () > tv_) { 00098 DL((REACT,"Top timer:\n")); 00099 tp->dump (); 00100 break; 00101 } 00102 /* First, pop item from the queue. Then call an appropriate 00103 EventHandler. If done in reverse, EventHandler might 00104 remove item first and then pop () will fail 00105 (This needs more investigation!). 00106 */ 00107 m_queue.pop (); 00108 00109 DL((REACT,"Expired %s [t=%s] timer!\n", 00110 tp->get_id ().c_str (), 00111 tp->getExpirationTime ().fmtString ().c_str ())); 00112 00113 int ret = tp->getHandler ()->handle_timeout ((TimerId) tp); 00114 00118 if (ret == 1) { 00119 tp->rescheduleExpirationTime (); 00120 m_queue.insert (tp); 00121 } 00122 else { 00123 delete tp; 00124 tp = (Timer*)NULL; 00125 } 00126 cnt++; 00127 } 00128 00129 if (cnt) { 00130 DL((TRACE,"Expired total of %d timer(s).\n",cnt)); 00131 } 00132 00133 return cnt; 00134 } 00135 00136 TimerId 00137 TimerQueue:: 00138 insert (EventHandler* eh_, 00139 const TimeVal& tv_, 00140 const TimeVal& delta_, 00141 const std::string& name_) 00142 { 00143 trace("TimerQueue::insert"); 00144 00145 Timer* t = new Timer (eh_, tv_, delta_, name_); 00146 m_queue.insert (t); 00147 return (TimerId) t; 00148 } 00149 00150 void 00151 TimerQueue:: 00152 dump (void) 00153 { 00154 trace("TimerQueue::dump"); 00155 00156 if (m_queue.size() == 0) { 00157 DL((REACT,"Queue is empty\n")); 00158 } 00159 else { 00160 for (size_t i = 0; i < m_queue.size (); ) { 00161 m_queue[i++]->dump(); 00162 } 00163 } 00164 }