Clean up getTime helpers

This increases size of the getTime return values to 64 bits.
It also removes the TimeGetter classes since the getTime functions
are now very precise.
This commit is contained in:
ShadowNinja 2016-03-06 14:31:16 -05:00
parent 7f4cdbcbe9
commit b662a4577d
22 changed files with 116 additions and 216 deletions

View File

@ -1618,7 +1618,7 @@ float Client::mediaReceiveProgress()
typedef struct TextureUpdateArgs { typedef struct TextureUpdateArgs {
IrrlichtDevice *device; IrrlichtDevice *device;
gui::IGUIEnvironment *guienv; gui::IGUIEnvironment *guienv;
u32 last_time_ms; u64 last_time_ms;
u16 last_percent; u16 last_percent;
const wchar_t* text_base; const wchar_t* text_base;
ITextureSource *tsrc; ITextureSource *tsrc;
@ -1634,7 +1634,7 @@ void texture_update_progress(void *args, u32 progress, u32 max_progress)
u32 time_ms = targs->last_time_ms; u32 time_ms = targs->last_time_ms;
if (cur_percent != targs->last_percent) { if (cur_percent != targs->last_percent) {
targs->last_percent = cur_percent; targs->last_percent = cur_percent;
time_ms = getTimeMs(); time_ms = porting::getTimeMs();
// only draw when the user will notice something: // only draw when the user will notice something:
do_draw = (time_ms - targs->last_time_ms > 100); do_draw = (time_ms - targs->last_time_ms > 100);
} }
@ -1692,7 +1692,7 @@ void Client::afterContentReceived(IrrlichtDevice *device)
TextureUpdateArgs tu_args; TextureUpdateArgs tu_args;
tu_args.device = device; tu_args.device = device;
tu_args.guienv = guienv; tu_args.guienv = guienv;
tu_args.last_time_ms = getTimeMs(); tu_args.last_time_ms = porting::getTimeMs();
tu_args.last_percent = 0; tu_args.last_percent = 0;
tu_args.text_base = wgettext("Initializing nodes"); tu_args.text_base = wgettext("Initializing nodes");
tu_args.tsrc = m_tsrc; tu_args.tsrc = m_tsrc;

View File

@ -51,22 +51,6 @@ bool noMenuActive()
MainGameCallback *g_gamecallback = NULL; MainGameCallback *g_gamecallback = NULL;
// Instance of the time getter
static TimeGetter *g_timegetter = NULL;
u32 getTimeMs()
{
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(PRECISION_MILLI);
}
u32 getTime(TimePrecision prec) {
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(prec);
}
ClientLauncher::~ClientLauncher() ClientLauncher::~ClientLauncher()
{ {
if (receiver) if (receiver)
@ -96,9 +80,6 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
return false; return false;
} }
// Create time getter
g_timegetter = new IrrlichtTimeGetter(device);
// Speed tests (done after irrlicht is loaded to get timer) // Speed tests (done after irrlicht is loaded to get timer)
if (cmd_args.getFlag("speedtests")) { if (cmd_args.getFlag("speedtests")) {
dstream << "Running speed tests" << std::endl; dstream << "Running speed tests" << std::endl;

View File

@ -24,42 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/inputhandler.h" #include "client/inputhandler.h"
#include "gameparams.h" #include "gameparams.h"
// A small helper class
class TimeGetter
{
public:
virtual u32 getTime(TimePrecision prec) = 0;
};
// A precise irrlicht one
class IrrlichtTimeGetter: public TimeGetter
{
public:
IrrlichtTimeGetter(IrrlichtDevice *device):
m_device(device)
{}
u32 getTime(TimePrecision prec)
{
if (prec == PRECISION_MILLI) {
if (m_device == NULL)
return 0;
return m_device->getTimer()->getRealTime();
} else {
return porting::getTime(prec);
}
}
private:
IrrlichtDevice *m_device;
};
// Not so precise one which works without irrlicht
class SimpleTimeGetter: public TimeGetter
{
public:
u32 getTime(TimePrecision prec)
{
return porting::getTime(prec);
}
};
class ClientLauncher class ClientLauncher
{ {

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "keys.h" #include "keys.h"
#include "settings.h" #include "settings.h"
#include "gettime.h" #include "gettime.h"
#include "porting.h"
#include "../util/string.h" #include "../util/string.h"
bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
@ -199,7 +200,7 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
if (ev.Joystick != m_joystick_id) if (ev.Joystick != m_joystick_id)
return false; return false;
m_internal_time = getTimeMs() / 1000.f; m_internal_time = porting::getTimeMs() / 1000.f;
std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed; std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;

View File

@ -592,7 +592,7 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
u32 RemoteClient::uptime() u32 RemoteClient::uptime()
{ {
return getTime(PRECISION_SECONDS) - m_connection_time; return porting::getTime(PRECISION_SECONDS) - m_connection_time;
} }
ClientInterface::ClientInterface(con::Connection* con) ClientInterface::ClientInterface(con::Connection* con)

View File

@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "threading/mutex.h" #include "threading/mutex.h"
#include "network/networkpacket.h" #include "network/networkpacket.h"
#include "util/cpp11_container.h" #include "util/cpp11_container.h"
#include "porting.h"
#include <list> #include <list>
#include <vector> #include <vector>
@ -265,7 +266,7 @@ public:
m_version_patch(0), m_version_patch(0),
m_full_version("unknown"), m_full_version("unknown"),
m_deployed_compression(0), m_deployed_compression(0),
m_connection_time(getTime(PRECISION_SECONDS)) m_connection_time(porting::getTime(PRECISION_SECONDS))
{ {
} }
~RemoteClient() ~RemoteClient()

View File

@ -71,7 +71,7 @@ int Database_SQLite3::busyHandler(void *data, int count)
{ {
s64 &first_time = reinterpret_cast<s64 *>(data)[0]; s64 &first_time = reinterpret_cast<s64 *>(data)[0];
s64 &prev_time = reinterpret_cast<s64 *>(data)[1]; s64 &prev_time = reinterpret_cast<s64 *>(data)[1];
s64 cur_time = getTimeMs(); s64 cur_time = porting::getTimeMs();
if (count == 0) { if (count == 0) {
first_time = cur_time; first_time = cur_time;

View File

@ -21,33 +21,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define GETTIME_HEADER #define GETTIME_HEADER
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include <time.h>
#include <string>
/*
Get a millisecond counter value.
Precision depends on implementation.
Overflows at any value above 10000000.
Implementation of this is done in:
Normal build: main.cpp
Server build: servermain.cpp
*/
enum TimePrecision enum TimePrecision
{ {
PRECISION_SECONDS = 0, PRECISION_SECONDS,
PRECISION_MILLI, PRECISION_MILLI,
PRECISION_MICRO, PRECISION_MICRO,
PRECISION_NANO PRECISION_NANO
}; };
extern u32 getTimeMs();
extern u32 getTime(TimePrecision prec);
/*
Timestamp stuff
*/
#include <string>
#include <time.h>
inline std::string getTimestamp() inline std::string getTimestamp()
{ {

View File

@ -55,7 +55,7 @@ GUIChatConsole::GUIChatConsole(
m_client(client), m_client(client),
m_menumgr(menumgr), m_menumgr(menumgr),
m_screensize(v2u32(0,0)), m_screensize(v2u32(0,0)),
m_animate_time_old(0), m_animate_time_old(porting::getTimeMs()),
m_open(false), m_open(false),
m_close_on_enter(false), m_close_on_enter(false),
m_height(0), m_height(0),
@ -71,8 +71,6 @@ GUIChatConsole::GUIChatConsole(
m_font(NULL), m_font(NULL),
m_fontsize(0, 0) m_fontsize(0, 0)
{ {
m_animate_time_old = getTimeMs();
// load background settings // load background settings
s32 console_alpha = g_settings->getS32("console_alpha"); s32 console_alpha = g_settings->getS32("console_alpha");
m_background_color.setAlpha(clamp_u8(console_alpha)); m_background_color.setAlpha(clamp_u8(console_alpha));
@ -124,7 +122,7 @@ void GUIChatConsole::openConsole(f32 scale)
m_desired_height_fraction = scale; m_desired_height_fraction = scale;
m_desired_height = scale * m_screensize.Y; m_desired_height = scale * m_screensize.Y;
reformatConsole(); reformatConsole();
m_animate_time_old = getTimeMs(); m_animate_time_old = porting::getTimeMs();
IGUIElement::setVisible(true); IGUIElement::setVisible(true);
Environment->setFocus(this); Environment->setFocus(this);
m_menumgr->createdMenu(this); m_menumgr->createdMenu(this);
@ -212,7 +210,7 @@ void GUIChatConsole::draw()
} }
// Animation // Animation
u32 now = getTimeMs(); u64 now = porting::getTimeMs();
animate(now - m_animate_time_old); animate(now - m_animate_time_old);
m_animate_time_old = now; m_animate_time_old = now;

View File

@ -98,7 +98,7 @@ private:
v2u32 m_screensize; v2u32 m_screensize;
// used to compute how much time passed since last animate() // used to compute how much time passed since last animate()
u32 m_animate_time_old; u64 m_animate_time_old;
// should the console be opened or closed? // should the console be opened or closed?
bool m_open; bool m_open;

View File

@ -2664,9 +2664,9 @@ void GUIFormSpecMenu::drawMenu()
m_old_tooltip = L""; m_old_tooltip = L"";
} else { } else {
if (id == m_old_tooltip_id) { if (id == m_old_tooltip_id) {
delta = porting::getDeltaMs(m_hovered_time, getTimeMs()); delta = porting::getDeltaMs(m_hovered_time, porting::getTimeMs());
} else { } else {
m_hovered_time = getTimeMs(); m_hovered_time = porting::getTimeMs();
m_old_tooltip_id = id; m_old_tooltip_id = id;
} }
} }
@ -3244,10 +3244,10 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
m_doubleclickdetect[0].time = m_doubleclickdetect[1].time; m_doubleclickdetect[0].time = m_doubleclickdetect[1].time;
m_doubleclickdetect[1].pos = m_pointer; m_doubleclickdetect[1].pos = m_pointer;
m_doubleclickdetect[1].time = getTimeMs(); m_doubleclickdetect[1].time = porting::getTimeMs();
} }
else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, getTimeMs()); u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, porting::getTimeMs());
if (delta > 400) { if (delta > 400) {
return false; return false;
} }

View File

@ -421,7 +421,7 @@ protected:
gui::IGUIStaticText *m_tooltip_element; gui::IGUIStaticText *m_tooltip_element;
u32 m_tooltip_show_delay; u32 m_tooltip_show_delay;
s32 m_hovered_time; s64 m_hovered_time;
s32 m_old_tooltip_id; s32 m_old_tooltip_id;
std::wstring m_old_tooltip; std::wstring m_old_tooltip;
@ -527,7 +527,7 @@ private:
struct clickpos struct clickpos
{ {
v2s32 pos; v2s32 pos;
s32 time; s64 time;
}; };
clickpos m_doubleclickdetect[2]; clickpos m_doubleclickdetect[2];

View File

@ -828,7 +828,7 @@ bool GUITable::OnEvent(const SEvent &event)
} }
else if (event.KeyInput.PressedDown && event.KeyInput.Char) { else if (event.KeyInput.PressedDown && event.KeyInput.Char) {
// change selection based on text as it is typed // change selection based on text as it is typed
s32 now = getTimeMs(); u64 now = porting::getTimeMs();
if (now - m_keynav_time >= 500) if (now - m_keynav_time >= 500)
m_keynav_buffer = L""; m_keynav_buffer = L"";
m_keynav_time = now; m_keynav_time = now;

View File

@ -196,7 +196,7 @@ protected:
bool m_sel_doubleclick; bool m_sel_doubleclick;
// Keyboard navigation stuff // Keyboard navigation stuff
s32 m_keynav_time; u64 m_keynav_time;
core::stringw m_keynav_buffer; core::stringw m_keynav_buffer;
// Drawing and geometry information // Drawing and geometry information

View File

@ -619,7 +619,7 @@ void Hud::resizeHotbar() {
} }
struct MeshTimeInfo { struct MeshTimeInfo {
s32 time; s64 time;
scene::IMesh *mesh; scene::IMesh *mesh;
}; };
@ -653,9 +653,9 @@ void drawItemStack(video::IVideoDriver *driver,
MeshTimeInfo &ti = rotation_time_infos[rotation_kind]; MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
if (mesh != ti.mesh) { if (mesh != ti.mesh) {
ti.mesh = mesh; ti.mesh = mesh;
ti.time = getTimeMs(); ti.time = porting::getTimeMs();
} else { } else {
delta = porting::getDeltaMs(ti.time, getTimeMs()) % 100000; delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
} }
} }
core::rect<s32> oldViewPort = driver->getViewPort(); core::rect<s32> oldViewPort = driver->getViewPort();

View File

@ -107,24 +107,6 @@ static bool migrate_map_database(const GameParams &game_params, const Settings &
/**********************************************************************/ /**********************************************************************/
/*
gettime.h implementation
*/
#ifdef SERVER
u32 getTimeMs()
{
/* Use imprecise system calls directly (from porting.h) */
return porting::getTime(PRECISION_MILLI);
}
u32 getTime(TimePrecision prec)
{
return porting::getTime(prec);
}
#endif
FileLogOutput file_log_output; FileLogOutput file_log_output;

View File

@ -981,7 +981,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
time_until_purge *= 1000; // seconds -> milliseconds time_until_purge *= 1000; // seconds -> milliseconds
u32 curr_time = getTime(PRECISION_MILLI); u32 curr_time = porting::getTime(PRECISION_MILLI);
u32 prev_unprocessed = m_unprocessed_count; u32 prev_unprocessed = m_unprocessed_count;
m_unprocessed_count = m_transforming_liquid.size(); m_unprocessed_count = m_transforming_liquid.size();

View File

@ -942,5 +942,18 @@ void attachOrCreateConsole(void)
#endif #endif
} }
// Load performance counter frequency only once at startup
#ifdef _WIN32
inline double get_perf_freq()
{
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return freq.QuadPart;
}
double perf_freq = get_perf_freq();
#endif
} //namespace porting } //namespace porting

View File

@ -181,124 +181,99 @@ std::string get_sysinfo();
void initIrrlicht(irr::IrrlichtDevice * ); void initIrrlicht(irr::IrrlichtDevice * );
/*
Resolution is 10-20ms. // Monotonic counter getters.
Remember to check for overflows.
Overflow can occur at any value higher than 10000000.
*/
#ifdef _WIN32 // Windows #ifdef _WIN32 // Windows
inline u32 getTimeS() extern double perf_freq;
{
return GetTickCount() / 1000;
}
inline u32 getTimeMs() inline u64 os_get_time(double mult)
{ {
return GetTickCount(); LARGE_INTEGER t;
} QueryPerformanceCounter(&t);
return static_cast<double>(t.QuadPart) / (perf_freq / mult);
}
inline u32 getTimeUs() // Resolution is <1us.
{ inline u64 getTimeS() { return os_get_time(1); }
LARGE_INTEGER freq, t; inline u64 getTimeMs() { return os_get_time(1000); }
QueryPerformanceFrequency(&freq); inline u64 getTimeUs() { return os_get_time(1000*1000); }
QueryPerformanceCounter(&t); inline u64 getTimeNs() { return os_get_time(1000*1000*1000); }
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0);
}
inline u32 getTimeNs()
{
LARGE_INTEGER freq, t;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&t);
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0);
}
#else // Posix #else // Posix
inline void _os_get_clock(struct timespec *ts)
{ inline void os_get_clock(struct timespec *ts)
{
#if defined(__MACH__) && defined(__APPLE__) #if defined(__MACH__) && defined(__APPLE__)
// from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x // From http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
// OS X does not have clock_gettime, use clock_get_time // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock; clock_serv_t cclock;
mach_timespec_t mts; mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts); clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock); mach_port_deallocate(mach_task_self(), cclock);
ts->tv_sec = mts.tv_sec; ts->tv_sec = mts.tv_sec;
ts->tv_nsec = mts.tv_nsec; ts->tv_nsec = mts.tv_nsec;
#elif defined(CLOCK_MONOTONIC_RAW) #elif defined(CLOCK_MONOTONIC_RAW)
clock_gettime(CLOCK_MONOTONIC_RAW, ts); clock_gettime(CLOCK_MONOTONIC_RAW, ts);
#elif defined(_POSIX_MONOTONIC_CLOCK) #elif defined(_POSIX_MONOTONIC_CLOCK)
clock_gettime(CLOCK_MONOTONIC, ts); clock_gettime(CLOCK_MONOTONIC, ts);
#else #else
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, ts); TIMEVAL_TO_TIMESPEC(&tv, ts);
#endif // defined(__MACH__) && defined(__APPLE__) #endif
} }
// Note: these clock functions do not return wall time, but inline u64 getTimeS()
// generally a clock that starts at 0 when the process starts. {
inline u32 getTimeS() struct timespec ts;
{ os_get_clock(&ts);
struct timespec ts; return ts.tv_sec;
_os_get_clock(&ts); }
return ts.tv_sec;
}
inline u32 getTimeMs() inline u64 getTimeMs()
{ {
struct timespec ts; struct timespec ts;
_os_get_clock(&ts); os_get_clock(&ts);
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
} }
inline u32 getTimeUs() inline u64 getTimeUs()
{ {
struct timespec ts; struct timespec ts;
_os_get_clock(&ts); os_get_clock(&ts);
return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
} }
inline u32 getTimeNs() inline u64 getTimeNs()
{ {
struct timespec ts; struct timespec ts;
_os_get_clock(&ts); os_get_clock(&ts);
return ts.tv_sec * 1000000000 + ts.tv_nsec; return ts.tv_sec * 1000000000 + ts.tv_nsec;
} }
/*#include <sys/timeb.h>
inline u32 getTimeMs()
{
struct timeb tb;
ftime(&tb);
return tb.time * 1000 + tb.millitm;
}*/
#endif #endif
inline u32 getTime(TimePrecision prec) inline u64 getTime(TimePrecision prec)
{ {
switch (prec) { switch (prec) {
case PRECISION_SECONDS: case PRECISION_SECONDS: return getTimeS();
return getTimeS(); case PRECISION_MILLI: return getTimeMs();
case PRECISION_MILLI: case PRECISION_MICRO: return getTimeUs();
return getTimeMs(); case PRECISION_NANO: return getTimeNs();
case PRECISION_MICRO:
return getTimeUs();
case PRECISION_NANO:
return getTimeNs();
} }
return 0; FATAL_ERROR("Called getTime with invalid time precision");
} }
/** /**
* Delta calculation function taking two 32bit arguments. * Delta calculation function arguments.
* @param old_time_ms old time for delta calculation (order is relevant!) * @param old_time_ms old time for delta calculation
* @param new_time_ms new time for delta calculation (order is relevant!) * @param new_time_ms new time for delta calculation
* @return positive 32bit delta value * @return positive delta value
*/ */
inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms) inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms)
{ {
if (new_time_ms >= old_time_ms) { if (new_time_ms >= old_time_ms) {
return (new_time_ms - old_time_ms); return (new_time_ms - old_time_ms);

View File

@ -794,7 +794,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
if (m_move_id == -1) { if (m_move_id == -1) {
m_move_id = event.TouchInput.ID; m_move_id = event.TouchInput.ID;
m_move_has_really_moved = false; m_move_has_really_moved = false;
m_move_downtime = getTimeMs(); m_move_downtime = porting::getTimeMs();
m_move_downlocation = v2s32(event.TouchInput.X, event.TouchInput.Y); m_move_downlocation = v2s32(event.TouchInput.X, event.TouchInput.Y);
m_move_sent_as_mouse_event = false; m_move_sent_as_mouse_event = false;
} }

View File

@ -186,7 +186,7 @@ private:
int m_move_id; int m_move_id;
bool m_move_has_really_moved; bool m_move_has_really_moved;
s32 m_move_downtime; s64 m_move_downtime;
bool m_move_sent_as_mouse_event; bool m_move_sent_as_mouse_event;
v2s32 m_move_downlocation; v2s32 m_move_downlocation;

View File

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "timetaker.h" #include "timetaker.h"
#include "../gettime.h" #include "../porting.h"
#include "../log.h" #include "../log.h"
#include <ostream> #include <ostream>
@ -29,14 +29,14 @@ TimeTaker::TimeTaker(const char *name, u32 *result, TimePrecision prec)
m_result = result; m_result = result;
m_running = true; m_running = true;
m_precision = prec; m_precision = prec;
m_time1 = getTime(prec); m_time1 = porting::getTime(prec);
} }
u32 TimeTaker::stop(bool quiet) u32 TimeTaker::stop(bool quiet)
{ {
if(m_running) if(m_running)
{ {
u32 time2 = getTime(m_precision); u32 time2 = porting::getTime(m_precision);
u32 dtime = time2 - m_time1; u32 dtime = time2 - m_time1;
if(m_result != NULL) if(m_result != NULL)
{ {
@ -64,7 +64,7 @@ u32 TimeTaker::stop(bool quiet)
u32 TimeTaker::getTimerTime() u32 TimeTaker::getTimerTime()
{ {
u32 time2 = getTime(m_precision); u32 time2 = porting::getTime(m_precision);
u32 dtime = time2 - m_time1; u32 dtime = time2 - m_time1;
return dtime; return dtime;
} }