📄 wartimer.cpp
字号:
#include "StdAfx.h"#include "WarTimer.h" // class implemented#ifndef WAR_AUTO_LOCK_H# include "WarAutoLock.h"#endif#ifndef WAR_SHUTDOWN_ENGINE_H# include "WarShutdownEngine.h"#endif#ifndef WAR_LOG# include "WarLog.h"#endif#ifndef WAR_TIMER_EVENT_TASK_H# include "WarTimerEventTask.h"#endif#define AUTO_LOCK WarAutoLock MyLock(mLock);/////////////////////////////// PUBLIC ///////////////////////////////////////WarTimer *WarTimer::spThis = NULL;//============================= LIFECYCLE ====================================WarTimer::WarTimer(): mSignal(true){ mPool.Create(5,10); if (!spThis) spThis = this;}// WarTimerWarTimer::~WarTimer(){ if (spThis == this) spThis = NULL;}// ~WarTimer//============================= OPERATORS ====================================//============================= OPERATIONS ===================================void WarTimer::OnShutdown(war_cptr_t ptr){ WarLog sys_log(WARLOG_SYSTEM, "WarTimer::OnShutdown()"); sys_log << "Shutting down the internal timer." << war_endl; ((WarTimer *)ptr)->SetExitFlag(); while(WarTimer::IsTimerActive()) { ((WarTimer *)ptr)->mSignal.Signal(); WarTime::Sleep(100); }}void WarTimer::AddEvent(war_timer_event_ptr_t& newEvent)throw(WarException){ assert(this != NULL); // Must start the timer! AUTO_LOCK if (!IsActive()) WarThrow(WarError(WAR_ERR_ABORT_THREAD), NULL); events_t::const_iterator P = mEvents.insert(newEvent); if (P == mEvents.begin()) { // Signal the timer-thread so that it can wake up and // process the event. mSignal.Signal(); }}void WarTimer::KillEvent(war_timer_event_ptr_t& oldEvent)throw(WarException){ AUTO_LOCK for(events_t::iterator P = mEvents.begin() ; P != mEvents.end() ; ++P) { if (P->IsSameObject(oldEvent)) { if (P == mEvents.begin()) { // Signal the timer-thread so that it can wake up and // reschedule the next event mSignal.Signal(); } (*P)->Kill(); mEvents.erase(P); break; } }}void WarTimer::SetExitFlag(){ AUTO_LOCK WarThread::SetExitFlag(); mSignal.Signal();}//============================= ACCESS ===================================WarTimer& WarTimer::GetTimer() throw(WarException){ if (NULL == spThis) WarThrow(WarError(WAR_ERR_INTERNAL_DATA_NOT_INITIALIZED), NULL); return *spThis;}//============================= INQUIRY ===================================/////////////////////////////// PROTECTED ///////////////////////////////////void WarTimer::Run(){ WarLog log_error(WARLOG_ERROR, "WarTimer::Run()"); WarLog thrd_log(WARLOG_THREADS, "WarTimer::Run()"); WarShutdownEngine::GetEngine().AddEvent(OnShutdown, this); war_time_t next_time; war_timer_event_ptr_t my_event; thrd_log << "Timer is running" << war_endl; SetState(STATE_IDLE); while(!IsExiting()) { SetState(STATE_BUSY); next_time = WarThreadEvent::WAIT_INFINITE; my_event = NULL; { AUTO_LOCK if (!mEvents.empty()) { next_time = (*mEvents.begin())->GetTime().GetTimeDiff(); if (next_time > 0) goto sleep; // Unlock my_event = (*mEvents.begin()); mEvents.erase(mEvents.begin()); goto process_it; // Unlock } }sleep: assert(my_event.IsEmpty()); SetState(STATE_IDLE); mSignal.WaitForEvent(next_time); continue;process_it: assert(my_event.IsEmpty() == false); WarTimerEvent& revent = *my_event; try { if (thrd_log) { thrd_log << "Timer is processing event: " << revent.Explain(); } if (revent.IsFast()) { // Do it now. revent.DoTimer(); OnCompleted(my_event); } else // Add to queue, another thread will take care of it. { war_timer_ptr_t my_timer_ptr = this; mPool.PushTask(new WarTimerEventTask(my_event, my_timer_ptr)); } } catch(WarException& e) { log_error << "Caught unexcpected exception from DoTimer(). " << e.Explain() << war_endl; } #if WAR_CATCH_ALL catch(...) { log_error << "Caught unknown exception from DoTimer().", NULL); continue; }#endif } SetState(STATE_QUITTING); // Avoid dead-lock, other thearde may poll on this pointer, waiting for it to // be NULL, while keeping a reference to us... if (spThis == this) spThis = NULL;}void WarTimer::OnCompleted(war_timer_event_ptr_t& my_event){ WarTimerEvent& revent = *my_event; WarTime next_time; switch(revent.GetType()) { case WarTimerEvent::TIMER_ONCE: return; case WarTimerEvent::TIMER_LOOP_RELATIVE: next_time.mTime += revent.GetDelay(); break; case WarTimerEvent::TIMER_LOOP_ABSOLUTE: next_time.mTime = revent.mTime.mTime + revent.GetDelay(); break; } assert(revent.GetDelay() > 0); revent.SetTime(next_time); if (revent.IsFast()) { AUTO_LOCK mEvents.insert(my_event); } else AddEvent(my_event);}/////////////////////////////// PRIVATE ///////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -