From 195d6cded05f7ef5bde695ee047b341a0265eab3 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 24 Mar 2013 00:03:37 +0100 Subject: Fixed timer functions on win32 * changed win32 implementation to QueryPerformaceTimer system function * refactored system utils code * proper tests for time utils and update event creation in application * should fix issue #134 --- src/app/app.cpp | 133 +++++++++++++++++--------------- src/app/app.h | 2 +- src/app/main.cpp | 32 ++++---- src/app/system.cpp | 185 +++++++++++++++++++++++++++------------------ src/app/system.h | 90 ++++++++++++++-------- src/app/system_linux.cpp | 25 +++++- src/app/system_linux.h | 16 +++- src/app/system_other.cpp | 93 ++--------------------- src/app/system_other.h | 13 ++-- src/app/system_windows.cpp | 64 ++++++++++------ src/app/system_windows.h | 29 ++++--- 11 files changed, 370 insertions(+), 312 deletions(-) (limited to 'src/app') diff --git a/src/app/app.cpp b/src/app/app.cpp index e84091b..9349cbf 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -125,14 +125,14 @@ CApplication::CApplication() m_absTime = 0.0f; m_relTime = 0.0f; - m_baseTimeStamp = CreateTimeStamp(); - m_curTimeStamp = CreateTimeStamp(); - m_lastTimeStamp = CreateTimeStamp(); + m_baseTimeStamp = GetSystemUtils()->CreateTimeStamp(); + m_curTimeStamp = GetSystemUtils()->CreateTimeStamp(); + m_lastTimeStamp = GetSystemUtils()->CreateTimeStamp(); for (int i = 0; i < PCNT_MAX; ++i) { - m_performanceCounters[i][0] = CreateTimeStamp(); - m_performanceCounters[i][1] = CreateTimeStamp(); + m_performanceCounters[i][0] = GetSystemUtils()->CreateTimeStamp(); + m_performanceCounters[i][1] = GetSystemUtils()->CreateTimeStamp(); } m_joystickEnabled = false; @@ -177,14 +177,14 @@ CApplication::~CApplication() delete m_iMan; m_iMan = nullptr; - DestroyTimeStamp(m_baseTimeStamp); - DestroyTimeStamp(m_curTimeStamp); - DestroyTimeStamp(m_lastTimeStamp); + GetSystemUtils()->DestroyTimeStamp(m_baseTimeStamp); + GetSystemUtils()->DestroyTimeStamp(m_curTimeStamp); + GetSystemUtils()->DestroyTimeStamp(m_lastTimeStamp); for (int i = 0; i < PCNT_MAX; ++i) { - DestroyTimeStamp(m_performanceCounters[i][0]); - DestroyTimeStamp(m_performanceCounters[i][1]); + GetSystemUtils()->DestroyTimeStamp(m_performanceCounters[i][0]); + GetSystemUtils()->DestroyTimeStamp(m_performanceCounters[i][1]); } } @@ -199,8 +199,8 @@ CSoundInterface* CApplication::GetSound() for (int i = 0; i < PCNT_MAX; ++i) { - DestroyTimeStamp(m_performanceCounters[i][0]); - DestroyTimeStamp(m_performanceCounters[i][1]); + GetSystemUtils()->DestroyTimeStamp(m_performanceCounters[i][0]); + GetSystemUtils()->DestroyTimeStamp(m_performanceCounters[i][1]); } } @@ -607,7 +607,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig) std::string(SDL_GetError()) + std::string("\n") + std::string("Previous mode will be restored"); GetLogger()->Error(error.c_str()); - SystemDialog( SDT_ERROR, "COLOBT - Error", error); + GetSystemUtils()->SystemDialog( SDT_ERROR, "COLOBT - Error", error); restore = true; ChangeVideoConfig(m_lastDeviceConfig); @@ -620,7 +620,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig) std::string error = std::string("SDL error while restoring previous video mode:\n") + std::string(SDL_GetError()); GetLogger()->Error(error.c_str()); - SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", error); + GetSystemUtils()->SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", error); // Fatal error, so post the quit event @@ -755,9 +755,9 @@ int CApplication::Run() { m_active = true; - GetCurrentTimeStamp(m_baseTimeStamp); - GetCurrentTimeStamp(m_lastTimeStamp); - GetCurrentTimeStamp(m_curTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_baseTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_lastTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_curTimeStamp); MoveMouse(Math::Point(0.5f, 0.5f)); // center mouse on start @@ -1109,49 +1109,49 @@ bool CApplication::ProcessEvent(const Event &event) { case EVENT_KEY_DOWN: case EVENT_KEY_UP: - l->Info("EVENT_KEY_%s:\n", (event.type == EVENT_KEY_DOWN) ? "DOWN" : "UP"); - l->Info(" virt = %s\n", (event.key.virt) ? "true" : "false"); - l->Info(" key = %d\n", event.key.key); - l->Info(" unicode = 0x%04x\n", event.key.unicode); + l->Trace("EVENT_KEY_%s:\n", (event.type == EVENT_KEY_DOWN) ? "DOWN" : "UP"); + l->Trace(" virt = %s\n", (event.key.virt) ? "true" : "false"); + l->Trace(" key = %d\n", event.key.key); + l->Trace(" unicode = 0x%04x\n", event.key.unicode); break; case EVENT_MOUSE_MOVE: - l->Info("EVENT_MOUSE_MOVE:\n"); + l->Trace("EVENT_MOUSE_MOVE:\n"); break; case EVENT_MOUSE_BUTTON_DOWN: case EVENT_MOUSE_BUTTON_UP: - l->Info("EVENT_MOUSE_BUTTON_%s:\n", (event.type == EVENT_MOUSE_BUTTON_DOWN) ? "DOWN" : "UP"); - l->Info(" button = %d\n", event.mouseButton.button); + l->Trace("EVENT_MOUSE_BUTTON_%s:\n", (event.type == EVENT_MOUSE_BUTTON_DOWN) ? "DOWN" : "UP"); + l->Trace(" button = %d\n", event.mouseButton.button); break; case EVENT_MOUSE_WHEEL: - l->Info("EVENT_MOUSE_WHEEL:\n"); - l->Info(" dir = %s\n", (event.mouseWheel.dir == WHEEL_DOWN) ? "WHEEL_DOWN" : "WHEEL_UP"); + l->Trace("EVENT_MOUSE_WHEEL:\n"); + l->Trace(" dir = %s\n", (event.mouseWheel.dir == WHEEL_DOWN) ? "WHEEL_DOWN" : "WHEEL_UP"); break; case EVENT_JOY_AXIS: - l->Info("EVENT_JOY_AXIS:\n"); - l->Info(" axis = %d\n", event.joyAxis.axis); - l->Info(" value = %d\n", event.joyAxis.value); + l->Trace("EVENT_JOY_AXIS:\n"); + l->Trace(" axis = %d\n", event.joyAxis.axis); + l->Trace(" value = %d\n", event.joyAxis.value); break; case EVENT_JOY_BUTTON_DOWN: case EVENT_JOY_BUTTON_UP: - l->Info("EVENT_JOY_BUTTON_%s:\n", (event.type == EVENT_JOY_BUTTON_DOWN) ? "DOWN" : "UP"); - l->Info(" button = %d\n", event.joyButton.button); + l->Trace("EVENT_JOY_BUTTON_%s:\n", (event.type == EVENT_JOY_BUTTON_DOWN) ? "DOWN" : "UP"); + l->Trace(" button = %d\n", event.joyButton.button); break; case EVENT_ACTIVE: - l->Info("EVENT_ACTIVE:\n"); - l->Info(" flags = 0x%x\n", event.active.flags); - l->Info(" gain = %s\n", event.active.gain ? "true" : "false"); + l->Trace("EVENT_ACTIVE:\n"); + l->Trace(" flags = 0x%x\n", event.active.flags); + l->Trace(" gain = %s\n", event.active.gain ? "true" : "false"); break; default: - l->Info("Event type = %d:\n", static_cast(event.type)); + l->Trace("Event type = %d:\n", static_cast(event.type)); break; } - l->Info(" systemEvent = %s\n", event.systemEvent ? "true" : "false"); - l->Info(" rTime = %f\n", event.rTime); - l->Info(" kmodState = %04x\n", event.kmodState); - l->Info(" trackedKeysState = %04x\n", event.trackedKeysState); - l->Info(" mousePos = %f, %f\n", event.mousePos.x, event.mousePos.y); - l->Info(" mouseButtonsState = %02x\n", event.mouseButtonsState); + l->Trace(" systemEvent = %s\n", event.systemEvent ? "true" : "false"); + l->Trace(" rTime = %f\n", event.rTime); + l->Trace(" kmodState = %04x\n", event.kmodState); + l->Trace(" trackedKeysState = %04x\n", event.trackedKeysState); + l->Trace(" mousePos = %f, %f\n", event.mousePos.x, event.mousePos.y); + l->Trace(" mouseButtonsState = %02x\n", event.mouseButtonsState); } // By default, pass on all events @@ -1219,8 +1219,8 @@ void CApplication::ResumeSimulation() { m_simulationSuspended = false; - GetCurrentTimeStamp(m_baseTimeStamp); - CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_baseTimeStamp); + GetSystemUtils()->CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp); m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; @@ -1236,7 +1236,7 @@ void CApplication::SetSimulationSpeed(float speed) { m_simulationSpeed = speed; - GetCurrentTimeStamp(m_baseTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_baseTimeStamp); m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; @@ -1248,18 +1248,31 @@ Event CApplication::CreateUpdateEvent() if (m_simulationSuspended) return Event(EVENT_NULL); - CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); - GetCurrentTimeStamp(m_curTimeStamp); + GetSystemUtils()->CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); + GetSystemUtils()->GetCurrentTimeStamp(m_curTimeStamp); - long long absDiff = TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); - m_realAbsTime = m_realAbsTimeBase + absDiff; - // m_baseTimeStamp is updated on simulation speed change, so this is OK - m_exactAbsTime = m_absTimeBase + m_simulationSpeed * absDiff; - m_absTime = (m_absTimeBase + m_simulationSpeed * absDiff) / 1e9f; + long long absDiff = GetSystemUtils()->TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); + long long newRealAbsTime = m_realAbsTimeBase + absDiff; + long long newRealRelTime = GetSystemUtils()->TimeStampExactDiff(m_lastTimeStamp, m_curTimeStamp); - m_realRelTime = TimeStampExactDiff(m_lastTimeStamp, m_curTimeStamp); - m_exactRelTime = m_simulationSpeed * m_realRelTime; - m_relTime = (m_simulationSpeed * m_realRelTime) / 1e9f; + if (newRealAbsTime < m_realAbsTime || newRealRelTime < 0) + { + GetLogger()->Error("Fatal error: got negative system counter difference!\n"); + GetLogger()->Error("This should never happen. Please report this error.\n"); + m_eventQueue->AddEvent(Event(EVENT_QUIT)); + return Event(EVENT_NULL); + } + else + { + m_realAbsTime = newRealAbsTime; + // m_baseTimeStamp is updated on simulation speed change, so this is OK + m_exactAbsTime = m_absTimeBase + m_simulationSpeed * absDiff; + m_absTime = (m_absTimeBase + m_simulationSpeed * absDiff) / 1e9f; + + m_realRelTime = newRealRelTime; + m_exactRelTime = m_simulationSpeed * m_realRelTime; + m_relTime = (m_simulationSpeed * m_realRelTime) / 1e9f; + } Event frameEvent(EVENT_FRAME); frameEvent.systemEvent = true; @@ -1651,12 +1664,12 @@ bool CApplication::GetLowCPU() void CApplication::StartPerformanceCounter(PerformanceCounter counter) { - GetCurrentTimeStamp(m_performanceCounters[counter][0]); + GetSystemUtils()->GetCurrentTimeStamp(m_performanceCounters[counter][0]); } void CApplication::StopPerformanceCounter(PerformanceCounter counter) { - GetCurrentTimeStamp(m_performanceCounters[counter][1]); + GetSystemUtils()->GetCurrentTimeStamp(m_performanceCounters[counter][1]); } float CApplication::GetPerformanceCounterData(PerformanceCounter counter) @@ -1675,13 +1688,13 @@ void CApplication::ResetPerformanceCounters() void CApplication::UpdatePerformanceCountersData() { - long long sum = TimeStampExactDiff(m_performanceCounters[PCNT_ALL][0], - m_performanceCounters[PCNT_ALL][1]); + long long sum = GetSystemUtils()->TimeStampExactDiff(m_performanceCounters[PCNT_ALL][0], + m_performanceCounters[PCNT_ALL][1]); for (int i = 0; i < PCNT_MAX; ++i) { - long long diff = TimeStampExactDiff(m_performanceCounters[i][0], - m_performanceCounters[i][1]); + long long diff = GetSystemUtils()->TimeStampExactDiff(m_performanceCounters[i][0], + m_performanceCounters[i][1]); m_performanceCountersData[static_cast(i)] = static_cast(diff) / static_cast(sum); diff --git a/src/app/app.h b/src/app/app.h index 71a3527..d2561e7 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -352,7 +352,7 @@ protected: //! If applicable, creates a virtual event to match the changed state as of new event Event CreateVirtualEvent(const Event& sourceEvent); //! Prepares a simulation update event - Event CreateUpdateEvent(); + TEST_VIRTUAL Event CreateUpdateEvent(); //! Handles some incoming events bool ProcessEvent(const Event& event); //! Renders the image in window diff --git a/src/app/main.cpp b/src/app/main.cpp index 0622370..edb5828 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -76,40 +76,46 @@ extern "C" int SDL_MAIN_FUNC(int argc, char *argv[]) { - CLogger logger; // Create the logger + CLogger logger; // single istance of logger - InitializeRestext(); // Initialize translation strings + InitializeRestext(); // init static translation strings + + CSystemUtils* systemUtils = CSystemUtils::Create(); // platform-specific utils + systemUtils->Init(); logger.Info("Colobot starting\n"); - CApplication app; // single instance of the application + CApplication* app = new CApplication(); // single instance of the application - ParseArgsStatus status = app.ParseArguments(argc, argv); + ParseArgsStatus status = app->ParseArguments(argc, argv); if (status == PARSE_ARGS_FAIL) { - SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); - return app.GetExitCode(); + systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); + return app->GetExitCode(); } else if (status == PARSE_ARGS_HELP) { - return app.GetExitCode(); + return app->GetExitCode(); } int code = 0; - if (! app.Create()) + if (! app->Create()) { - app.Destroy(); // ensure a clean exit - code = app.GetExitCode(); - if ( code != 0 && !app.GetErrorMessage().empty() ) + app->Destroy(); // ensure a clean exit + code = app->GetExitCode(); + if ( code != 0 && !app->GetErrorMessage().empty() ) { - SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app.GetErrorMessage()); + systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app->GetErrorMessage()); } logger.Info("Didn't run main loop. Exiting with code %d\n", code); return code; } - code = app.Run(); + code = app->Run(); + + delete app; + delete systemUtils; logger.Info("Exiting with code %d\n", code); return code; diff --git a/src/app/system.cpp b/src/app/system.cpp index 73614aa..6927af8 100644 --- a/src/app/system.cpp +++ b/src/app/system.cpp @@ -22,75 +22,142 @@ #if defined(PLATFORM_WINDOWS) -#include "app/system_windows.h" - + #include "app/system_windows.h" #elif defined(PLATFORM_LINUX) -#include "app/system_linux.h" - + #include "app/system_linux.h" #else -#include "app/system_other.h" - + #include "app/system_other.h" #endif - #include +#include + + +template<> +CSystemUtils* CSingleton::m_instance = nullptr; -/** - * Displays a system dialog with info, error, question etc. message. - * - * \param type type of dialog - * \param message text of message (in UTF-8) - * \param title dialog title (in UTF-8) - * \returns result (which button was clicked) - */ -SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) +CSystemUtils::CSystemUtils() { +} + +CSystemUtils* CSystemUtils::Create() +{ + assert(m_instance == nullptr); #if defined(PLATFORM_WINDOWS) - return SystemDialog_Windows(type, title, message); + m_instance = new CSystemUtilsWindows(); #elif defined(PLATFORM_LINUX) - return SystemDialog_Linux(type, title, message); + m_instance = new CSystemUtilsLinux(); #else - return SystemDialog_Other(type, title, message); + m_instance = new CSystemUtilsOther(); #endif + return m_instance; } -SystemTimeStamp* CreateTimeStamp() +SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, const std::string& title, const std::string& message) { - return new SystemTimeStamp(); + switch (type) + { + case SDT_INFO: + std::cout << "INFO: "; + break; + case SDT_WARNING: + std::cout << "WARNING:"; + break; + case SDT_ERROR: + std::cout << "ERROR: "; + break; + case SDT_YES_NO: + case SDT_OK_CANCEL: + std::cout << "QUESTION: "; + break; + } + + std::cout << message << std::endl; + + std::string line; + + SystemDialogResult result = SDR_OK; + + bool done = false; + while (!done) + { + switch (type) + { + case SDT_INFO: + case SDT_WARNING: + case SDT_ERROR: + std::cout << "Press ENTER to continue"; + break; + + case SDT_YES_NO: + std::cout << "Type 'Y' for Yes or 'N' for No"; + break; + + case SDT_OK_CANCEL: + std::cout << "Type 'O' for OK or 'C' for Cancel"; + break; + } + + std::getline(std::cin, line); + + switch (type) + { + case SDT_INFO: + case SDT_WARNING: + case SDT_ERROR: + done = true; + break; + + case SDT_YES_NO: + if (line == "Y" || line == "y") + { + result = SDR_YES; + done = true; + } + else if (line == "N" || line == "n") + { + result = SDR_NO; + done = true; + } + break; + + case SDT_OK_CANCEL: + if (line == "O" || line == "o") + { + done = true; + result = SDR_OK; + } + else if (line == "C" || line == "c") + { + done = true; + result = SDR_CANCEL; + } + break; + } + } + + return result; } -void DestroyTimeStamp(SystemTimeStamp *stamp) +SystemTimeStamp* CSystemUtils::CreateTimeStamp() { - delete stamp; + return new SystemTimeStamp(); } -void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src) +void CSystemUtils::DestroyTimeStamp(SystemTimeStamp *stamp) { - *dst = *src; + delete stamp; } -void GetCurrentTimeStamp(SystemTimeStamp *stamp) +void CSystemUtils::CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src) { -#if defined(PLATFORM_WINDOWS) - GetCurrentTimeStamp_Windows(stamp); -#elif defined(PLATFORM_LINUX) - GetCurrentTimeStamp_Linux(stamp); -#else - GetCurrentTimeStamp_Other(stamp); -#endif + *dst = *src; } -float GetTimeStampResolution(SystemTimeUnit unit) +float CSystemUtils::GetTimeStampResolution(SystemTimeUnit unit) { - unsigned long long exact = 0; -#if defined(PLATFORM_WINDOWS) - exact = GetTimeStampExactResolution_Windows(); -#elif defined(PLATFORM_LINUX) - exact = GetTimeStampExactResolution_Linux(); -#else - exact = GetTimeStampExactResolution_Other(); -#endif + unsigned long long exact = GetTimeStampExactResolution(); float result = 0.0f; if (unit == STU_SEC) result = exact * 1e-9; @@ -100,30 +167,14 @@ float GetTimeStampResolution(SystemTimeUnit unit) result = exact * 1e-3; else assert(false); + return result; } -long long GetTimeStampExactResolution() +float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit) { -#if defined(PLATFORM_WINDOWS) - return GetTimeStampExactResolution_Windows(); -#elif defined(PLATFORM_LINUX) - return GetTimeStampExactResolution_Linux(); -#else - return GetTimeStampExactResolution_Other(); -#endif -} + long long exact = TimeStampExactDiff(before, after); -float TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit) -{ - long long exact = 0; -#if defined(PLATFORM_WINDOWS) - exact = TimeStampExactDiff_Windows(before, after); -#elif defined(PLATFORM_LINUX) - exact = TimeStampExactDiff_Linux(before, after); -#else - exact = TimeStampExactDiff_Other(before, after); -#endif float result = 0.0f; if (unit == STU_SEC) result = exact * 1e-9; @@ -133,16 +184,6 @@ float TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeU result = exact * 1e-3; else assert(false); - return result; -} -long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) -{ -#if defined(PLATFORM_WINDOWS) - return TimeStampExactDiff_Windows(before, after); -#elif defined(PLATFORM_LINUX) - return TimeStampExactDiff_Linux(before, after); -#else - return TimeStampExactDiff_Other(before, after); -#endif + return result; } diff --git a/src/app/system.h b/src/app/system.h index e216842..278a4bf 100644 --- a/src/app/system.h +++ b/src/app/system.h @@ -22,12 +22,10 @@ #pragma once +#include "common/singleton.h" #include - -/* Dialog utils */ - /** * \enum SystemDialogType * \brief Type of system dialog @@ -60,12 +58,10 @@ enum SystemDialogResult SDR_NO }; -//! Displays a system dialog -SystemDialogResult SystemDialog(SystemDialogType, const std::string &title, const std::string &message); - - -/* Time utils */ - +/** + * \enum SystemTimeUnit + * \brief Time unit + */ enum SystemTimeUnit { //! seconds @@ -76,33 +72,67 @@ enum SystemTimeUnit STU_USEC }; -/* Forward declaration of time stamp struct - * SystemTimeStamp should be used in a pointer context. - * The implementation details are hidden because of platform dependence. */ +/* + * Forward declaration of time stamp struct + * SystemTimeStamp should only be used in a pointer context. + * The implementation details are hidden because of platform dependence. + */ struct SystemTimeStamp; -//! Creates a new time stamp object -SystemTimeStamp* CreateTimeStamp(); +/** + * \class CSystemUtils + * \brief Platform-specific utils + * + * This class provides system-specific utilities like displaying user dialogs and + * querying system timers for exact timestamps. + */ +class CSystemUtils : public CSingleton +{ +protected: + CSystemUtils(); + +public: + //! Creates system utils for specific platform + static CSystemUtils* Create(); + + //! Performs platform-specific initialization + virtual void Init() = 0; + + //! Displays a system dialog + virtual SystemDialogResult SystemDialog(SystemDialogType, const std::string &title, const std::string &message) = 0; -//! Destroys a time stamp object -void DestroyTimeStamp(SystemTimeStamp *stamp); + //! Displays a fallback system dialog using console + TEST_VIRTUAL SystemDialogResult ConsoleSystemDialog(SystemDialogType type, const std::string& title, const std::string& message); -//! Copies the time stamp from \a src to \a dst -void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); + //! Creates a new time stamp object + TEST_VIRTUAL SystemTimeStamp* CreateTimeStamp(); -//! Returns a time stamp associated with current time -void GetCurrentTimeStamp(SystemTimeStamp *stamp); + //! Destroys a time stamp object + TEST_VIRTUAL void DestroyTimeStamp(SystemTimeStamp *stamp); -//! Returns the platform's expected time stamp resolution -float GetTimeStampResolution(SystemTimeUnit unit = STU_SEC); + //! Copies the time stamp from \a src to \a dst + TEST_VIRTUAL void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); -//! Returns the platform's exact (in nanosecond units) expected time stamp resolution -long long GetTimeStampExactResolution(); + //! Returns a time stamp associated with current time + virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) = 0; -//! Returns a difference between two timestamps in given time unit -/** The difference is \a after - \a before. */ -float TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit = STU_SEC); + //! Returns the platform's expected time stamp resolution + TEST_VIRTUAL float GetTimeStampResolution(SystemTimeUnit unit = STU_SEC); -//! Returns the exact (in nanosecond units) difference between two timestamps -/** The difference is \a after - \a before. */ -long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after); + //! Returns the platform's exact (in nanosecond units) expected time stamp resolution + virtual long long GetTimeStampExactResolution() = 0; + + //! Returns a difference between two timestamps in given time unit + /** The difference is \a after - \a before. */ + TEST_VIRTUAL float TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit = STU_SEC); + + //! Returns the exact (in nanosecond units) difference between two timestamps + /** The difference is \a after - \a before. */ + virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) = 0; +}; + +//! Global function to get CSystemUtils instance +inline CSystemUtils* GetSystemUtils() +{ + return CSystemUtils::GetInstancePointer(); +} diff --git a/src/app/system_linux.cpp b/src/app/system_linux.cpp index cd785f8..619909d 100644 --- a/src/app/system_linux.cpp +++ b/src/app/system_linux.cpp @@ -17,11 +17,28 @@ #include "app/system_linux.h" +#include "common/logger.h" + #include -SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message) +void CSystemUtilsLinux::Init() { + m_zenityAvailable = true; + if (system("zenity --version") != 0) + { + m_zenityAvailable = false; + GetLogger()->Warn("Zenity not available, will fallback to console users dialogs.\n"); + } +} + +SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) +{ + if (!m_zenityAvailable) + { + return ConsoleSystemDialog(type, title, message); + } + std::string options = ""; switch (type) { @@ -62,17 +79,17 @@ SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& return result; } -void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp) +void CSystemUtilsLinux::GetCurrentTimeStamp(SystemTimeStamp *stamp) { clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime); } -long long GetTimeStampExactResolution_Linux() +long long CSystemUtilsLinux::GetTimeStampExactResolution() { return 1ll; } -long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after) +long long CSystemUtilsLinux::TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) { return (after->clockTime.tv_nsec - before->clockTime.tv_nsec) + (after->clockTime.tv_sec - before->clockTime.tv_sec) * 1000000000ll; diff --git a/src/app/system_linux.h b/src/app/system_linux.h index bc07c31..ba0d8cd 100644 --- a/src/app/system_linux.h +++ b/src/app/system_linux.h @@ -35,9 +35,17 @@ struct SystemTimeStamp } }; +class CSystemUtilsLinux : public CSystemUtils +{ +public: + virtual void Init() override; + + virtual SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; -SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message); + virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; + virtual long long GetTimeStampExactResolution() override; + virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; -void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp); -long long GetTimeStampExactResolution_Linux(); -long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after); +private: + bool m_zenityAvailable; +}; diff --git a/src/app/system_other.cpp b/src/app/system_other.cpp index 006bf6d..9fc1f95 100644 --- a/src/app/system_other.cpp +++ b/src/app/system_other.cpp @@ -18,105 +18,22 @@ #include "app/system_other.h" -SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message) +SystemDialogResult CSystemUtilsOther::SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) { - switch (type) - { - case SDT_INFO: - std::cout << "INFO: "; - break; - case SDT_WARNING: - std::cout << "WARNING:"; - break; - case SDT_ERROR: - std::cout << "ERROR: "; - break; - case SDT_YES_NO: - case SDT_OK_CANCEL: - std::cout << "QUESTION: "; - break; - } - - std::cout << message << std::endl; - - std::string line; - - SystemDialogResult result = SDR_OK; - - bool done = false; - while (!done) - { - switch (type) - { - case SDT_INFO: - case SDT_WARNING: - case SDT_ERROR: - std::cout << "Press ENTER to continue"; - break; - - case SDT_YES_NO: - std::cout << "Type 'Y' for Yes or 'N' for No"; - break; - - case SDT_OK_CANCEL: - std::cout << "Type 'O' for OK or 'C' for Cancel"; - break; - } - - std::getline(std::cin, line); - - switch (type) - { - case SDT_INFO: - case SDT_WARNING: - case SDT_ERROR: - done = true; - break; - - case SDT_YES_NO: - if (line == "Y" || line == "y") - { - result = SDR_YES; - done = true; - } - else if (line == "N" || line == "n") - { - result = SDR_NO; - done = true; - } - break; - - case SDT_OK_CANCEL: - if (line == "O" || line == "o") - { - done = true; - result = SDR_OK; - } - else if (line == "C" || line == "c") - { - done = true; - result = SDR_CANCEL; - } - break; - } - } - - return result; + return ConsoleSystemDialog(type, title, message); } - - -void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp) +void CSystemUtilsOther::GetCurrentTimeStamp(SystemTimeStamp* stamp) { stamp->sdlTicks = SDL_GetTicks(); } -long long GetTimeStampExactResolution_Other() +long long int CSystemUtilsOther::GetTimeStampExactResolution() { return 1000000ll; } -long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after) +long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) const { return (after->sdlTicks - before->sdlTicks) * 1000000ll; } diff --git a/src/app/system_other.h b/src/app/system_other.h index aee3536..bf16c80 100644 --- a/src/app/system_other.h +++ b/src/app/system_other.h @@ -37,9 +37,12 @@ struct SystemTimeStamp } }; +class CSystemUtilsOther : public CSystemUtils +{ +public: + virtual SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; -SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message); - -void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp); -long long GetTimeStampExactResolution_Other(); -long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after); + virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; + virtual long long GetTimeStampExactResolution() override; + virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; +}; diff --git a/src/app/system_windows.cpp b/src/app/system_windows.cpp index 34fa57e..780afef 100644 --- a/src/app/system_windows.cpp +++ b/src/app/system_windows.cpp @@ -17,30 +17,25 @@ #include "app/system_windows.h" +#include "common/logger.h" + +#include -// Convert a wide Unicode string to an UTF8 string -std::string UTF8_Encode_Windows(const std::wstring &wstr) -{ - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast(wstr.size()), NULL, 0, NULL, NULL); - std::string strTo(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast(wstr.size()), &strTo[0], size_needed, NULL, NULL); - return strTo; -} -// Convert an UTF8 string to a wide Unicode String -std::wstring UTF8_Decode_Windows(const std::string &str) +void CSystemUtilsWindows::Init() { - int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast(str.size()), NULL, 0); - std::wstring wstrTo(size_needed, 0); - MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast(str.size()), &wstrTo[0], size_needed); - return wstrTo; + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + m_counterFrequency = freq.QuadPart; + + assert(m_counterFrequency != 0); } -SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message) +SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) { unsigned int windowsType = 0; - std::wstring windowsMessage = UTF8_Decode_Windows(message); - std::wstring windowsTitle = UTF8_Decode_Windows(title); + std::wstring windowsMessage = UTF8_Decode(message); + std::wstring windowsTitle = UTF8_Decode(title); switch (type) { @@ -79,20 +74,39 @@ SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string return SDR_OK; } +void CSystemUtilsWindows::GetCurrentTimeStamp(SystemTimeStamp* stamp) +{ + LARGE_INTEGER value; + QueryPerformanceCounter(&value); + stamp->counterValue = value.QuadPart; +} + +long long int CSystemUtilsWindows::GetTimeStampExactResolution() +{ + return 1000000000ll / m_counterFrequency; +} -void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp) +long long int CSystemUtilsWindows::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) { - GetSystemTimeAsFileTime(&stamp->fileTime); + float floatValue = static_cast(after->counterValue - before->counterValue) * (1e9 / static_cast(m_counterFrequency)); + return static_cast(floatValue); } -long long GetTimeStampExactResolution_Windows() +//! Converts a wide Unicode string to an UTF8 string +std::string CSystemUtilsWindows::UTF8_Encode(const std::wstring& wstr) { - return 100ll; + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast(wstr.size()), NULL, 0, NULL, NULL); + std::string strTo(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast(wstr.size()), &strTo[0], size_needed, NULL, NULL); + return strTo; } -long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after) +//! Converts an UTF8 string to a wide Unicode String +std::wstring CSystemUtilsWindows::UTF8_Decode(const std::string& str) { - long long tH = (1ll << 32) * (after->fileTime.dwHighDateTime - before->fileTime.dwHighDateTime); - long long tL = after->fileTime.dwLowDateTime - before->fileTime.dwLowDateTime; - return (tH + tL) * 100ll; + int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast(str.size()), NULL, 0); + std::wstring wstrTo(size_needed, 0); + MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast(str.size()), &wstrTo[0], size_needed); + return wstrTo; + } diff --git a/src/app/system_windows.h b/src/app/system_windows.h index 804d064..e367b92 100644 --- a/src/app/system_windows.h +++ b/src/app/system_windows.h @@ -22,23 +22,32 @@ #include "app/system.h" -#include - struct SystemTimeStamp { - FILETIME fileTime; + long long counterValue; SystemTimeStamp() { - fileTime.dwHighDateTime = fileTime.dwLowDateTime = 0; + counterValue = 0; } }; -std::string UTF8_Encode_Windows(const std::wstring &wstr); -std::wstring UTF8_Decode_Windows(const std::string &str); -SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message); +class CSystemUtilsWindows : public CSystemUtils +{ +public: + virtual void Init() override; + + virtual SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; -void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp); -long long GetTimeStampExactResolution_Windows(); -long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after); + virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; + virtual long long GetTimeStampExactResolution() override; + virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; + +private: + std::string UTF8_Encode(const std::wstring &wstr); + std::wstring UTF8_Decode(const std::string &str); + +protected: + long long m_counterFrequency; +}; -- cgit v1.2.3-1-g7c22