1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/TimerSys.cpp Sat Mar 10 21:26:04 2007 +0000
1.3 @@ -0,0 +1,199 @@
1.4 +/**
1.5 +* vim: set ts=4 :
1.6 +* ===============================================================
1.7 +* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.8 +* ===============================================================
1.9 +*
1.10 +* This file is not open source and may not be copied without explicit
1.11 +* written permission of AlliedModders LLC. This file may not be redistributed
1.12 +* in whole or significant part.
1.13 +* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
1.14 +*
1.15 +* Version: $Id$
1.16 +*/
1.17 +
1.18 +#include "TimerSys.h"
1.19 +
1.20 +CTimerSystem g_Timers;
1.21 +
1.22 +void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
1.23 +{
1.24 + m_Listener = pCallbacks;
1.25 + m_Interval = fInterval;
1.26 + m_ToExec = fToExec;
1.27 + m_pData = pData;
1.28 + m_Flags = flags;
1.29 + m_InExec = false;
1.30 + m_KillMe = false;
1.31 +}
1.32 +
1.33 +void CTimerSystem::OnSourceModAllInitialized()
1.34 +{
1.35 + g_ShareSys.AddInterface(NULL, this);
1.36 +}
1.37 +
1.38 +void CTimerSystem::RunFrame()
1.39 +{
1.40 + ITimer *pTimer;
1.41 + TimerIter iter;
1.42 +
1.43 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
1.44 + {
1.45 + pTimer = (*iter);
1.46 + if (gpGlobals->curtime >= pTimer->m_ToExec)
1.47 + {
1.48 + pTimer->m_InExec = true;
1.49 + pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.50 + if (pTimer->m_KillMe)
1.51 + {
1.52 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.53 + }
1.54 + iter = m_SingleTimers.erase(iter);
1.55 + m_FreeTimers.push(pTimer);
1.56 + } else {
1.57 + break;
1.58 + }
1.59 + }
1.60 +
1.61 + ResultType res;
1.62 + for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
1.63 + {
1.64 + pTimer = (*iter);
1.65 + if (gpGlobals->curtime >= pTimer->m_ToExec)
1.66 + {
1.67 + pTimer->m_InExec = true;
1.68 + res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.69 + if (pTimer->m_KillMe || (res == Pl_Stop))
1.70 + {
1.71 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.72 + iter = m_LoopTimers.erase(iter);
1.73 + m_FreeTimers.push(pTimer);
1.74 + continue;
1.75 + }
1.76 + pTimer->m_InExec = false;
1.77 + pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.78 + }
1.79 + iter++;
1.80 + }
1.81 +
1.82 + m_LastExecTime = gpGlobals->curtime;
1.83 +}
1.84 +
1.85 +ITimer *CTimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
1.86 +{
1.87 + ITimer *pTimer;
1.88 + TimerIter iter;
1.89 + float to_exec = gpGlobals->curtime + fInterval;
1.90 +
1.91 + if (m_FreeTimers.empty())
1.92 + {
1.93 + pTimer = new ITimer;
1.94 + } else {
1.95 + pTimer = m_FreeTimers.front();
1.96 + m_FreeTimers.pop();
1.97 + }
1.98 +
1.99 + pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
1.100 +
1.101 + if (flags & TIMER_FLAG_REPEAT)
1.102 + {
1.103 + m_LoopTimers.push_back(pTimer);
1.104 + goto return_timer;
1.105 + }
1.106 +
1.107 + if (m_SingleTimers.size() >= 1)
1.108 + {
1.109 + iter = --m_SingleTimers.end();
1.110 + if ((*iter)->m_ToExec <= to_exec)
1.111 + {
1.112 + goto insert_end;
1.113 + }
1.114 + }
1.115 +
1.116 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
1.117 + {
1.118 + if ((*iter)->m_ToExec >= to_exec)
1.119 + {
1.120 + m_SingleTimers.insert(iter, pTimer);
1.121 + goto return_timer;
1.122 + }
1.123 + }
1.124 +
1.125 +insert_end:
1.126 + m_SingleTimers.push_back(pTimer);
1.127 +
1.128 +return_timer:
1.129 + return pTimer;
1.130 +}
1.131 +
1.132 +void CTimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
1.133 +{
1.134 + ResultType res;
1.135 +
1.136 + if (pTimer->m_InExec)
1.137 + {
1.138 + return;
1.139 + }
1.140 +
1.141 + pTimer->m_InExec = true;
1.142 + res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.143 +
1.144 + if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
1.145 + {
1.146 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.147 + m_SingleTimers.remove(pTimer);
1.148 + m_FreeTimers.push(pTimer);
1.149 + } else {
1.150 + if (delayExec && (res != Pl_Stop) && !pTimer->m_KillMe)
1.151 + {
1.152 + pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.153 + pTimer->m_InExec = false;
1.154 + return;
1.155 + }
1.156 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.157 + m_LoopTimers.remove(pTimer);
1.158 + m_FreeTimers.push(pTimer);
1.159 + }
1.160 +}
1.161 +
1.162 +void CTimerSystem::KillTimer(ITimer *pTimer)
1.163 +{
1.164 + TimerList *pList;
1.165 +
1.166 + if (pTimer->m_KillMe)
1.167 + {
1.168 + return;
1.169 + }
1.170 +
1.171 + if (pTimer->m_InExec)
1.172 + {
1.173 + pTimer->m_KillMe = true;
1.174 + return;
1.175 + }
1.176 +
1.177 + pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
1.178 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.179 +
1.180 + pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
1.181 +
1.182 + pList->remove(pTimer);
1.183 + m_FreeTimers.push(pTimer);
1.184 +}
1.185 +
1.186 +void CTimerSystem::MapChange()
1.187 +{
1.188 + ITimer *pTimer;
1.189 + TimerIter iter;
1.190 +
1.191 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
1.192 + {
1.193 + pTimer = (*iter);
1.194 + pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
1.195 + }
1.196 +
1.197 + for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
1.198 + {
1.199 + pTimer = (*iter);
1.200 + pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
1.201 + }
1.202 +}