core/TimerSys.cpp
author Scott Ehlert <ds@alliedmods.net>
Sat Apr 21 17:03:28 2007 +0000 (2007-04-21)
changeset 702 ff520b71249c
parent 673 fc1d50579d06
child 727 fade10824d88
permissions -rw-r--r--
Wow, how did I forget this - exported IMemoryUtils interface
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "TimerSys.h"
    16 
    17 TimerSystem g_Timers;
    18 
    19 void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
    20 {
    21 	m_Listener = pCallbacks;
    22 	m_Interval = fInterval;
    23 	m_ToExec = fToExec;
    24 	m_pData = pData;
    25 	m_Flags = flags;
    26 	m_InExec = false;
    27 	m_KillMe = false;
    28 }
    29 
    30 TimerSystem::~TimerSystem()
    31 {
    32 	CStack<ITimer *>::iterator iter;
    33 	for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++)
    34 	{
    35 		delete (*iter);
    36 	}
    37 	m_FreeTimers.popall();
    38 }
    39 
    40 void TimerSystem::OnSourceModAllInitialized()
    41 {
    42 	g_ShareSys.AddInterface(NULL, this);
    43 }
    44 
    45 void TimerSystem::OnSourceModLevelChange(const char *mapName)
    46 {
    47 	MapChange();
    48 }
    49 
    50 void TimerSystem::RunFrame()
    51 {
    52 	ITimer *pTimer;
    53 	TimerIter iter;
    54 
    55 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
    56 	{
    57 		pTimer = (*iter);
    58 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    59 		{
    60 			pTimer->m_InExec = true;
    61 			pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    62 			pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    63 			iter = m_SingleTimers.erase(iter);
    64 			m_FreeTimers.push(pTimer);
    65 		} else {
    66 			break;
    67 		}
    68 	}
    69 
    70 	ResultType res;
    71 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
    72 	{
    73 		pTimer = (*iter);
    74 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    75 		{
    76 			pTimer->m_InExec = true;
    77 			res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    78 			if (pTimer->m_KillMe || (res == Pl_Stop))
    79 			{
    80 				pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    81 				iter = m_LoopTimers.erase(iter);
    82 				m_FreeTimers.push(pTimer);
    83 				continue;
    84 			}
    85 			pTimer->m_InExec = false;
    86 			pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
    87 		}
    88 		iter++;
    89 	}
    90 
    91 	m_LastExecTime = gpGlobals->curtime;
    92 }
    93 
    94 ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
    95 {
    96 	ITimer *pTimer;
    97 	TimerIter iter;
    98 	float to_exec = gpGlobals->curtime + fInterval;
    99 
   100 	if (m_FreeTimers.empty())
   101 	{
   102 		pTimer = new ITimer;
   103 	} else {
   104 		pTimer = m_FreeTimers.front();
   105 		m_FreeTimers.pop();
   106 	}
   107 
   108 	pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
   109 
   110 	if (flags & TIMER_FLAG_REPEAT)
   111 	{
   112 		m_LoopTimers.push_back(pTimer);
   113 		goto return_timer;
   114 	}
   115 
   116 	if (m_SingleTimers.size() >= 1)
   117 	{
   118 		iter = --m_SingleTimers.end();
   119 		if ((*iter)->m_ToExec <= to_exec)
   120 		{
   121 			goto insert_end;
   122 		}
   123 	}
   124 
   125 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   126 	{
   127 		if ((*iter)->m_ToExec >= to_exec)
   128 		{
   129 			m_SingleTimers.insert(iter, pTimer);
   130 			goto return_timer;
   131 		}
   132 	}
   133 
   134 insert_end:
   135 	m_SingleTimers.push_back(pTimer);
   136 
   137 return_timer:
   138 	return pTimer;
   139 }
   140 
   141 void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
   142 {
   143 	ResultType res;
   144 
   145 	if (pTimer->m_InExec)
   146 	{
   147 		return;
   148 	}
   149 
   150 	pTimer->m_InExec = true;
   151 	res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
   152 
   153 	if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
   154 	{
   155 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   156 		m_SingleTimers.remove(pTimer);
   157 		m_FreeTimers.push(pTimer);
   158 	} else {
   159 		if ((res != Pl_Stop) && !pTimer->m_KillMe)
   160 		{
   161 			if (delayExec)
   162 			{
   163 				pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
   164 			}
   165 			pTimer->m_InExec = false;
   166 			return;
   167 		}
   168 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   169 		m_LoopTimers.remove(pTimer);
   170 		m_FreeTimers.push(pTimer);
   171 	}
   172 }
   173 
   174 void TimerSystem::KillTimer(ITimer *pTimer)
   175 {
   176 	TimerList *pList;
   177 
   178 	if (pTimer->m_KillMe)
   179 	{
   180 		return;
   181 	}
   182 
   183 	if (pTimer->m_InExec)
   184 	{
   185 		pTimer->m_KillMe = true;
   186 		return;
   187 	}
   188 
   189 	pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
   190 	pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   191 
   192 	pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
   193 
   194 	pList->remove(pTimer);
   195 	m_FreeTimers.push(pTimer);
   196 }
   197 
   198 void TimerSystem::MapChange()
   199 {
   200 	ITimer *pTimer;
   201 	TimerIter iter;
   202 
   203 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   204 	{
   205 		pTimer = (*iter);
   206 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   207 	}
   208 
   209 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
   210 	{
   211 		pTimer = (*iter);
   212 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   213 	}
   214 }