Main Page   Namespace List   Class Hierarchy   Data Structures   File List   Namespace Members   Data Fields   Globals   Related Pages  

Timer.cpp

Go to the documentation of this file.
00001 /*
00002  * Timer.cpp
00003  *
00004  * Copyright 2003, MobileSpear Inc. (www.mobilespear.com). All rights reserved.
00005  * Copyright 2003, David Resnick. All rights reserved.
00006  *
00007  * See the file doc\license.txt for the terms of usage and distribution.
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 // CTimer
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                 // Check if the timer target is still active.
00083                 // This is done only when its timer expires because
00084                 // doing it (searching the set of active targets) every time 
00085                 // for each timer is potentially much more expensive in time.
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             // remove from active list
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             // destroy timer target
00142             delete pTarget;
00143         }
00144         m_vecDefunct.clear();
00145     }
00146 
00147     /*
00148      *  Create a timer_info structure for ADlgcDev (d).
00149      *  Set timer_info.Count to d.m_delay / Period.
00150      *  
00151      *  Add the timer_info structure to the ordered TimerList.
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     // timer_info
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 }

Generated on Tue Aug 12 12:41:30 2003 for bogotel by doxygen 1.3. Hosted by SourceForge.net Logo