core/TimerSys.cpp
author Scott Ehlert <ds@alliedmods.net>
Thu Mar 22 21:50:20 2007 +0000 (2007-03-22)
changeset 653 ef60870067ff
parent 641 ce1f369ba889
child 673 fc1d50579d06
permissions -rw-r--r--
More consistency of some sort...

Oh god, what has possessed me to do this?
     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::RunFrame()
    46 {
    47 	ITimer *pTimer;
    48 	TimerIter iter;
    49 
    50 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
    51 	{
    52 		pTimer = (*iter);
    53 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    54 		{
    55 			pTimer->m_InExec = true;
    56 			pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    57 			pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    58 			iter = m_SingleTimers.erase(iter);
    59 			m_FreeTimers.push(pTimer);
    60 		} else {
    61 			break;
    62 		}
    63 	}
    64 
    65 	ResultType res;
    66 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
    67 	{
    68 		pTimer = (*iter);
    69 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    70 		{
    71 			pTimer->m_InExec = true;
    72 			res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    73 			if (pTimer->m_KillMe || (res == Pl_Stop))
    74 			{
    75 				pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    76 				iter = m_LoopTimers.erase(iter);
    77 				m_FreeTimers.push(pTimer);
    78 				continue;
    79 			}
    80 			pTimer->m_InExec = false;
    81 			pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
    82 		}
    83 		iter++;
    84 	}
    85 
    86 	m_LastExecTime = gpGlobals->curtime;
    87 }
    88 
    89 ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
    90 {
    91 	ITimer *pTimer;
    92 	TimerIter iter;
    93 	float to_exec = gpGlobals->curtime + fInterval;
    94 
    95 	if (m_FreeTimers.empty())
    96 	{
    97 		pTimer = new ITimer;
    98 	} else {
    99 		pTimer = m_FreeTimers.front();
   100 		m_FreeTimers.pop();
   101 	}
   102 
   103 	pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
   104 
   105 	if (flags & TIMER_FLAG_REPEAT)
   106 	{
   107 		m_LoopTimers.push_back(pTimer);
   108 		goto return_timer;
   109 	}
   110 
   111 	if (m_SingleTimers.size() >= 1)
   112 	{
   113 		iter = --m_SingleTimers.end();
   114 		if ((*iter)->m_ToExec <= to_exec)
   115 		{
   116 			goto insert_end;
   117 		}
   118 	}
   119 
   120 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   121 	{
   122 		if ((*iter)->m_ToExec >= to_exec)
   123 		{
   124 			m_SingleTimers.insert(iter, pTimer);
   125 			goto return_timer;
   126 		}
   127 	}
   128 
   129 insert_end:
   130 	m_SingleTimers.push_back(pTimer);
   131 
   132 return_timer:
   133 	return pTimer;
   134 }
   135 
   136 void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
   137 {
   138 	ResultType res;
   139 
   140 	if (pTimer->m_InExec)
   141 	{
   142 		return;
   143 	}
   144 
   145 	pTimer->m_InExec = true;
   146 	res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
   147 
   148 	if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
   149 	{
   150 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   151 		m_SingleTimers.remove(pTimer);
   152 		m_FreeTimers.push(pTimer);
   153 	} else {
   154 		if ((res != Pl_Stop) && !pTimer->m_KillMe)
   155 		{
   156 			if (delayExec)
   157 			{
   158 				pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
   159 			}
   160 			pTimer->m_InExec = false;
   161 			return;
   162 		}
   163 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   164 		m_LoopTimers.remove(pTimer);
   165 		m_FreeTimers.push(pTimer);
   166 	}
   167 }
   168 
   169 void TimerSystem::KillTimer(ITimer *pTimer)
   170 {
   171 	TimerList *pList;
   172 
   173 	if (pTimer->m_KillMe)
   174 	{
   175 		return;
   176 	}
   177 
   178 	if (pTimer->m_InExec)
   179 	{
   180 		pTimer->m_KillMe = true;
   181 		return;
   182 	}
   183 
   184 	pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
   185 	pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   186 
   187 	pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
   188 
   189 	pList->remove(pTimer);
   190 	m_FreeTimers.push(pTimer);
   191 }
   192 
   193 void TimerSystem::MapChange()
   194 {
   195 	ITimer *pTimer;
   196 	TimerIter iter;
   197 
   198 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   199 	{
   200 		pTimer = (*iter);
   201 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   202 	}
   203 
   204 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
   205 	{
   206 		pTimer = (*iter);
   207 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   208 	}
   209 }