1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/**
* @file timer.cpp
* Timing subsystem. @ingroup system
*
* @note Under WIN32, uses Win32 multimedia timing routines.
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2007-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2007-2008 Jamie Jones <jamie_jones_au@yahoo.com.au>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/
#include <QTime>
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <mmsystem.h>
#endif
#include "de/timer.h"
#include "de/concurrency.h"
static float ticksPerSecond = TICSPERSEC;
static double timeOffset = 0;
static mutex_t timerMutex; // To prevent Data races in the timer
static QTime startedAt;
static uint timerOffset = 0;
static uint const TIMER_WARP_INTERVAL = 12*60*60*1000;
void Timer_Shutdown(void)
{
#ifdef WIN32
timeEndPeriod(1);
#endif
mutex_t m = timerMutex;
timerMutex = 0;
Sys_DestroyMutex(m);
}
void Timer_Init(void)
{
assert(timerMutex == 0);
timerMutex = Sys_CreateMutex("TIMER_MUTEX");
#ifdef WIN32
timeBeginPeriod(1);
#endif
startedAt.start();
timerOffset = 0;
}
unsigned int Timer_RealMilliseconds(void)
{
static boolean first = true;
static unsigned int start;
#ifdef WIN32
DWORD return_time, now;
#else
uint return_time, now;
#endif
Sys_Lock(timerMutex);
#ifdef WIN32
now = timeGetTime();
#else
now = uint(startedAt.elapsed());
if(now > TIMER_WARP_INTERVAL)
{
now += timerOffset;
// QTime will wrap around every 24 hours; we'll wrap it manually before that.
timerOffset += TIMER_WARP_INTERVAL;
startedAt = startedAt.addMSecs(TIMER_WARP_INTERVAL);
}
else
{
now += timerOffset;
}
#endif
if(first)
{
first = false;
start = now;
Sys_Unlock(timerMutex);
return 0;
}
// Wrapped around? (Every 50 days...)
if(now < start)
{
return_time = 0xffffffff - start + now + 1;
Sys_Unlock(timerMutex);
return return_time;
}
return_time = now - start;
Sys_Unlock(timerMutex);
return return_time;
}
double Timer_Seconds(void)
{
return (double) ((Timer_RealMilliseconds() / 1000.0) * (ticksPerSecond / 35)) + timeOffset;
}
double Timer_RealSeconds(void)
{
return (double) (Timer_RealMilliseconds() / 1000.0);
}
double Timer_Ticksf(void)
{
return Timer_Seconds() * 35;
}
int Timer_Ticks(void)
{
return (int) Timer_Ticksf();
}
void Timer_SetTicksPerSecond(float newTics)
{
double nowTime = Timer_RealMilliseconds() / 1000.0;
if(newTics <= 0)
newTics = TICSPERSEC;
// Update the time offset so that after the change time will
// continue from the same value.
timeOffset += nowTime * (ticksPerSecond - newTics) / 35;
ticksPerSecond = newTics;
}
float Timer_TicksPerSecond(void)
{
return ticksPerSecond;
}
|