core/TimerSys.cpp
author David Anderson <dvander@alliedmods.net>
Thu Mar 15 04:45:33 2007 +0000 (2007-03-15)
changeset 617 dc7671b320e4
parent 616 d5b1dcf38c07
child 641 ce1f369ba889
permissions -rw-r--r--
fixed two spelling mistakes
     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 void TimerSystem::OnSourceModAllInitialized()
    31 {
    32 	g_ShareSys.AddInterface(NULL, this);
    33 }
    34 
    35 void TimerSystem::RunFrame()
    36 {
    37 	ITimer *pTimer;
    38 	TimerIter iter;
    39 
    40 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
    41 	{
    42 		pTimer = (*iter);
    43 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    44 		{
    45 			pTimer->m_InExec = true;
    46 			pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    47 			pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    48 			iter = m_SingleTimers.erase(iter);
    49 			m_FreeTimers.push(pTimer);
    50 		} else {
    51 			break;
    52 		}
    53 	}
    54 
    55 	ResultType res;
    56 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
    57 	{
    58 		pTimer = (*iter);
    59 		if (gpGlobals->curtime >= pTimer->m_ToExec)
    60 		{
    61 			pTimer->m_InExec = true;
    62 			res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    63 			if (pTimer->m_KillMe || (res == Pl_Stop))
    64 			{
    65 				pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    66 				iter = m_LoopTimers.erase(iter);
    67 				m_FreeTimers.push(pTimer);
    68 				continue;
    69 			}
    70 			pTimer->m_InExec = false;
    71 			pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
    72 		}
    73 		iter++;
    74 	}
    75 
    76 	m_LastExecTime = gpGlobals->curtime;
    77 }
    78 
    79 ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
    80 {
    81 	ITimer *pTimer;
    82 	TimerIter iter;
    83 	float to_exec = gpGlobals->curtime + fInterval;
    84 
    85 	if (m_FreeTimers.empty())
    86 	{
    87 		pTimer = new ITimer;
    88 	} else {
    89 		pTimer = m_FreeTimers.front();
    90 		m_FreeTimers.pop();
    91 	}
    92 
    93 	pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
    94 
    95 	if (flags & TIMER_FLAG_REPEAT)
    96 	{
    97 		m_LoopTimers.push_back(pTimer);
    98 		goto return_timer;
    99 	}
   100 
   101 	if (m_SingleTimers.size() >= 1)
   102 	{
   103 		iter = --m_SingleTimers.end();
   104 		if ((*iter)->m_ToExec <= to_exec)
   105 		{
   106 			goto insert_end;
   107 		}
   108 	}
   109 
   110 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   111 	{
   112 		if ((*iter)->m_ToExec >= to_exec)
   113 		{
   114 			m_SingleTimers.insert(iter, pTimer);
   115 			goto return_timer;
   116 		}
   117 	}
   118 
   119 insert_end:
   120 	m_SingleTimers.push_back(pTimer);
   121 
   122 return_timer:
   123 	return pTimer;
   124 }
   125 
   126 void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
   127 {
   128 	ResultType res;
   129 
   130 	if (pTimer->m_InExec)
   131 	{
   132 		return;
   133 	}
   134 
   135 	pTimer->m_InExec = true;
   136 	res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
   137 
   138 	if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
   139 	{
   140 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   141 		m_SingleTimers.remove(pTimer);
   142 		m_FreeTimers.push(pTimer);
   143 	} else {
   144 		if ((res != Pl_Stop) && !pTimer->m_KillMe)
   145 		{
   146 			if (delayExec)
   147 			{
   148 				pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
   149 			}
   150 			pTimer->m_InExec = false;
   151 			return;
   152 		}
   153 		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   154 		m_LoopTimers.remove(pTimer);
   155 		m_FreeTimers.push(pTimer);
   156 	}
   157 }
   158 
   159 void TimerSystem::KillTimer(ITimer *pTimer)
   160 {
   161 	TimerList *pList;
   162 
   163 	if (pTimer->m_KillMe)
   164 	{
   165 		return;
   166 	}
   167 
   168 	if (pTimer->m_InExec)
   169 	{
   170 		pTimer->m_KillMe = true;
   171 		return;
   172 	}
   173 
   174 	pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
   175 	pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   176 
   177 	pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
   178 
   179 	pList->remove(pTimer);
   180 	m_FreeTimers.push(pTimer);
   181 }
   182 
   183 void TimerSystem::MapChange()
   184 {
   185 	ITimer *pTimer;
   186 	TimerIter iter;
   187 
   188 	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
   189 	{
   190 		pTimer = (*iter);
   191 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   192 	}
   193 
   194 	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
   195 	{
   196 		pTimer = (*iter);
   197 		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
   198 	}
   199 }