00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <bogotel/portability.h>
00011 #include <bogotel/Timer.h>
00012 #include <bogotel/Util.h>
00013 #include <bogotel/DevBase.h>
00014 #include <bogotel/TimerTarget.h>
00015
00016 #include <boost/thread/xtime.hpp>
00017
00018 #include <log4cpp/NDC.hh>
00019
00021
00023
00024 namespace bogotel {
00025
00026 CTimer::CTimer(int period) :
00027 m_period(period),
00028 m_bStop(false)
00029 {
00030 m_pThrd = new boost::thread(thread_adapter(&CTimer::do_thread, this));
00031 }
00032
00033 CTimer::~CTimer()
00034 {
00035 m_bStop = true;
00036 m_condStop.notify_one();
00037 m_pThrd->join();
00038 delete m_pThrd;
00039 }
00040
00041 void CTimer::do_thread(void* param)
00042 {
00043 log4cpp::NDC::push("CTimer");
00044 try {
00045 static_cast<CTimer*>(param)->run();
00046 } catch (std::exception& e) {
00047 g_util->log(1, -1, "CTimer::do_thread: Exception %s", e.what());
00048 } catch (char *p) {
00049 g_util->log(1, -1, "CTimer::do_thread: Exception %s", p);
00050 } catch (...) {
00051 g_util->log(1, -1, "CTimer::do_thread: Exception");
00052 }
00053 }
00054
00055 void CTimer::run()
00056 {
00057 boost::xtime xt;
00058 boost::mutex::scoped_lock lock(m_mtxStop);
00059
00060 do {
00061 handleDefunctTargets();
00062 checkForExpirations();
00063 boost::xtime_get(&xt, boost::TIME_UTC);
00064 xt.nsec += m_period * 1000000;
00065 } while (! m_condStop.timed_wait(lock, xt, cond_predicate(m_bStop, true)));
00066 }
00067
00068 void CTimer::checkForExpirations()
00069 {
00070 char method[] = "CTimer::checkForExpirations";
00071
00072 boost::mutex::scoped_lock lock(m_mtxTimerInfoList);
00073 LST_TIMER::iterator i = m_lstTimer.begin();
00074
00075 while (i != m_lstTimer.end()) {
00076 assert(m_lstTimer.begin() != m_lstTimer.end());
00077
00078 timer_info* pTimerInfo = (*i);
00079
00080 if (pTimerInfo->m_count < 0) {
00081
00082
00083
00084
00085
00087 if (targetIsActive(pTimerInfo->m_lTargetId)) {
00088 g_util->log(9, -1, "%s: Expired timer. target %s", method,
00089 pTimerInfo->m_pTarget->toString().c_str());
00090 if (pTimerInfo->m_lTargetId != pTimerInfo->m_pTarget->getId()) {
00091 g_util->log(3, -1, "%s: Timer doesn't match target. timer has id:%d, "
00092 "target id:%d", method, pTimerInfo->m_lTargetId,
00093 pTimerInfo->m_pTarget->getId());
00094 }
00095 pTimerInfo->m_pTarget->timerExpired(pTimerInfo->m_iTimerType,
00096 pTimerInfo->m_iTargetStateId);
00097 }
00098
00099 i = m_lstTimer.erase(i);
00100 g_util->log(9, -1, "%s: Deleting timer_info %s", method,
00101 pTimerInfo->toString().c_str());
00102 delete pTimerInfo;
00103
00104 } else {
00105 pTimerInfo->m_count--;
00106 i++;
00107 }
00108 }
00109 }
00110
00111 bool CTimer::targetIsActive(long lTimerId)
00112 {
00113 boost::mutex::scoped_lock lock2(m_mtxActiveTimerSet);
00114 return m_setActive.find(lTimerId) != m_setActive.end();
00115 }
00116
00122 void CTimer::handleDefunctTargets()
00123 {
00124 char method[] = "CTimer::handleDefunctTargets";
00125 boost::mutex::scoped_lock lock1(m_mtxDefunctVec);
00126 boost::mutex::scoped_lock lock2(m_mtxActiveTimerSet);
00127
00128 for (VEC_TIMERTARGET::reverse_iterator iter = m_vecDefunct.rbegin();
00129 iter != m_vecDefunct.rend();
00130 iter++) {
00131
00132 CTimerTarget* pTarget = (*iter);
00133
00134 g_util->log(9, -1, "%s: Removing target %s", method,
00135 pTarget->toString().c_str());
00136
00137
00138 if (m_setActive.erase(pTarget->getId()) == 0) {
00139 g_util->log(3, -1, "%s: target didn't exist in active list.", method);
00140 }
00141
00142 delete pTarget;
00143 }
00144 m_vecDefunct.clear();
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void CTimer::add(long lDelay, CTimerTarget *pTarget, int timerType, int stateId) {
00154
00155 char method[] = "CTimer::add";
00156
00157 timer_info* pTimerInfo;
00158
00159 int numPeriods = lDelay / m_period;
00160
00161 assert(numPeriods > 0);
00162
00163 pTimerInfo = new timer_info(numPeriods, pTarget, timerType, stateId);
00164
00165 g_util->log(9, -1, "%s: timer_info %s", method, pTimerInfo->toString().c_str());
00166
00167 if (pTimerInfo->m_pTarget != NULL) {
00168 boost::mutex::scoped_lock lock(m_mtxTimerInfoList);
00169
00170 m_lstTimer.push_back(pTimerInfo);
00171 m_lstTimer.sort();
00172 }
00173 }
00174
00175 int CTimer::registerTarget(CTimerTarget *pTarget)
00176 {
00177 char method[] = "CTimer::registerTarget";
00178 g_util->log(9, -1, "%s: target %s", method, pTarget->toString().c_str());
00179
00180 std::pair<SET_LONG::const_iterator,bool> rv;
00181 {
00182 boost::mutex::scoped_lock lock(m_mtxActiveTimerSet);
00183 rv = m_setActive.insert(pTarget->getId());
00184 }
00185 if (! rv.second) {
00186 g_util->log(3, -1, "%s: already registered. Target: %s", method, pTarget->toString().c_str());
00187 return resultFUNC_BAD_PARAMETER;
00188 }
00189 return resultSUCCESS;
00190 }
00191
00192 void CTimer::requestTargetDeletion(CTimerTarget *pTarget)
00193 {
00194 char method[] = "CTimer::requestTargetDeletion";
00195 g_util->log(9, -1, "%s: target: %s", method, pTarget->toString().c_str());
00196 boost::mutex::scoped_lock lock(m_mtxDefunctVec);
00197 m_vecDefunct.push_back(pTarget);
00198 }
00199
00201
00203
00204 timer_info::timer_info(int count, CTimerTarget* pTarget, int timerType, int targetStateId) :
00205 m_pTarget(pTarget),
00206 m_count(count),
00207 m_iTimerType(timerType),
00208 m_iTargetStateId(targetStateId),
00209 m_lTargetId(pTarget->getId())
00210 {}
00211
00212 std::string timer_info::toString()
00213 {
00214 std::ostringstream str;
00215 str << "target id:" << m_lTargetId;
00216 return str.str();
00217 }
00218
00219 }