ui_timer.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "../client.h"
00026 #include "ui_nodes.h"
00027 #include "ui_timer.h"
00028 
00032 #define UI_TIMER_SLOT_NUMBER 10
00033 
00037 static uiTimer_t mn_timerSlots[UI_TIMER_SLOT_NUMBER];
00038 
00043 static uiTimer_t *mn_firstTimer;
00044 
00049 static inline void UI_RemoveTimerFromActiveList (uiTimer_t *timer)
00050 {
00051     assert(timer >= mn_timerSlots && timer < mn_timerSlots + UI_TIMER_SLOT_NUMBER);
00052     if (timer->prev) {
00053         timer->prev->next = timer->next;
00054     } else {
00055         mn_firstTimer = timer->next;
00056     }
00057     if (timer->next) {
00058         timer->next->prev = timer->prev;
00059     }
00060 }
00061 
00066 static void UI_InsertTimerInActiveList (uiTimer_t* first, uiTimer_t* newTimer)
00067 {
00068     uiTimer_t* current = first;
00069     uiTimer_t* prev = NULL;
00070 
00071     /* find insert position */
00072     if (current != NULL) {
00073         prev = current->prev;
00074     }
00075     while (current) {
00076         if (newTimer->nextTime < current->nextTime)
00077             break;
00078         prev = current;
00079         current = current->next;
00080     }
00081 
00082     /* insert between previous and current */
00083     newTimer->prev = prev;
00084     newTimer->next = current;
00085     if (current != NULL) {
00086         current->prev = newTimer;
00087     }
00088     if (prev != NULL) {
00089         prev->next = newTimer;
00090     } else {
00091         mn_firstTimer = newTimer;
00092     }
00093 }
00094 
00098 void UI_HandleTimers (void)
00099 {
00100     /* is first element is out of date? */
00101     while (mn_firstTimer && mn_firstTimer->nextTime <= CL_Milliseconds()) {
00102         uiTimer_t *timer = mn_firstTimer;
00103 
00104         /* throw event */
00105         timer->calledTime++;
00106         timer->callback(timer->owner, timer);
00107 
00108         /* update the sorted list */
00109         if (timer->isRunning) {
00110             UI_RemoveTimerFromActiveList(timer);
00111             timer->nextTime += timer->delay;
00112             UI_InsertTimerInActiveList(timer->next, timer);
00113         }
00114     }
00115 }
00116 
00123 uiTimer_t* UI_AllocTimer (uiNode_t *node, int firstDelay, timerCallback_t callback)
00124 {
00125     uiTimer_t *timer = NULL;
00126     int i;
00127 
00128     /* search empty slot */
00129     for (i = 0; i < UI_TIMER_SLOT_NUMBER; i++) {
00130         if (mn_timerSlots[i].callback != NULL)
00131             continue;
00132         timer = mn_timerSlots + i;
00133         break;
00134     }
00135     if (timer == NULL)
00136         Com_Error(ERR_FATAL, "UI_AllocTimer: No more timer slot");
00137 
00138     timer->owner = node;
00139     timer->delay = firstDelay;
00140     timer->callback = callback;
00141     timer->calledTime = 0;
00142     timer->prev = NULL;
00143     timer->next = NULL;
00144     timer->isRunning = qfalse;
00145     return timer;
00146 }
00147 
00151 void UI_TimerStart (uiTimer_t *timer)
00152 {
00153     if (timer->isRunning)
00154         return;
00155     assert(mn_firstTimer != timer && timer->prev == NULL && timer->next == NULL);
00156     timer->nextTime = CL_Milliseconds() + timer->delay;
00157     timer->isRunning = qtrue;
00158     UI_InsertTimerInActiveList(mn_firstTimer, timer);
00159 }
00160 
00164 void UI_TimerStop (uiTimer_t *timer)
00165 {
00166     if (!timer->isRunning)
00167         return;
00168     UI_RemoveTimerFromActiveList(timer);
00169     timer->prev = NULL;
00170     timer->next = NULL;
00171     timer->isRunning = qfalse;
00172 }
00173 
00177 void UI_TimerRelease (uiTimer_t *timer)
00178 {
00179     UI_RemoveTimerFromActiveList(timer);
00180     timer->prev = NULL;
00181     timer->next = NULL;
00182     timer->owner = NULL;
00183     timer->callback = NULL;
00184 }
00185 
00186 #ifdef COMPILE_UNITTESTS
00187 
00192 uiTimer_t *UI_GetFirstTimer (void)
00193 {
00194     return mn_firstTimer;
00195 }
00196 
00197 void UI_PrivateInsertTimerInActiveList (uiTimer_t* first, uiTimer_t* newTimer)
00198 {
00199     UI_InsertTimerInActiveList(first, newTimer);
00200 }
00201 
00202 #endif

Generated by  doxygen 1.6.2