dvander@592: /** dvander@592: * vim: set ts=4 : dvander@592: * =============================================================== dvander@592: * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. dvander@592: * =============================================================== dvander@592: * dvander@592: * This file is not open source and may not be copied without explicit dvander@592: * written permission of AlliedModders LLC. This file may not be redistributed dvander@592: * in whole or significant part. dvander@592: * For information, see LICENSE.txt or http://www.sourcemod.net/license.php dvander@592: * dvander@592: * Version: $Id$ dvander@592: */ dvander@592: dvander@592: #include "TimerSys.h" dvander@592: dvander@616: TimerSystem g_Timers; dvander@592: dvander@592: void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags) dvander@592: { dvander@592: m_Listener = pCallbacks; dvander@592: m_Interval = fInterval; dvander@592: m_ToExec = fToExec; dvander@592: m_pData = pData; dvander@592: m_Flags = flags; dvander@592: m_InExec = false; dvander@592: m_KillMe = false; dvander@592: } dvander@592: dvander@616: void TimerSystem::OnSourceModAllInitialized() dvander@592: { dvander@592: g_ShareSys.AddInterface(NULL, this); dvander@592: } dvander@592: dvander@616: void TimerSystem::RunFrame() dvander@592: { dvander@592: ITimer *pTimer; dvander@592: TimerIter iter; dvander@592: dvander@592: for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); ) dvander@592: { dvander@592: pTimer = (*iter); dvander@592: if (gpGlobals->curtime >= pTimer->m_ToExec) dvander@592: { dvander@592: pTimer->m_InExec = true; dvander@592: pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData); faluco@612: pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData); dvander@592: iter = m_SingleTimers.erase(iter); dvander@592: m_FreeTimers.push(pTimer); dvander@592: } else { dvander@592: break; dvander@592: } dvander@592: } dvander@592: dvander@592: ResultType res; dvander@592: for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); ) dvander@592: { dvander@592: pTimer = (*iter); dvander@592: if (gpGlobals->curtime >= pTimer->m_ToExec) dvander@592: { dvander@592: pTimer->m_InExec = true; dvander@592: res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData); dvander@592: if (pTimer->m_KillMe || (res == Pl_Stop)) dvander@592: { dvander@592: pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData); dvander@592: iter = m_LoopTimers.erase(iter); dvander@592: m_FreeTimers.push(pTimer); dvander@592: continue; dvander@592: } dvander@592: pTimer->m_InExec = false; dvander@592: pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval; dvander@592: } dvander@592: iter++; dvander@592: } dvander@592: dvander@592: m_LastExecTime = gpGlobals->curtime; dvander@592: } dvander@592: dvander@616: ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags) dvander@592: { dvander@592: ITimer *pTimer; dvander@592: TimerIter iter; dvander@592: float to_exec = gpGlobals->curtime + fInterval; dvander@592: dvander@592: if (m_FreeTimers.empty()) dvander@592: { dvander@592: pTimer = new ITimer; dvander@592: } else { dvander@592: pTimer = m_FreeTimers.front(); dvander@592: m_FreeTimers.pop(); dvander@592: } dvander@592: dvander@592: pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags); dvander@592: dvander@592: if (flags & TIMER_FLAG_REPEAT) dvander@592: { dvander@592: m_LoopTimers.push_back(pTimer); dvander@592: goto return_timer; dvander@592: } dvander@592: dvander@592: if (m_SingleTimers.size() >= 1) dvander@592: { dvander@592: iter = --m_SingleTimers.end(); dvander@592: if ((*iter)->m_ToExec <= to_exec) dvander@592: { dvander@592: goto insert_end; dvander@592: } dvander@592: } dvander@592: dvander@592: for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++) dvander@592: { dvander@592: if ((*iter)->m_ToExec >= to_exec) dvander@592: { dvander@592: m_SingleTimers.insert(iter, pTimer); dvander@592: goto return_timer; dvander@592: } dvander@592: } dvander@592: dvander@592: insert_end: dvander@592: m_SingleTimers.push_back(pTimer); dvander@592: dvander@592: return_timer: dvander@592: return pTimer; dvander@592: } dvander@592: dvander@616: void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec) dvander@592: { dvander@592: ResultType res; dvander@592: dvander@592: if (pTimer->m_InExec) dvander@592: { dvander@592: return; dvander@592: } dvander@592: dvander@592: pTimer->m_InExec = true; dvander@592: res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData); dvander@592: dvander@592: if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT)) dvander@592: { dvander@592: pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData); dvander@592: m_SingleTimers.remove(pTimer); dvander@592: m_FreeTimers.push(pTimer); dvander@592: } else { faluco@612: if ((res != Pl_Stop) && !pTimer->m_KillMe) dvander@592: { faluco@612: if (delayExec) faluco@612: { faluco@612: pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval; faluco@612: } dvander@592: pTimer->m_InExec = false; dvander@592: return; dvander@592: } dvander@592: pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData); dvander@592: m_LoopTimers.remove(pTimer); dvander@592: m_FreeTimers.push(pTimer); dvander@592: } dvander@592: } dvander@592: dvander@616: void TimerSystem::KillTimer(ITimer *pTimer) dvander@592: { dvander@592: TimerList *pList; dvander@592: dvander@592: if (pTimer->m_KillMe) dvander@592: { dvander@592: return; dvander@592: } dvander@592: dvander@592: if (pTimer->m_InExec) dvander@592: { dvander@592: pTimer->m_KillMe = true; dvander@592: return; dvander@592: } dvander@592: dvander@592: pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */ dvander@592: pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData); dvander@592: dvander@592: pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers; dvander@592: dvander@592: pList->remove(pTimer); dvander@592: m_FreeTimers.push(pTimer); dvander@592: } dvander@592: dvander@616: void TimerSystem::MapChange() dvander@592: { dvander@592: ITimer *pTimer; dvander@592: TimerIter iter; dvander@592: dvander@592: for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++) dvander@592: { dvander@592: pTimer = (*iter); dvander@592: pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime; dvander@592: } dvander@592: dvander@592: for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++) dvander@592: { dvander@592: pTimer = (*iter); dvander@592: pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime; dvander@592: } dvander@592: }