00001 /* 00002 * timer.cpp 00003 * 00004 * Copyright (c) 2009 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * Implementation of a simple timer queue. See timer.h 00031 */ 00032 00033 // includes -------------------------------------------------------------------- 00034 #include "timer.h" // always include our own header first 00035 00036 #include <fstream> 00037 00038 #include "common/wave_ex.h" 00039 #include "perf/perf.h" 00040 #include "util/token_stream.h" 00041 00042 00043 namespace timer { 00044 00045 /// \ingroup timer 00046 /*@{*/ 00047 00048 00049 // interface destructors 00050 Timer::~Timer(void) throw() { } 00051 Queue::~Queue(void) throw() { } 00052 00053 00054 //////////////////////////////////////////////////////////////////////////////// 00055 // 00056 // static helper methods 00057 // 00058 //////////////////////////////////////////////////////////////////////////////// 00059 00060 00061 //////////////////////////////////////////////////////////////////////////////// 00062 // 00063 // QImpl -- class that implements the timer::Queue interface 00064 // 00065 //////////////////////////////////////////////////////////////////////////////// 00066 00067 class QImpl : public Queue { 00068 public: 00069 // constructor, destructor --------------------------------------------- 00070 QImpl(void) throw(); 00071 ~QImpl(void) throw() { } 00072 00073 // public class methods ------------------------------------------------ 00074 void initialize(void) throw() { } 00075 00076 // timer::Queue class interface methods -------------------------------- 00077 void addTimer(IN qword_t microseconds, 00078 IN smart_ptr<Timer>& timer); 00079 void setTime(IN qword_t usSinceEpoch) throw(); 00080 void checkTimers(IN qword_t usSinceEpoch); 00081 00082 private: 00083 // private typedefs ---------------------------------------------------- 00084 typedef std::multimap<qword_t, smart_ptr<Timer> > timer_map_t; 00085 00086 // private member data ------------------------------------------------- 00087 smart_mutex m_mutex; 00088 qword_t m_currentTime; 00089 timer_map_t m_timerMap; 00090 }; 00091 00092 00093 00094 QImpl::QImpl(void) 00095 throw() 00096 { 00097 m_currentTime = 0; 00098 } 00099 00100 00101 00102 void 00103 QImpl::addTimer 00104 ( 00105 IN qword_t microseconds, 00106 IN smart_ptr<Timer>& timer 00107 ) 00108 { 00109 ASSERT(timer, "null"); 00110 qword_t alarmTime = m_currentTime + microseconds; 00111 00112 // lock! 00113 mlock m(m_mutex); 00114 m_timerMap.insert(timer_map_t::value_type(alarmTime, timer)); 00115 } 00116 00117 00118 00119 void 00120 QImpl::setTime 00121 ( 00122 IN qword_t usSinceEpoch 00123 ) 00124 throw() 00125 { 00126 m_currentTime = usSinceEpoch; 00127 } 00128 00129 00130 00131 void 00132 QImpl::checkTimers 00133 ( 00134 IN qword_t usSinceEpoch 00135 ) 00136 { 00137 // update time (can do this outside mutex) 00138 this->setTime(usSinceEpoch); 00139 00140 // lock! 00141 mlock m(m_mutex); 00142 00143 // iterate over all timers up to current time 00144 while (true) { 00145 timer_map_t::iterator i = m_timerMap.begin(); 00146 if (m_timerMap.end() == i) 00147 return; // end of map! 00148 00149 qword_t qTime = i->first; 00150 if (qTime > usSinceEpoch) 00151 return; // remaining timers are later 00152 00153 // timer is up! notify 00154 Timer * timer = i->second; 00155 ASSERT(timer, "null"); 00156 timer->notifyTimer(); 00157 00158 // remove timer from queue 00159 m_timerMap.erase(i); 00160 } 00161 } 00162 00163 00164 00165 //////////////////////////////////////////////////////////////////////////////// 00166 // 00167 // Public APIs 00168 // 00169 //////////////////////////////////////////////////////////////////////////////// 00170 00171 smart_ptr<Queue> 00172 Queue::create 00173 ( 00174 void 00175 ) 00176 { 00177 smart_ptr<QImpl> local = new QImpl; 00178 ASSERT(local, "out of memory"); 00179 00180 local->initialize(); 00181 00182 return local; 00183 } 00184 00185 00186 00187 }; // timer namespace 00188