clean up a bit to and descripe it better

This commit is contained in:
Jupeyy 2018-03-12 15:10:49 +01:00
parent ced0ea3f82
commit 5e1bee2760
3 changed files with 72 additions and 23 deletions

View file

@ -1001,6 +1001,48 @@ int64 time_freq()
#endif #endif
} }
int64 time_get_microseconds()
{
static int64 last = 0;
{
#if defined(CONF_PLATFORM_MACOSX)
static int got_timebase = 0;
mach_timebase_info_data_t timebase;
uint64_t time;
uint64_t q;
uint64_t r;
if (!got_timebase)
{
mach_timebase_info(&timebase);
}
time = mach_absolute_time();
q = time / timebase.denom;
r = time % timebase.denom;
last = q * timebase.numer + r * timebase.numer / timebase.denom;
return last / (int64)1000;
#elif defined(CONF_FAMILY_UNIX)
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
last = (int64)spec.tv_sec*(int64)1000000 + (int64)spec.tv_nsec / 1000;
return last;
#elif defined(CONF_FAMILY_WINDOWS)
int64 t;
QueryPerformanceCounter((PLARGE_INTEGER)&t);
int64 tf;
QueryPerformanceFrequency((PLARGE_INTEGER)&tf);
t = (t * (int64)1000000) / tf;
if(t < last) // for some reason, QPC can return values in the past
return last;
last = t;
return t;
#else
#error not implemented
#endif
}
}
/* ----- network ----- */ /* ----- network ----- */
static void netaddr_to_sockaddr_in(const NETADDR *src, struct sockaddr_in *dest) static void netaddr_to_sockaddr_in(const NETADDR *src, struct sockaddr_in *dest)
{ {

View file

@ -621,6 +621,15 @@ int64 time_freq();
*/ */
int time_timestamp(); int time_timestamp();
/*
Function: time_get_microseconds
Fetches a sample from a high resolution timer and converts it in microseconds.
Returns:
Current value of the timer in microseconds.
*/
int64 time_get_microseconds();
/* Group: Network General */ /* Group: Network General */
typedef struct typedef struct
{ {

View file

@ -2699,11 +2699,11 @@ void CClient::Run()
bool LastQ = false; bool LastQ = false;
bool LastE = false; bool LastE = false;
bool LastG = false; bool LastG = false;
int64 LastTime = time_get(); int64 LastTime = time_get_microseconds();
int64 LastRenderTime = time_get(); int64 LastRenderTime = time_get();
while (1) while(1)
{ {
set_new_tick(); set_new_tick();
@ -2804,7 +2804,7 @@ void CClient::Run()
// keep the overflow time - it's used to make sure the gfx refreshrate is reached // keep the overflow time - it's used to make sure the gfx refreshrate is reached
int64 AdditionalTime = g_Config.m_GfxRefreshRate ? ((Now - LastRenderTime) - (int64)((float)time_freq() / (float)g_Config.m_GfxRefreshRate)) : 0; int64 AdditionalTime = g_Config.m_GfxRefreshRate ? ((Now - LastRenderTime) - (int64)((float)time_freq() / (float)g_Config.m_GfxRefreshRate)) : 0;
// if the value is over a second time loose, reset the additional time (drop the frames we lost already) // if the value is over a second time loose, reset the additional time (drop the frames, that are lost already)
if(AdditionalTime > time_freq()) if(AdditionalTime > time_freq())
AdditionalTime = time_freq(); AdditionalTime = time_freq();
LastRenderTime = Now - AdditionalTime; LastRenderTime = Now - AdditionalTime;
@ -2859,7 +2859,7 @@ void CClient::Run()
#endif #endif
// beNice // beNice
int64 Now = time_get(); int64 Now = time_get_microseconds();
int64 SleepTimeInMicroSeconds = 0; int64 SleepTimeInMicroSeconds = 0;
bool Slept = false; bool Slept = false;
if( if(
@ -2868,34 +2868,32 @@ void CClient::Run()
#endif #endif
(g_Config.m_ClRefreshRateInactive && !m_pGraphics->WindowActive())) (g_Config.m_ClRefreshRateInactive && !m_pGraphics->WindowActive()))
{ {
int64 TimeNowInMicroSeconds = (Now * 1000000ll) / time_freq(); SleepTimeInMicroSeconds = ((int64)1000000 / (int64)g_Config.m_ClRefreshRateInactive) - (Now - LastTime);
int64 TimeLastInMicroSeconds = (LastTime * 1000000ll) / time_freq(); if (SleepTimeInMicroSeconds / (int64)1000 > (int64)0)
SleepTimeInMicroSeconds = (1000000ll / g_Config.m_ClRefreshRateInactive) - (TimeNowInMicroSeconds - TimeLastInMicroSeconds); thread_sleep(SleepTimeInMicroSeconds / (int64)1000);
thread_sleep(max(SleepTimeInMicroSeconds / 1000ll, (int64)0));
Slept = true; Slept = true;
} }
else if(g_Config.m_ClRefreshRate) else if(g_Config.m_ClRefreshRate)
{ {
int64 TimeNowInMicroSeconds = (Now * 1000000ll) / time_freq(); SleepTimeInMicroSeconds = ((int64)1000000 / (int64)g_Config.m_ClRefreshRate) - (Now - LastTime);
int64 TimeLastInMicroSeconds = (LastTime * 1000000ll) / time_freq(); if(SleepTimeInMicroSeconds > (int64)0)
SleepTimeInMicroSeconds = (1000000ll / g_Config.m_ClRefreshRate) - (TimeNowInMicroSeconds - TimeLastInMicroSeconds); net_socket_read_wait(m_NetClient[0].m_Socket, SleepTimeInMicroSeconds);
net_socket_read_wait(m_NetClient[0].m_Socket, max(SleepTimeInMicroSeconds, (int64)0));
Slept = true; Slept = true;
} }
if(Slept) if(Slept)
{ {
// look how much we actually slept/waited
int64 After = time_get();
int64 TimeNowInMicroSeconds = (Now * 1000000ll) / time_freq();
int64 TimeAfterInMicroSeconds = (After * 1000000ll) / time_freq();
int64 TimeDiff = SleepTimeInMicroSeconds - (TimeAfterInMicroSeconds - TimeNowInMicroSeconds);
// if the diff gets too small it shouldn't get even smaller (drop the updates, that could not be handled) // if the diff gets too small it shouldn't get even smaller (drop the updates, that could not be handled)
if(TimeDiff < -1000000ll) if(SleepTimeInMicroSeconds < (int64)-1000000)
TimeDiff = -1000000ll; SleepTimeInMicroSeconds = (int64)-1000000;
// don't go higher than the game ticks speed, because the network is waking up the client with the server's snapshots anyway // don't go higher than the game ticks speed, because the network is waking up the client with the server's snapshots anyway
else if(TimeDiff > 1000000ll / m_GameTickSpeed) else if(SleepTimeInMicroSeconds > (int64)1000000 / m_GameTickSpeed)
TimeDiff = 1000000ll / m_GameTickSpeed; SleepTimeInMicroSeconds = (int64)1000000 / m_GameTickSpeed;
LastTime = Now + (TimeDiff * time_freq()) / 1000000ll; // the time diff between the time that was used actually used and the time the thread should sleep/wait
// will be calculated in the sleep time of the next update tick by faking the time it should have slept/wait.
// so two cases (and the case it slept exactly the time it should):
// - the thread slept/waited too long, then it adjust the time to sleep/wait less in the next update tick
// - the thread slept/waited too less, then it adjust the time to sleep/wait more in the next update tick
LastTime = Now + SleepTimeInMicroSeconds;
} }
else else
LastTime = Now; LastTime = Now;