From 2a003a27b1045e4ed3f5d6bb4977b2d174a5c36c Mon Sep 17 00:00:00 2001 From: AbigailBuccaneer Date: Thu, 19 Apr 2018 20:29:06 +0100 Subject: [PATCH 1/7] Use C++11 threads, mutexes and condition variables --- src/CMakeLists.txt | 4 - src/app/app.cpp | 10 +- src/common/event.cpp | 19 +-- src/common/event.h | 5 +- src/common/thread/resource_owning_thread.h | 133 --------------------- src/common/thread/sdl_cond_wrapper.h | 62 ---------- src/common/thread/sdl_mutex_wrapper.h | 60 ---------- src/common/thread/thread.h | 77 ------------ src/common/thread/worker_thread.h | 49 ++++---- src/graphics/engine/engine.cpp | 6 +- src/sound/oalsound/alsound.cpp | 3 +- 11 files changed, 33 insertions(+), 395 deletions(-) delete mode 100644 src/common/thread/resource_owning_thread.h delete mode 100644 src/common/thread/sdl_cond_wrapper.h delete mode 100644 src/common/thread/sdl_mutex_wrapper.h delete mode 100644 src/common/thread/thread.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0857506..271aa75b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -150,10 +150,6 @@ set(BASE_SOURCES common/singleton.h common/stringutils.cpp common/stringutils.h - common/thread/resource_owning_thread.h - common/thread/sdl_cond_wrapper.h - common/thread/sdl_mutex_wrapper.h - common/thread/thread.h common/thread/worker_thread.h graphics/core/color.cpp graphics/core/color.h diff --git a/src/app/app.cpp b/src/app/app.cpp index ef929e43..4ef861f6 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -36,8 +36,6 @@ #include "common/system/system.h" -#include "common/thread/thread.h" - #include "graphics/core/nulldevice.h" #include "graphics/opengl/glutil.h" @@ -60,6 +58,7 @@ #include #include #include +#include char CApplication::m_languageLocale[] = { 0 }; @@ -671,8 +670,7 @@ bool CApplication::Create() // Create the robot application. m_controller = MakeUnique(); - CThread musicLoadThread([this]() - { + std::thread{[this]() { GetLogger()->Debug("Cache sounds...\n"); SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); m_systemUtils->GetCurrentTimeStamp(musicLoadStart); @@ -683,9 +681,7 @@ bool CApplication::Create() m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); - }, - "Sound loading thread"); - musicLoadThread.Start(); + }}.detach(); if (m_runSceneCategory == LevelCategory::Max) m_controller->StartApp(); diff --git a/src/common/event.cpp b/src/common/event.cpp index 36f2bcb5..510cee7e 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -563,8 +563,7 @@ std::string ParseEventType(EventType eventType) CEventQueue::CEventQueue() - : m_mutex{}, - m_fifo(), + : m_fifo(), m_head{0}, m_tail{0}, m_total{0} @@ -582,15 +581,13 @@ bool CEventQueue::IsEmpty() Else, adds the event to the queue and returns \c true. */ bool CEventQueue::AddEvent(Event&& event) { - bool result{}; - - SDL_LockMutex(*m_mutex); + std::lock_guard lock{m_mutex}; if (m_total >= MAX_EVENT_QUEUE) { GetLogger()->Warn("Event queue flood!\n"); - result = false; + return false; } else { @@ -601,19 +598,15 @@ bool CEventQueue::AddEvent(Event&& event) m_total++; - result = true; + return true; } - - SDL_UnlockMutex(*m_mutex); - - return result; } Event CEventQueue::GetEvent() { Event event; - SDL_LockMutex(*m_mutex); + std::lock_guard lock{m_mutex}; if (m_head == m_tail) { @@ -630,7 +623,5 @@ Event CEventQueue::GetEvent() } - SDL_UnlockMutex(*m_mutex); - return event; } diff --git a/src/common/event.h b/src/common/event.h index fe9b6448..00ad33cb 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -27,12 +27,11 @@ #include "common/key.h" #include "common/make_unique.h" -#include "common/thread/sdl_mutex_wrapper.h" - #include "math/point.h" #include "math/vector.h" #include +#include /** \enum EventType @@ -888,7 +887,7 @@ public: Event GetEvent(); protected: - CSDLMutexWrapper m_mutex; + std::mutex m_mutex; Event m_fifo[MAX_EVENT_QUEUE]; int m_head; int m_tail; diff --git a/src/common/thread/resource_owning_thread.h b/src/common/thread/resource_owning_thread.h deleted file mode 100644 index 995cf4cb..00000000 --- a/src/common/thread/resource_owning_thread.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#pragma once - -#include "common/thread/sdl_cond_wrapper.h" -#include "common/thread/sdl_mutex_wrapper.h" - -#include - -#include -#include - -/** - * \class CResourceOwningThread - * \brief Wrapper around SDL thread allowing passing of resources in safe manner - * - * This class is a workaround for passing ownership of resources in a safe - * manner to newly created threads. It takes a pointer to a function to call - * in new thread and a unique_ptr to resource which is to be passed to the new thread. - * - * This is how it works: - * - in main thread: create a new thread passing to it a special temporary context, - * - in main thread: wait for synchronization signal that the ownership was passed, - * - in new thread: acquire the resource from the context - * - in new thread: signal back to main thread that the resource was acquired, - * - in main thread: clean up temporary context and exit - * - in new thread: run the specified function with the acquired resource. - * - * It's a bit complicated, but that's the safe (thread-safe and exception-safe) - * way of doing this. - */ -template -class CResourceOwningThread -{ -public: - using ResourceUPtr = std::unique_ptr; - using ThreadFunctionPtr = void(*)(ResourceUPtr); - - CResourceOwningThread(ThreadFunctionPtr threadFunction, ResourceUPtr resource, std::string name = "") - : m_threadFunction(threadFunction), - m_resource(std::move(resource)), - m_name(name) - {} - - ~CResourceOwningThread() - { - SDL_DetachThread(m_thread); - } - - void Start() - { - CSDLMutexWrapper mutex; - CSDLCondWrapper cond; - bool condition = false; - - ThreadData data; - data.resource = std::move(m_resource); - data.threadFunction = m_threadFunction; - data.mutex = &mutex; - data.cond = &cond; - data.condition = &condition; - - SDL_LockMutex(*mutex); - - m_thread = SDL_CreateThread(Run, !m_name.empty() ? m_name.c_str() : nullptr, reinterpret_cast(&data)); - - while (!condition) - { - SDL_CondWait(*cond, *mutex); - } - - SDL_UnlockMutex(*mutex); - } - - void Join() - { - if (m_thread == nullptr) return; - SDL_WaitThread(m_thread, nullptr); - m_thread = nullptr; - } - -private: - static int Run(void* data) - { - ThreadFunctionPtr threadFunction = nullptr; - ResourceUPtr resource; - - ThreadData* threadData = reinterpret_cast(data); - SDL_LockMutex(**threadData->mutex); - - threadFunction = threadData->threadFunction; - resource = std::move(threadData->resource); - - *threadData->condition = true; - SDL_CondSignal(**threadData->cond); - SDL_UnlockMutex(**threadData->mutex); - - threadFunction(std::move(resource)); - return 0; - } - -private: - struct ThreadData - { - ResourceUPtr resource; - CSDLMutexWrapper* mutex = nullptr; - CSDLCondWrapper* cond = nullptr; - bool* condition = nullptr; - ThreadFunctionPtr threadFunction = nullptr; - }; - - ThreadFunctionPtr m_threadFunction; - ResourceUPtr m_resource; - std::string m_name; - SDL_Thread* m_thread = nullptr; -}; diff --git a/src/common/thread/sdl_cond_wrapper.h b/src/common/thread/sdl_cond_wrapper.h deleted file mode 100644 index 1be681cf..00000000 --- a/src/common/thread/sdl_cond_wrapper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#pragma once - -#include "common/thread/sdl_mutex_wrapper.h" - -#include - -/** - * \class CSDLCondWrapper - * \brief Wrapper for safe creation/deletion of SDL_cond - */ -class CSDLCondWrapper -{ -public: - CSDLCondWrapper() - : m_cond(SDL_CreateCond()) - {} - - ~CSDLCondWrapper() - { - SDL_DestroyCond(m_cond); - } - - CSDLCondWrapper(const CSDLCondWrapper&) = delete; - CSDLCondWrapper& operator=(const CSDLCondWrapper&) = delete; - - SDL_cond* operator*() - { - return m_cond; - } - - void Signal() - { - SDL_CondSignal(m_cond); - } - - void Wait(SDL_mutex* mutex) - { - SDL_CondWait(m_cond, mutex); - } - -private: - SDL_cond* m_cond; -}; diff --git a/src/common/thread/sdl_mutex_wrapper.h b/src/common/thread/sdl_mutex_wrapper.h deleted file mode 100644 index 476ddcae..00000000 --- a/src/common/thread/sdl_mutex_wrapper.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#pragma once - -#include - -/** - * \class CSDLMutexWrapper - * \brief Wrapper for safe creation/deletion of SDL_mutex - */ -class CSDLMutexWrapper -{ -public: - CSDLMutexWrapper() - : m_mutex(SDL_CreateMutex()) - {} - - ~CSDLMutexWrapper() - { - SDL_DestroyMutex(m_mutex); - } - - CSDLMutexWrapper(const CSDLMutexWrapper&) = delete; - CSDLMutexWrapper& operator=(const CSDLMutexWrapper&) = delete; - - SDL_mutex* operator*() - { - return m_mutex; - } - - void Lock() - { - SDL_LockMutex(m_mutex); - } - - void Unlock() - { - SDL_UnlockMutex(m_mutex); - } - -private: - SDL_mutex* m_mutex; -}; diff --git a/src/common/thread/thread.h b/src/common/thread/thread.h deleted file mode 100644 index 59433ae3..00000000 --- a/src/common/thread/thread.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#pragma once - -#include "common/make_unique.h" - -#include "common/thread/resource_owning_thread.h" - -#include -#include -#include - -/** - * \class CThread - * \brief Wrapper for using SDL_thread with std::function - */ -class CThread -{ -public: - using ThreadFunctionPtr = std::function; - -private: - struct ThreadData - { - ThreadFunctionPtr func; - }; - -public: - CThread(ThreadFunctionPtr func, std::string name = "") - : m_func(std::move(func)) - , m_name(name) - {} - - void Start() - { - std::unique_ptr data = MakeUnique(); - data->func = m_func; - m_thread = MakeUnique>(Run, std::move(data), m_name); - m_thread->Start(); - } - - void Join() - { - if (!m_thread) return; - m_thread->Join(); - } - - CThread(const CThread&) = delete; - CThread& operator=(const CThread&) = delete; - -private: - static void Run(std::unique_ptr data) - { - data->func(); - } - - std::unique_ptr> m_thread; - ThreadFunctionPtr m_func; - std::string m_name; -}; diff --git a/src/common/thread/worker_thread.h b/src/common/thread/worker_thread.h index ad127556..44b6bf41 100644 --- a/src/common/thread/worker_thread.h +++ b/src/common/thread/worker_thread.h @@ -21,13 +21,12 @@ #include "common/make_unique.h" -#include "common/thread/sdl_cond_wrapper.h" -#include "common/thread/sdl_mutex_wrapper.h" -#include "common/thread/thread.h" - +#include #include -#include +#include #include +#include +#include /** * \class CWorkerThread @@ -39,27 +38,23 @@ public: using ThreadFunctionPtr = std::function; public: - CWorkerThread(std::string name = "") - : m_thread(std::bind(&CWorkerThread::Run, this), name) - { - m_thread.Start(); - } + CWorkerThread() : m_thread{&CWorkerThread::Run, this} {} ~CWorkerThread() { - m_mutex.Lock(); - m_running = false; - m_cond.Signal(); - m_mutex.Unlock(); - m_thread.Join(); + { + std::lock_guard lock{m_mutex}; + m_running = false; + m_cond.notify_one(); + } + m_thread.join(); } - void Start(ThreadFunctionPtr func) + void Start(ThreadFunctionPtr&& func) { - m_mutex.Lock(); + std::lock_guard lock{m_mutex}; m_queue.push(func); - m_cond.Signal(); - m_mutex.Unlock(); + m_cond.notify_one(); } CWorkerThread(const CWorkerThread&) = delete; @@ -68,25 +63,21 @@ public: private: void Run() { - m_mutex.Lock(); + auto lock = std::unique_lock(m_mutex); while (true) { - while (m_queue.empty() && m_running) - { - m_cond.Wait(*m_mutex); - } + m_cond.wait(lock, [&]() { return !m_running || !m_queue.empty(); }); if (!m_running) break; - ThreadFunctionPtr func = m_queue.front(); + ThreadFunctionPtr func = std::move(m_queue.front()); m_queue.pop(); func(); } - m_mutex.Unlock(); } - CThread m_thread; - CSDLMutexWrapper m_mutex; - CSDLCondWrapper m_cond; + std::thread m_thread; + std::mutex m_mutex; + std::condition_variable m_cond; bool m_running = true; std::queue m_queue; }; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index e489b1e8..0f86e6fd 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -32,8 +32,6 @@ #include "common/system/system.h" -#include "common/thread/resource_owning_thread.h" - #include "graphics/core/device.h" #include "graphics/core/framebuffer.h" @@ -63,6 +61,7 @@ #include #include #include +#include // Graphics module namespace namespace Gfx @@ -500,8 +499,7 @@ void CEngine::WriteScreenShot(const std::string& fileName) data->fileName = fileName; - CResourceOwningThread thread(CEngine::WriteScreenShotThread, std::move(data), "WriteScreenShot thread"); - thread.Start(); + std::thread{&CEngine::WriteScreenShotThread, std::move(data)}.detach(); } void CEngine::WriteScreenShotThread(std::unique_ptr data) diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp index e4d457d3..c682e8b7 100644 --- a/src/sound/oalsound/alsound.cpp +++ b/src/sound/oalsound/alsound.cpp @@ -32,8 +32,7 @@ CALSound::CALSound() m_musicVolume(1.0f), m_channelsLimit(2048), m_device{}, - m_context{}, - m_thread("Music loading thread") + m_context{} { } From 285350464fc997482e71ffeffc4c1bd63e8df755 Mon Sep 17 00:00:00 2001 From: AbigailBuccaneer Date: Thu, 19 Apr 2018 21:06:56 +0100 Subject: [PATCH 2/7] Remove platform-specific handling of times Now all platforms use std::chrono::high_resolution_clock and std::this_thread::sleep_for instead of platform-specific timestamp and sleep methods. --- src/common/system/system.cpp | 16 +++++++++++++++ src/common/system/system.h | 14 +++++--------- src/common/system/system_linux.cpp | 16 --------------- src/common/system/system_linux.h | 10 ---------- src/common/system/system_macosx.cpp | 5 ----- src/common/system/system_macosx.h | 2 -- src/common/system/system_other.cpp | 15 -------------- src/common/system/system_other.h | 15 -------------- src/common/system/system_windows.cpp | 29 ---------------------------- src/common/system/system_windows.h | 13 ------------- 10 files changed, 21 insertions(+), 114 deletions(-) diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index 01b633cc..81d12640 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -37,6 +37,7 @@ #include #include #include +#include std::unique_ptr CSystemUtils::Create() @@ -161,6 +162,16 @@ void CSystemUtils::CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src) *dst = *src; } +void CSystemUtils::GetCurrentTimeStamp(SystemTimeStamp *stamp) +{ + *stamp = std::chrono::high_resolution_clock::now(); +} + +long long CSystemUtils::TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) +{ + return std::chrono::duration_cast(*after - *before).count(); +} + float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit) { long long exact = TimeStampExactDiff(before, after); @@ -192,3 +203,8 @@ std::string CSystemUtils::GetSaveDir() { return std::string("saves"); } + +void CSystemUtils::Usleep(int usecs) +{ + std::this_thread::sleep_for(std::chrono::microseconds{usecs}); +} diff --git a/src/common/system/system.h b/src/common/system/system.h index aaf54954..4366d8c2 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -24,6 +24,7 @@ #pragma once +#include #include #include #include @@ -74,12 +75,7 @@ enum SystemTimeUnit STU_USEC }; -/* - * 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; +using SystemTimeStamp = std::chrono::time_point; /** * \class CSystemUtils @@ -115,7 +111,7 @@ public: TEST_VIRTUAL void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); //! Returns a time stamp associated with current time - virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) = 0; + TEST_VIRTUAL void GetCurrentTimeStamp(SystemTimeStamp *stamp); //! Returns a difference between two timestamps in given time unit /** The difference is \a after - \a before. */ @@ -123,7 +119,7 @@ public: //! 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; + virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after); //! Returns the data path (containing textures, levels, helpfiles, etc) virtual std::string GetDataPath(); @@ -135,7 +131,7 @@ public: virtual std::string GetSaveDir(); //! Sleep for given amount of microseconds - virtual void Usleep(int usecs) = 0; + virtual void Usleep(int usecs); private: std::vector> m_timeStamps; diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index 3cd25ed2..1c40a960 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -83,17 +83,6 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const return result; } -void CSystemUtilsLinux::GetCurrentTimeStamp(SystemTimeStamp *stamp) -{ - clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime); -} - -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; -} - std::string CSystemUtilsLinux::GetSaveDir() { std::string savegameDir; @@ -120,8 +109,3 @@ std::string CSystemUtilsLinux::GetSaveDir() return savegameDir; } - -void CSystemUtilsLinux::Usleep(int usec) -{ - usleep(usec); -} diff --git a/src/common/system/system_linux.h b/src/common/system/system_linux.h index f1576f31..23dc197f 100644 --- a/src/common/system/system_linux.h +++ b/src/common/system/system_linux.h @@ -28,11 +28,6 @@ //@colobot-lint-exclude UndefinedFunctionRule -struct SystemTimeStamp -{ - timespec clockTime = {0, 0}; -}; - class CSystemUtilsLinux : public CSystemUtils { public: @@ -40,13 +35,8 @@ public: SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; - void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; - long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; - std::string GetSaveDir() override; - void Usleep(int usec) override; - private: bool m_zenityAvailable = false; }; diff --git a/src/common/system/system_macosx.cpp b/src/common/system/system_macosx.cpp index ede5b481..f41c0f29 100644 --- a/src/common/system/system_macosx.cpp +++ b/src/common/system/system_macosx.cpp @@ -107,8 +107,3 @@ std::string CSystemUtilsMacOSX::GetSaveDir() return savegameDir; } - -void CSystemUtilsMacOSX::Usleep(int usec) -{ - usleep(usec); -} diff --git a/src/common/system/system_macosx.h b/src/common/system/system_macosx.h index 5b572ec4..233a3c1d 100644 --- a/src/common/system/system_macosx.h +++ b/src/common/system/system_macosx.h @@ -36,8 +36,6 @@ public: std::string GetLangPath() override; std::string GetSaveDir() override; - void Usleep(int usec) override; - private: std::string m_ASPath; std::string m_dataPath; diff --git a/src/common/system/system_other.cpp b/src/common/system/system_other.cpp index a3311a74..91e61f84 100644 --- a/src/common/system/system_other.cpp +++ b/src/common/system/system_other.cpp @@ -28,18 +28,3 @@ SystemDialogResult CSystemUtilsOther::SystemDialog(SystemDialogType type, const { return ConsoleSystemDialog(type, title, message); } - -void CSystemUtilsOther::GetCurrentTimeStamp(SystemTimeStamp* stamp) -{ - stamp->sdlTicks = SDL_GetTicks(); -} - -long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) -{ - return (after->sdlTicks - before->sdlTicks) * 1000000ll; -} - -void CSystemUtilsOther::Usleep(int usec) -{ - SDL_Delay(usec / 1000); // close enough -} diff --git a/src/common/system/system_other.h b/src/common/system/system_other.h index ac80701b..ba87b842 100644 --- a/src/common/system/system_other.h +++ b/src/common/system/system_other.h @@ -30,26 +30,11 @@ //@colobot-lint-exclude UndefinedFunctionRule -struct SystemTimeStamp -{ - Uint32 sdlTicks; - - SystemTimeStamp() - { - sdlTicks = 0; - } -}; - class CSystemUtilsOther : public CSystemUtils { public: void Init() override; SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; - - void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; - long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; - - void Usleep(int usec) override; }; //@end-colobot-lint-exclude diff --git a/src/common/system/system_windows.cpp b/src/common/system/system_windows.cpp index f51959b4..bb32283e 100644 --- a/src/common/system/system_windows.cpp +++ b/src/common/system/system_windows.cpp @@ -26,11 +26,6 @@ void CSystemUtilsWindows::Init() { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - m_counterFrequency = freq.QuadPart; - - assert(m_counterFrequency != 0); } SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) @@ -76,19 +71,6 @@ SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, cons return SDR_OK; } -void CSystemUtilsWindows::GetCurrentTimeStamp(SystemTimeStamp* stamp) -{ - LARGE_INTEGER value; - QueryPerformanceCounter(&value); - stamp->counterValue = value.QuadPart; -} - -long long int CSystemUtilsWindows::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) -{ - float floatValue = static_cast(after->counterValue - before->counterValue) * (1e9 / static_cast(m_counterFrequency)); - return static_cast(floatValue); -} - //! Converts a wide Unicode string to an UTF8 string std::string CSystemUtilsWindows::UTF8_Encode(const std::wstring& wstr) { @@ -125,14 +107,3 @@ std::string CSystemUtilsWindows::GetSaveDir() return savegameDir; } - -void CSystemUtilsWindows::Usleep(int usec) -{ - LARGE_INTEGER ft; - ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time - - HANDLE timer = CreateWaitableTimer(nullptr, TRUE, nullptr); - SetWaitableTimer(timer, &ft, 0, nullptr, nullptr, 0); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); -} diff --git a/src/common/system/system_windows.h b/src/common/system/system_windows.h index 74f02455..3d437a7c 100644 --- a/src/common/system/system_windows.h +++ b/src/common/system/system_windows.h @@ -26,11 +26,6 @@ //@colobot-lint-exclude UndefinedFunctionRule -struct SystemTimeStamp -{ - long long counterValue = 0; -}; - class CSystemUtilsWindows : public CSystemUtils { public: @@ -38,19 +33,11 @@ public: SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; - void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; - long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; - std::string GetSaveDir() override; - void Usleep(int usec) override; - public: static std::string UTF8_Encode(const std::wstring &wstr); static std::wstring UTF8_Decode(const std::string &str); - -protected: - long long m_counterFrequency = 0; }; //@end-colobot-lint-exclude From 4119e669d1b86726676443cb9128c459bf3354ed Mon Sep 17 00:00:00 2001 From: AbigailBuccaneer Date: Thu, 19 Apr 2018 22:17:28 +0100 Subject: [PATCH 3/7] Remove central tracking of SystemTimeStamp SystemTimeStamp used to be an opaque class, as it was provided by `system_{linux/other/windows}.h`. Because of this, code dealt in SystemTimeStamp pointers, and getting the current timestamp required a memory allocation. Now SystemTimeStamp is just a `std::chrono::time_point`, we can make the code cleaner and faster by just directly keeping SystemTimeStamp instead of pointers around. --- src/app/app.cpp | 41 +++------- src/app/app.h | 12 +-- src/common/profiler.cpp | 10 +-- src/common/profiler.h | 4 +- src/common/system/system.cpp | 28 ++----- src/common/system/system.h | 20 +---- src/graphics/engine/engine.cpp | 14 +--- src/graphics/engine/engine.h | 6 +- test/unit/CMakeLists.txt | 9 +-- test/unit/app/app_test.cpp | 48 +----------- test/unit/common/system/system_linux_test.cpp | 77 ------------------- test/unit/common/system/system_test.cpp | 37 +++++++++ .../common/system/system_windows_test.cpp | 69 ----------------- 13 files changed, 81 insertions(+), 294 deletions(-) delete mode 100644 test/unit/common/system/system_linux_test.cpp create mode 100644 test/unit/common/system/system_test.cpp delete mode 100644 test/unit/common/system/system_windows_test.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 4ef861f6..7f278636 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -135,14 +135,6 @@ CApplication::CApplication(CSystemUtils* systemUtils) m_absTime = 0.0f; m_relTime = 0.0f; - m_baseTimeStamp = m_systemUtils->CreateTimeStamp(); - m_curTimeStamp = m_systemUtils->CreateTimeStamp(); - m_lastTimeStamp = m_systemUtils->CreateTimeStamp(); - - m_manualFrameLast = m_systemUtils->CreateTimeStamp(); - m_manualFrameTime = m_systemUtils->CreateTimeStamp(); - - m_joystickEnabled = false; m_mouseMode = MOUSE_SYSTEM; @@ -159,13 +151,6 @@ CApplication::CApplication(CSystemUtils* systemUtils) CApplication::~CApplication() { - m_systemUtils->DestroyTimeStamp(m_baseTimeStamp); - m_systemUtils->DestroyTimeStamp(m_curTimeStamp); - m_systemUtils->DestroyTimeStamp(m_lastTimeStamp); - - m_systemUtils->DestroyTimeStamp(m_manualFrameLast); - m_systemUtils->DestroyTimeStamp(m_manualFrameTime); - m_joystickEnabled = false; m_controller.reset(); @@ -672,13 +657,11 @@ bool CApplication::Create() std::thread{[this]() { GetLogger()->Debug("Cache sounds...\n"); - SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadStart); + SystemTimeStamp musicLoadStart = m_systemUtils->GetCurrentTimeStamp(); m_sound->CacheAll(); - SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); + SystemTimeStamp musicLoadEnd = m_systemUtils->GetCurrentTimeStamp(); float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); }}.detach(); @@ -984,9 +967,9 @@ int CApplication::Run() { m_active = true; - m_systemUtils->GetCurrentTimeStamp(m_baseTimeStamp); - m_systemUtils->GetCurrentTimeStamp(m_lastTimeStamp); - m_systemUtils->GetCurrentTimeStamp(m_curTimeStamp); + m_baseTimeStamp = m_systemUtils->GetCurrentTimeStamp(); + m_lastTimeStamp = m_systemUtils->GetCurrentTimeStamp(); + m_curTimeStamp = m_systemUtils->GetCurrentTimeStamp(); MoveMouse(Math::Point(0.5f, 0.5f)); // center mouse on start @@ -1410,13 +1393,13 @@ void CApplication::Render() void CApplication::RenderIfNeeded(int updateRate) { - m_systemUtils->GetCurrentTimeStamp(m_manualFrameTime); + m_manualFrameTime = m_systemUtils->GetCurrentTimeStamp(); long long diff = m_systemUtils->TimeStampExactDiff(m_manualFrameLast, m_manualFrameTime); if (diff < 1e9f / updateRate) { return; } - m_systemUtils->CopyTimeStamp(m_manualFrameLast, m_manualFrameTime); + m_manualFrameLast = m_manualFrameTime; Render(); } @@ -1444,8 +1427,8 @@ void CApplication::ResetTimeAfterLoading() void CApplication::InternalResumeSimulation() { - m_systemUtils->GetCurrentTimeStamp(m_baseTimeStamp); - m_systemUtils->CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp); + m_baseTimeStamp = m_systemUtils->GetCurrentTimeStamp(); + m_curTimeStamp = m_baseTimeStamp; m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; } @@ -1459,7 +1442,7 @@ void CApplication::SetSimulationSpeed(float speed) { m_simulationSpeed = speed; - m_systemUtils->GetCurrentTimeStamp(m_baseTimeStamp); + m_baseTimeStamp = m_systemUtils->GetCurrentTimeStamp(); m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; @@ -1471,8 +1454,8 @@ Event CApplication::CreateUpdateEvent() if (m_simulationSuspended) return Event(EVENT_NULL); - m_systemUtils->CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); - m_systemUtils->GetCurrentTimeStamp(m_curTimeStamp); + m_lastTimeStamp = m_curTimeStamp; + m_curTimeStamp = m_systemUtils->GetCurrentTimeStamp(); long long absDiff = m_systemUtils->TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); long long newRealAbsTime = m_realAbsTimeBase + absDiff; diff --git a/src/app/app.h b/src/app/app.h index ccae3a5c..c41b6106 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -27,6 +27,7 @@ #include "common/event.h" #include "common/language.h" #include "common/singleton.h" +#include "common/system/system.h" #include "graphics/core/device.h" @@ -45,7 +46,6 @@ class CInput; class CPathManager; class CConfigFile; class CSystemUtils; -struct SystemTimeStamp; namespace Gfx { @@ -339,9 +339,9 @@ protected: //! Animation time stamps, etc. //@{ - SystemTimeStamp* m_baseTimeStamp; - SystemTimeStamp* m_lastTimeStamp; - SystemTimeStamp* m_curTimeStamp; + SystemTimeStamp m_baseTimeStamp; + SystemTimeStamp m_lastTimeStamp; + SystemTimeStamp m_curTimeStamp; long long m_realAbsTimeBase; long long m_realAbsTime; @@ -358,8 +358,8 @@ protected: bool m_simulationSuspended; //@} - SystemTimeStamp* m_manualFrameLast; - SystemTimeStamp* m_manualFrameTime; + SystemTimeStamp m_manualFrameLast; + SystemTimeStamp m_manualFrameTime; //! Graphics device to use bool m_graphicsOverride = false; diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp index ff46036e..b3b418bc 100644 --- a/src/common/profiler.cpp +++ b/src/common/profiler.cpp @@ -26,7 +26,7 @@ CSystemUtils* CProfiler::m_systemUtils = nullptr; long long CProfiler::m_performanceCounters[PCNT_MAX] = {0}; long long CProfiler::m_prevPerformanceCounters[PCNT_MAX] = {0}; -std::stack CProfiler::m_runningPerformanceCounters; +std::stack CProfiler::m_runningPerformanceCounters; std::stack CProfiler::m_runningPerformanceCountersType; void CProfiler::SetSystemUtils(CSystemUtils* systemUtils) @@ -39,8 +39,7 @@ void CProfiler::StartPerformanceCounter(PerformanceCounter counter) if (counter == PCNT_ALL) ResetPerformanceCounters(); - SystemTimeStamp* timeStamp = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(timeStamp); + SystemTimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); m_runningPerformanceCounters.push(timeStamp); m_runningPerformanceCountersType.push(counter); } @@ -50,11 +49,8 @@ void CProfiler::StopPerformanceCounter(PerformanceCounter counter) assert(m_runningPerformanceCountersType.top() == counter); m_runningPerformanceCountersType.pop(); - SystemTimeStamp* timeStamp = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(timeStamp); + SystemTimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); m_performanceCounters[counter] += m_systemUtils->TimeStampExactDiff(m_runningPerformanceCounters.top(), timeStamp); - m_systemUtils->DestroyTimeStamp(timeStamp); - m_systemUtils->DestroyTimeStamp(m_runningPerformanceCounters.top()); m_runningPerformanceCounters.pop(); if (counter == PCNT_ALL) diff --git a/src/common/profiler.h b/src/common/profiler.h index 4caaea41..d9ff0797 100644 --- a/src/common/profiler.h +++ b/src/common/profiler.h @@ -20,8 +20,8 @@ #pragma once class CSystemUtils; -struct SystemTimeStamp; +#include "common/system/system.h" #include /** @@ -73,7 +73,7 @@ private: static long long m_performanceCounters[PCNT_MAX]; static long long m_prevPerformanceCounters[PCNT_MAX]; - static std::stack m_runningPerformanceCounters; + static std::stack m_runningPerformanceCounters; static std::stack m_runningPerformanceCountersType; }; diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index 81d12640..2d1c2a8d 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -144,35 +144,17 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons return result; } -SystemTimeStamp* CSystemUtils::CreateTimeStamp() +SystemTimeStamp CSystemUtils::GetCurrentTimeStamp() { - auto timeStamp = MakeUnique(); - SystemTimeStamp* timeStampPtr = timeStamp.get(); - m_timeStamps.push_back(std::move(timeStamp)); - return timeStampPtr; + return std::chrono::high_resolution_clock::now(); } -void CSystemUtils::DestroyTimeStamp(SystemTimeStamp *stamp) +long long CSystemUtils::TimeStampExactDiff(SystemTimeStamp before, SystemTimeStamp after) { - m_timeStamps.erase(std::remove_if(m_timeStamps.begin(), m_timeStamps.end(), [&](const std::unique_ptr& timeStamp) { return timeStamp.get() == stamp; })); + return std::chrono::duration_cast(after - before).count(); } -void CSystemUtils::CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src) -{ - *dst = *src; -} - -void CSystemUtils::GetCurrentTimeStamp(SystemTimeStamp *stamp) -{ - *stamp = std::chrono::high_resolution_clock::now(); -} - -long long CSystemUtils::TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) -{ - return std::chrono::duration_cast(*after - *before).count(); -} - -float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *after, SystemTimeUnit unit) +float CSystemUtils::TimeStampDiff(SystemTimeStamp before, SystemTimeStamp after, SystemTimeUnit unit) { long long exact = TimeStampExactDiff(before, after); diff --git a/src/common/system/system.h b/src/common/system/system.h index 4366d8c2..30d9279d 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -101,25 +101,16 @@ public: //! Displays a fallback system dialog using console TEST_VIRTUAL SystemDialogResult ConsoleSystemDialog(SystemDialogType type, const std::string& title, const std::string& message); - //! Creates a new time stamp object - TEST_VIRTUAL SystemTimeStamp* CreateTimeStamp(); - - //! Destroys a time stamp object - TEST_VIRTUAL void DestroyTimeStamp(SystemTimeStamp *stamp); - - //! Copies the time stamp from \a src to \a dst - TEST_VIRTUAL void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); - //! Returns a time stamp associated with current time - TEST_VIRTUAL void GetCurrentTimeStamp(SystemTimeStamp *stamp); + TEST_VIRTUAL SystemTimeStamp GetCurrentTimeStamp(); //! 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); + 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); + long long TimeStampExactDiff(SystemTimeStamp before, SystemTimeStamp after); //! Returns the data path (containing textures, levels, helpfiles, etc) virtual std::string GetDataPath(); @@ -131,8 +122,5 @@ public: virtual std::string GetSaveDir(); //! Sleep for given amount of microseconds - virtual void Usleep(int usecs); - -private: - std::vector> m_timeStamps; + void Usleep(int usecs); }; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 0f86e6fd..afb6f5a7 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -216,8 +216,6 @@ CEngine::CEngine(CApplication *app, CSystemUtils* systemUtils) m_mouseType = ENG_MOUSE_NORM; m_fpsCounter = 0; - m_lastFrameTime = m_systemUtils->CreateTimeStamp(); - m_currentFrameTime = m_systemUtils->CreateTimeStamp(); m_shadowColor = 0.5f; @@ -241,10 +239,6 @@ CEngine::CEngine(CApplication *app, CSystemUtils* systemUtils) CEngine::~CEngine() { - m_systemUtils->DestroyTimeStamp(m_lastFrameTime); - m_lastFrameTime = nullptr; - m_systemUtils->DestroyTimeStamp(m_currentFrameTime); - m_currentFrameTime = nullptr; } void CEngine::SetDevice(CDevice *device) @@ -361,8 +355,8 @@ bool CEngine::Create() params.mipmap = false; m_miceTexture = LoadTexture("textures/interface/mouse.png", params); - m_systemUtils->GetCurrentTimeStamp(m_currentFrameTime); - m_systemUtils->GetCurrentTimeStamp(m_lastFrameTime); + m_currentFrameTime = m_systemUtils->GetCurrentTimeStamp(); + m_lastFrameTime = m_systemUtils->GetCurrentTimeStamp(); return true; } @@ -3176,11 +3170,11 @@ void CEngine::Render() { m_fpsCounter++; - m_systemUtils->GetCurrentTimeStamp(m_currentFrameTime); + m_currentFrameTime = m_systemUtils->GetCurrentTimeStamp(); float diff = m_systemUtils->TimeStampDiff(m_lastFrameTime, m_currentFrameTime, STU_SEC); if (diff > 1.0f) { - m_systemUtils->CopyTimeStamp(m_lastFrameTime, m_currentFrameTime); + m_lastFrameTime = m_currentFrameTime; m_fps = m_fpsCounter / diff; m_fpsCounter = 0; diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 27f01585..33a1adad 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -25,6 +25,7 @@ #pragma once #include "common/singleton.h" +#include "common/system/system.h" #include "graphics/core/color.h" #include "graphics/core/material.h" @@ -50,7 +51,6 @@ class CApplication; class CSoundInterface; class CImage; class CSystemUtils; -struct SystemTimeStamp; struct Event; @@ -1303,8 +1303,8 @@ protected: //! Last encountered error std::string m_error; - SystemTimeStamp* m_lastFrameTime; - SystemTimeStamp* m_currentFrameTime; + SystemTimeStamp m_lastFrameTime; + SystemTimeStamp m_currentFrameTime; int m_fpsCounter; float m_fps; diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index c21fb600..613577d2 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,10 +1,3 @@ -# Platform-dependent tests -if(PLATFORM_WINDOWS) - set(PLATFORM_TESTS common/system/system_windows_test.cpp) -elseif(PLATFORM_LINUX) - set(PLATFORM_TESTS common/system/system_linux_test.cpp) -endif() - # Sources set(UT_SOURCES main.cpp @@ -12,12 +5,12 @@ set(UT_SOURCES CBot/CBotToken_test.cpp CBot/CBot_test.cpp common/config_file_test.cpp + common/system/system_test.cpp graphics/engine/lightman_test.cpp math/func_test.cpp math/geometry_test.cpp math/matrix_test.cpp math/vector_test.cpp - ${PLATFORM_TESTS} ) # Includes diff --git a/test/unit/app/app_test.cpp b/test/unit/app/app_test.cpp index 3ae5334d..8f13c8d0 100644 --- a/test/unit/app/app_test.cpp +++ b/test/unit/app/app_test.cpp @@ -32,14 +32,6 @@ using namespace HippoMocks; namespace ph = std::placeholders; -struct FakeSystemTimeStamp : public SystemTimeStamp -{ - FakeSystemTimeStamp(int uid) : uid(uid), time(0) {} - - int uid; - long long time; -}; - class CApplicationWrapper : public CApplication { public: @@ -66,7 +58,6 @@ class CApplicationUT : public testing::Test protected: CApplicationUT() : m_systemUtils(nullptr), - m_stampUid(0), m_currentTime(0) {} @@ -78,11 +69,7 @@ protected: void NextInstant(long long diff); - SystemTimeStamp* CreateTimeStamp(); - void DestroyTimeStamp(SystemTimeStamp *stamp); - void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); - void GetCurrentTimeStamp(SystemTimeStamp *stamp); - long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after); + SystemTimeStamp GetCurrentTimeStamp(); void TestCreateUpdateEvent(long long relTimeExact, long long absTimeExact, float relTime, float absTime, @@ -92,10 +79,8 @@ protected: std::unique_ptr m_app; MockRepository m_mocks; CSystemUtils* m_systemUtils; - std::vector> m_timeStamps; private: - int m_stampUid; long long m_currentTime; }; @@ -107,11 +92,7 @@ void CApplicationUT::SetUp() m_mocks.OnCall(m_systemUtils, CSystemUtils::GetLangPath).Return(""); m_mocks.OnCall(m_systemUtils, CSystemUtils::GetSaveDir).Return(""); - m_mocks.OnCall(m_systemUtils, CSystemUtils::CreateTimeStamp).Do(std::bind(&CApplicationUT::CreateTimeStamp, this)); - m_mocks.OnCall(m_systemUtils, CSystemUtils::DestroyTimeStamp).Do(std::bind(&CApplicationUT::DestroyTimeStamp, this, ph::_1)); - m_mocks.OnCall(m_systemUtils, CSystemUtils::CopyTimeStamp).Do(std::bind(&CApplicationUT::CopyTimeStamp, this, ph::_1, ph::_2)); - m_mocks.OnCall(m_systemUtils, CSystemUtils::GetCurrentTimeStamp).Do(std::bind(&CApplicationUT::GetCurrentTimeStamp, this, ph::_1)); - m_mocks.OnCall(m_systemUtils, CSystemUtils::TimeStampExactDiff).Do(std::bind(&CApplicationUT::TimeStampExactDiff, this, ph::_1, ph::_2)); + m_mocks.OnCall(m_systemUtils, CSystemUtils::GetCurrentTimeStamp).Do(std::bind(&CApplicationUT::GetCurrentTimeStamp, this)); m_app = MakeUnique(m_systemUtils); } @@ -121,31 +102,10 @@ void CApplicationUT::TearDown() m_app.reset(); } -SystemTimeStamp* CApplicationUT::CreateTimeStamp() -{ - auto stamp = MakeUnique(++m_stampUid); - auto stampPtr = stamp.get(); - m_timeStamps.push_back(std::move(stamp)); - return stampPtr; -} -void CApplicationUT::DestroyTimeStamp(SystemTimeStamp *stamp) +SystemTimeStamp CApplicationUT::GetCurrentTimeStamp() { -} - -void CApplicationUT::CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src) -{ - *static_cast(dst) = *static_cast(src); -} - -void CApplicationUT::GetCurrentTimeStamp(SystemTimeStamp *stamp) -{ - static_cast(stamp)->time = m_currentTime; -} - -long long CApplicationUT::TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) -{ - return static_cast(after)->time - static_cast(before)->time; + return SystemTimeStamp{SystemTimeStamp::duration{m_currentTime}}; } void CApplicationUT::NextInstant(long long diff) diff --git a/test/unit/common/system/system_linux_test.cpp b/test/unit/common/system/system_linux_test.cpp deleted file mode 100644 index a882f016..00000000 --- a/test/unit/common/system/system_linux_test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#include "common/system/system.h" -#include "common/system/system_linux.h" - -#include - -class CSystemUtilsLinuxUT : public testing::Test -{ -protected: - static const long long SEC = 1000000000; - - CSystemUtilsLinux m_systemUtils; -}; - - -TEST_F(CSystemUtilsLinuxUT, TimeStampDiff) -{ - SystemTimeStamp before, after; - - before.clockTime.tv_sec = 1; - before.clockTime.tv_nsec = 100; - - after.clockTime.tv_sec = 1; - after.clockTime.tv_nsec = 900; - - long long tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 800, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-800, tDiff); - - // ------- - - before.clockTime.tv_sec = 2; - before.clockTime.tv_nsec = 200; - - after.clockTime.tv_sec = 3; - after.clockTime.tv_nsec = 500; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( SEC + 300, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-SEC - 300, tDiff); - - // ------- - - before.clockTime.tv_sec = 3; - before.clockTime.tv_nsec = 200; - - after.clockTime.tv_sec = 4; - after.clockTime.tv_nsec = 100; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( SEC - 100, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-SEC + 100, tDiff); -} diff --git a/test/unit/common/system/system_test.cpp b/test/unit/common/system/system_test.cpp new file mode 100644 index 00000000..60447dd7 --- /dev/null +++ b/test/unit/common/system/system_test.cpp @@ -0,0 +1,37 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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 3 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, see http://gnu.org/licenses + */ + +#include "common/system/system_other.h" + +#include + +struct SystemTest : ::testing::Test { + CSystemUtilsOther system; +}; + +TEST_F(SystemTest, TimeStampExactDiff) { + auto epoch = SystemTimeStamp{}; + EXPECT_EQ(system.TimeStampExactDiff(epoch, epoch), 0); + + auto duration = std::chrono::microseconds{123456789L}; + auto before = std::chrono::high_resolution_clock::now(); + auto after = before + duration; + EXPECT_EQ(system.TimeStampExactDiff(before, after), std::chrono::nanoseconds{duration}.count()); + EXPECT_EQ(system.TimeStampExactDiff(after, before), -std::chrono::nanoseconds{duration}.count()); +} diff --git a/test/unit/common/system/system_windows_test.cpp b/test/unit/common/system/system_windows_test.cpp deleted file mode 100644 index f36e878c..00000000 --- a/test/unit/common/system/system_windows_test.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#include "common/system/system.h" -#include "common/system/system_windows.h" - -#include - -class CSystemUtilsWindowsWrapper : public CSystemUtilsWindows -{ -public: - void SetFrequency(long long frequency) - { - m_counterFrequency = frequency; - } -}; - -class CSystemUtilsWindowsUT : public testing::Test -{ -protected: - static const long long SEC = 1000000000; - - CSystemUtilsWindowsWrapper m_systemUtils; -}; - -TEST_F(CSystemUtilsWindowsUT, TimeStampDiff) -{ - m_systemUtils.SetFrequency(SEC); - - SystemTimeStamp before, after; - - before.counterValue = 100; - after.counterValue = 200; - - long long tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 100, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-100, tDiff); - - // ------- - - m_systemUtils.SetFrequency(SEC/3); - - before.counterValue = 200; - after.counterValue = 400; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 200*3, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-200*3, tDiff); -} From 5daaba6e646564af1424aa275a2036a2b0f93c1a Mon Sep 17 00:00:00 2001 From: MrSimbax Date: Sat, 11 Sep 2021 12:44:26 +0200 Subject: [PATCH 4/7] Fixes after merge Fix mistakes after previous merge and make it compile. Rewrite the function interpolating between time stamps as it was written after the original pull request was created. Add unit tests for it. I couldn't help myself and also changed some enums to enum classes and did some renames. --- src/app/app.cpp | 49 ++++-------- src/app/app.h | 2 +- src/app/main.cpp | 4 +- src/app/signal_handlers.cpp | 8 +- src/common/system/system.cpp | 51 ++++++------ src/common/system/system.h | 44 +++++------ src/common/system/system_linux.cpp | 33 +++----- src/common/system/system_linux.h | 4 - src/common/system/system_windows.cpp | 24 +++--- src/graphics/engine/engine.cpp | 2 +- test/unit/CMakeLists.txt | 15 +--- test/unit/app/app_test.cpp | 13 +--- test/unit/common/system/system_linux_test.cpp | 77 ------------------- test/unit/common/system/system_test.cpp | 46 ++++++++++- .../common/system/system_windows_test.cpp | 69 ----------------- 15 files changed, 146 insertions(+), 295 deletions(-) delete mode 100644 test/unit/common/system/system_linux_test.cpp delete mode 100644 test/unit/common/system/system_windows_test.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 74cc7e6b..c2264cf8 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -137,13 +137,6 @@ CApplication::CApplication(CSystemUtils* systemUtils) m_absTime = 0.0f; m_relTime = 0.0f; - m_baseTimeStamp = m_systemUtils->CreateTimeStamp(); - m_curTimeStamp = m_systemUtils->CreateTimeStamp(); - m_lastTimeStamp = m_systemUtils->CreateTimeStamp(); - - m_manualFrameLast = m_systemUtils->CreateTimeStamp(); - m_manualFrameTime = m_systemUtils->CreateTimeStamp(); - m_joystickEnabled = false; @@ -161,13 +154,6 @@ CApplication::CApplication(CSystemUtils* systemUtils) CApplication::~CApplication() { - m_systemUtils->DestroyTimeStamp(m_baseTimeStamp); - m_systemUtils->DestroyTimeStamp(m_curTimeStamp); - m_systemUtils->DestroyTimeStamp(m_lastTimeStamp); - - m_systemUtils->DestroyTimeStamp(m_manualFrameLast); - m_systemUtils->DestroyTimeStamp(m_manualFrameTime); - m_joystickEnabled = false; m_controller.reset(); @@ -674,7 +660,7 @@ bool CApplication::Create() { GetLogger()->Error("Unknown graphics device: %s\n", graphics.c_str()); GetLogger()->Info("Changing to default device\n"); - m_systemUtils->SystemDialog(SDT_ERROR, "Graphics initialization error", "You have selected invalid graphics device with -graphics switch. Game will use default OpenGL device instead."); + m_systemUtils->SystemDialog(SystemDialogType::ERROR, "Graphics initialization error", "You have selected invalid graphics device with -graphics switch. Game will use default OpenGL device instead."); m_device = Gfx::CreateDevice(m_deviceConfig, "opengl"); } } @@ -1057,9 +1043,9 @@ int CApplication::Run() MoveMouse(Math::Point(0.5f, 0.5f)); // center mouse on start - SystemTimeStamp *previousTimeStamp = m_systemUtils->CreateTimeStamp(); - SystemTimeStamp *currentTimeStamp = m_systemUtils->CreateTimeStamp(); - SystemTimeStamp *interpolatedTimeStamp = m_systemUtils->CreateTimeStamp(); + SystemTimeStamp previousTimeStamp{}; + SystemTimeStamp currentTimeStamp{}; + SystemTimeStamp interpolatedTimeStamp{}; while (true) { @@ -1163,11 +1149,11 @@ int CApplication::Run() // If game speed is increased then we do extra ticks per loop iteration to improve physics accuracy. int numTickSlices = static_cast(GetSimulationSpeed()); if(numTickSlices < 1) numTickSlices = 1; - m_systemUtils->CopyTimeStamp(previousTimeStamp, m_curTimeStamp); - m_systemUtils->GetCurrentTimeStamp(currentTimeStamp); + previousTimeStamp = m_curTimeStamp; + currentTimeStamp = m_systemUtils->GetCurrentTimeStamp(); for(int tickSlice = 0; tickSlice < numTickSlices; tickSlice++) { - m_systemUtils->InterpolateTimeStamp(interpolatedTimeStamp, previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast(numTickSlices)); + interpolatedTimeStamp = m_systemUtils->TimeStampLerp(previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast(numTickSlices)); Event event = CreateUpdateEvent(interpolatedTimeStamp); if (event.type != EVENT_NULL && m_controller != nullptr) { @@ -1198,9 +1184,6 @@ int CApplication::Run() } end: - m_systemUtils->DestroyTimeStamp(previousTimeStamp); - m_systemUtils->DestroyTimeStamp(currentTimeStamp); - m_systemUtils->DestroyTimeStamp(interpolatedTimeStamp); return m_exitCode; } @@ -1539,17 +1522,15 @@ void CApplication::StartLoadingMusic() std::thread{[this]() { GetLogger()->Debug("Cache sounds...\n"); - SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadStart); + SystemTimeStamp musicLoadStart{m_systemUtils->GetCurrentTimeStamp()}; m_sound->Reset(); m_sound->CacheAll(); - SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); - float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); + SystemTimeStamp musicLoadEnd{m_systemUtils->GetCurrentTimeStamp()}; + float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, SystemTimeUnit::MILLISECONDS); GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); - }).detach(); + }}.detach(); } bool CApplication::GetSimulationSuspended() const @@ -1561,20 +1542,20 @@ void CApplication::SetSimulationSpeed(float speed) { m_simulationSpeed = speed; - m_systemUtils->CopyTimeStamp(m_baseTimeStamp, m_curTimeStamp); + m_baseTimeStamp = m_curTimeStamp; m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; GetLogger()->Info("Simulation speed = %.2f\n", speed); } -Event CApplication::CreateUpdateEvent(SystemTimeStamp *newTimeStamp) +Event CApplication::CreateUpdateEvent(SystemTimeStamp newTimeStamp) { if (m_simulationSuspended) return Event(EVENT_NULL); - m_systemUtils->CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); - m_systemUtils->CopyTimeStamp(m_curTimeStamp, newTimeStamp); + m_lastTimeStamp = m_curTimeStamp; + m_curTimeStamp = newTimeStamp; long long absDiff = m_systemUtils->TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); long long newRealAbsTime = m_realAbsTimeBase + absDiff; diff --git a/src/app/app.h b/src/app/app.h index 02e12124..60d11c42 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -297,7 +297,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 - TEST_VIRTUAL Event CreateUpdateEvent(SystemTimeStamp *newTimeStamp); + TEST_VIRTUAL Event CreateUpdateEvent(SystemTimeStamp newTimeStamp); //! Logs debug data for event void LogEvent(const Event& event); diff --git a/src/app/main.cpp b/src/app/main.cpp index 1cb8171a..002bd4f8 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -177,7 +177,7 @@ int main(int argc, char *argv[]) ParseArgsStatus status = app.ParseArguments(argc, argv); if (status == PARSE_ARGS_FAIL) { - systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); + systemUtils->SystemDialog(SystemDialogType::ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); return app.GetExitCode(); } else if (status == PARSE_ARGS_HELP) @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) code = app.GetExitCode(); if (code != 0 && !app.GetErrorMessage().empty()) { - systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app.GetErrorMessage()); + systemUtils->SystemDialog(SystemDialogType::ERROR, "COLOBOT - Fatal Error", app.GetErrorMessage()); } logger.Info("Didn't run main loop. Exiting with code %d\n", code); return code; diff --git a/src/app/signal_handlers.cpp b/src/app/signal_handlers.cpp index 1558f4be..99c04d5d 100644 --- a/src/app/signal_handlers.cpp +++ b/src/app/signal_handlers.cpp @@ -162,7 +162,7 @@ void CSignalHandlers::ReportError(const std::string& errorMessage) std::cerr << std::endl << msg.str() << std::endl; - m_systemUtils->SystemDialog(SDT_ERROR, "Unhandled exception occurred!", msg.str()); + m_systemUtils->SystemDialog(SystemDialogType::ERROR, "Unhandled exception occurred!", msg.str()); if (canSave && !triedSaving) { @@ -172,13 +172,13 @@ void CSignalHandlers::ReportError(const std::string& errorMessage) msg << std::endl; msg << "Do you want to try saving now?"; - SystemDialogResult result = m_systemUtils->SystemDialog(SDT_YES_NO, "Try to save?", msg.str()); - if (result == SDR_YES) + SystemDialogResult result = m_systemUtils->SystemDialog(SystemDialogType::YES_NO, "Try to save?", msg.str()); + if (result == SystemDialogResult::YES) { triedSaving = true; CResourceManager::CreateNewDirectory("crashsave"); robotMain->IOWriteScene("crashsave/data.sav", "crashsave/cbot.run", "crashsave/screen.png", "Backup at the moment of a crash", true); - m_systemUtils->SystemDialog(SDT_INFO, "Try to save?", "Saving finished.\nPlease restart the game now"); + m_systemUtils->SystemDialog(SystemDialogType::INFO, "Try to save?", "Saving finished.\nPlease restart the game now"); } } diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index 46fa81e2..d007fcb1 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -61,17 +61,17 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons { switch (type) { - case SDT_INFO: + case SystemDialogType::INFO: std::cout << "INFO: "; break; - case SDT_WARNING: + case SystemDialogType::WARNING: std::cout << "WARNING:"; break; - case SDT_ERROR: + case SystemDialogType::ERROR: std::cout << "ERROR: "; break; - case SDT_YES_NO: - case SDT_OK_CANCEL: + case SystemDialogType::YES_NO: + case SystemDialogType::OK_CANCEL: std::cout << "QUESTION: "; break; } @@ -80,24 +80,24 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons std::string line; - SystemDialogResult result = SDR_OK; + auto result = SystemDialogResult::OK; bool done = false; while (!done) { switch (type) { - case SDT_INFO: - case SDT_WARNING: - case SDT_ERROR: + case SystemDialogType::INFO: + case SystemDialogType::WARNING: + case SystemDialogType::ERROR: std::cout << "Press ENTER to continue"; break; - case SDT_YES_NO: + case SystemDialogType::YES_NO: std::cout << "Type 'Y' for Yes or 'N' for No"; break; - case SDT_OK_CANCEL: + case SystemDialogType::OK_CANCEL: std::cout << "Type 'O' for OK or 'C' for Cancel"; break; } @@ -106,35 +106,35 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons switch (type) { - case SDT_INFO: - case SDT_WARNING: - case SDT_ERROR: + case SystemDialogType::INFO: + case SystemDialogType::WARNING: + case SystemDialogType::ERROR: done = true; break; - case SDT_YES_NO: + case SystemDialogType::YES_NO: if (line == "Y" || line == "y") { - result = SDR_YES; + result = SystemDialogResult::YES; done = true; } else if (line == "N" || line == "n") { - result = SDR_NO; + result = SystemDialogResult::NO; done = true; } break; - case SDT_OK_CANCEL: + case SystemDialogType::OK_CANCEL: if (line == "O" || line == "o") { done = true; - result = SDR_OK; + result = SystemDialogResult::OK; } else if (line == "C" || line == "c") { done = true; - result = SDR_CANCEL; + result = SystemDialogResult::CANCEL; } break; } @@ -148,6 +148,11 @@ SystemTimeStamp CSystemUtils::GetCurrentTimeStamp() return std::chrono::high_resolution_clock::now(); } +SystemTimeStamp CSystemUtils::TimeStampLerp(SystemTimeStamp a, SystemTimeStamp b, float t) +{ + return a + std::chrono::duration_cast((b - a) * t); +} + long long CSystemUtils::TimeStampExactDiff(SystemTimeStamp before, SystemTimeStamp after) { return std::chrono::duration_cast(after - before).count(); @@ -158,11 +163,11 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp before, SystemTimeStamp after, long long exact = TimeStampExactDiff(before, after); float result = 0.0f; - if (unit == STU_SEC) + if (unit == SystemTimeUnit::SECONDS) result = exact * 1e-9; - else if (unit == STU_MSEC) + else if (unit == SystemTimeUnit::MILLISECONDS) result = exact * 1e-6; - else if (unit == STU_USEC) + else if (unit == SystemTimeUnit::MICROSECONDS) result = exact * 1e-3; else assert(false); diff --git a/src/common/system/system.h b/src/common/system/system.h index 2f7fd146..1d0b31eb 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -35,18 +35,18 @@ * \enum SystemDialogType * \brief Type of system dialog */ -enum SystemDialogType +enum class SystemDialogType { //! Information message - SDT_INFO, + INFO, //! Warning message - SDT_WARNING, + WARNING, //! Error message - SDT_ERROR, + ERROR, //! Yes/No question - SDT_YES_NO, + YES_NO, //! Ok/Cancel question - SDT_OK_CANCEL + OK_CANCEL }; /** @@ -55,26 +55,23 @@ enum SystemDialogType * * Means which button was pressed. */ -enum SystemDialogResult +enum class SystemDialogResult { - SDR_OK, - SDR_CANCEL, - SDR_YES, - SDR_NO + OK, + CANCEL, + YES, + NO }; /** * \enum SystemTimeUnit * \brief Time unit */ -enum SystemTimeUnit +enum class SystemTimeUnit { - //! seconds - STU_SEC, - //! milliseconds - STU_MSEC, - //! microseconds - STU_USEC + SECONDS, + MILLISECONDS, + MICROSECONDS }; using SystemTimeStamp = std::chrono::time_point; @@ -103,20 +100,23 @@ public: //! Displays a fallback system dialog using console TEST_VIRTUAL SystemDialogResult ConsoleSystemDialog(SystemDialogType type, const std::string& title, const std::string& message); - //! Interpolates between two timestamps. If i=0 then dst=a. If i=1 then dst=b. If i=0.5 then dst is halfway between. - virtual void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) = 0; - //! Returns a time stamp associated with current time TEST_VIRTUAL SystemTimeStamp GetCurrentTimeStamp(); + //! Linearly interpolates between two timestamps. + SystemTimeStamp TimeStampLerp(SystemTimeStamp a, SystemTimeStamp b, float t); + //! 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); + float TimeStampDiff(SystemTimeStamp before, SystemTimeStamp after, SystemTimeUnit unit = SystemTimeUnit::SECONDS); //! 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 path where the executable binary is located (ends with the path separator) + virtual std::string GetBasePath(); + //! Returns the data path (containing textures, levels, helpfiles, etc) virtual std::string GetDataPath(); diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index 9f738aa9..056e34ad 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -46,20 +46,20 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const std::string options = ""; switch (type) { - case SDT_INFO: + case SystemDialogType::INFO: default: options = "--info"; break; - case SDT_WARNING: + case SystemDialogType::WARNING: options = "--warning"; break; - case SDT_ERROR: + case SystemDialogType::ERROR: options = "--error"; break; - case SDT_YES_NO: + case SystemDialogType::YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break; - case SDT_OK_CANCEL: + case SystemDialogType::OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break; } @@ -67,14 +67,14 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\""; int code = system(command.c_str()); - SystemDialogResult result = SDR_OK; + SystemDialogResult result = SystemDialogResult::OK; switch (type) { - case SDT_YES_NO: - result = code ? SDR_NO : SDR_YES; + case SystemDialogType::YES_NO: + result = code ? SystemDialogResult::NO : SystemDialogResult::YES; break; - case SDT_OK_CANCEL: - result = code ? SDR_CANCEL : SDR_OK; + case SystemDialogType::OK_CANCEL: + result = code ? SystemDialogResult::CANCEL : SystemDialogResult::OK; break; default: break; @@ -83,19 +83,6 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const return result; } -void CSystemUtilsLinux::InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) -{ - long long delta = TimeStampExactDiff(a, b); - delta *= i; // truncates - dst->clockTime.tv_sec = a->clockTime.tv_sec + delta / 1000000000; - dst->clockTime.tv_nsec = a->clockTime.tv_nsec + delta % 1000000000; - if(dst->clockTime.tv_nsec >= 1000000000) - { - dst->clockTime.tv_nsec -= 1000000000; - dst->clockTime.tv_sec++; - } -} - void CSystemUtilsLinux::GetCurrentTimeStamp(SystemTimeStamp *stamp) { clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime); diff --git a/src/common/system/system_linux.h b/src/common/system/system_linux.h index 93a0c8ba..8a1e60ec 100644 --- a/src/common/system/system_linux.h +++ b/src/common/system/system_linux.h @@ -24,8 +24,6 @@ #include "common/system/system.h" -#include - //@colobot-lint-exclude UndefinedFunctionRule class CSystemUtilsLinux : public CSystemUtils @@ -35,8 +33,6 @@ public: SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; - void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) override; - std::string GetSaveDir() override; std::string GetEnvVar(const std::string& name) override; diff --git a/src/common/system/system_windows.cpp b/src/common/system/system_windows.cpp index 1d3c9b1e..3f2bb171 100644 --- a/src/common/system/system_windows.cpp +++ b/src/common/system/system_windows.cpp @@ -37,20 +37,24 @@ SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, cons switch (type) { - case SDT_INFO: + case SystemDialogType::INFO: default: windowsType = MB_ICONINFORMATION|MB_OK; break; - case SDT_WARNING: + case SystemDialogType::WARNING: windowsType = MB_ICONWARNING|MB_OK; break; - case SDT_ERROR: +// windows.h defines ERROR which collides with the enum name +#pragma push_macro("ERROR") +#undef ERROR + case SystemDialogType::ERROR: +#pragma pop_macro("ERROR") windowsType = MB_ICONERROR|MB_OK; break; - case SDT_YES_NO: + case SystemDialogType::YES_NO: windowsType = MB_ICONQUESTION|MB_YESNO; break; - case SDT_OK_CANCEL: + case SystemDialogType::OK_CANCEL: windowsType = MB_ICONWARNING|MB_OKCANCEL; break; } @@ -58,18 +62,18 @@ SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, cons switch (MessageBoxW(nullptr, windowsMessage.c_str(), windowsTitle.c_str(), windowsType)) { case IDOK: - return SDR_OK; + return SystemDialogResult::OK; case IDCANCEL: - return SDR_CANCEL; + return SystemDialogResult::CANCEL; case IDYES: - return SDR_YES; + return SystemDialogResult::YES; case IDNO: - return SDR_NO; + return SystemDialogResult::NO; default: break; } - return SDR_OK; + return SystemDialogResult::OK; } //! Converts a wide Unicode string to an UTF8 string diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 19df60f8..72cc69b4 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -3168,7 +3168,7 @@ void CEngine::Render() m_fpsCounter++; m_currentFrameTime = m_systemUtils->GetCurrentTimeStamp(); - float diff = m_systemUtils->TimeStampDiff(m_lastFrameTime, m_currentFrameTime, STU_SEC); + float diff = m_systemUtils->TimeStampDiff(m_lastFrameTime, m_currentFrameTime, SystemTimeUnit::SECONDS); if (diff > 1.0f) { m_lastFrameTime = m_currentFrameTime; diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index f0eaecd9..bcf187d0 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,10 +1,3 @@ -# Platform-dependent tests -if(PLATFORM_WINDOWS) - set(PLATFORM_TESTS common/system/system_windows_test.cpp) -elseif(PLATFORM_LINUX) - set(PLATFORM_TESTS common/system/system_linux_test.cpp) -endif() - set(TEST_FILES common/colobot.ini ) @@ -21,6 +14,7 @@ add_executable(colobot_ut CBot/CBotToken_test.cpp CBot/CBot_test.cpp common/config_file_test.cpp + common/system/system_test.cpp graphics/engine/lightman_test.cpp math/func_test.cpp math/geometry_test.cpp @@ -28,13 +22,6 @@ add_executable(colobot_ut math/vector_test.cpp ) -# Platform-dependent tests -if(PLATFORM_WINDOWS) - target_sources(colobot_ut PRIVATE common/system/system_windows_test.cpp) -elseif(PLATFORM_LINUX) - target_sources(colobot_ut PRIVATE common/system/system_linux_test.cpp) -endif() - target_include_directories(colobot_ut PRIVATE common math diff --git a/test/unit/app/app_test.cpp b/test/unit/app/app_test.cpp index 3b9443db..22fc3eb4 100644 --- a/test/unit/app/app_test.cpp +++ b/test/unit/app/app_test.cpp @@ -47,7 +47,7 @@ public: SDL_Quit(); } - Event CreateUpdateEvent(SystemTimeStamp *timestamp) override + Event CreateUpdateEvent(SystemTimeStamp timestamp) override { return CApplication::CreateUpdateEvent(timestamp); } @@ -117,8 +117,7 @@ void CApplicationUT::TestCreateUpdateEvent(long long relTimeExact, long long abs float relTime, float absTime, long long relTimeReal, long long absTimeReal) { - SystemTimeStamp *now = CreateTimeStamp(); - GetCurrentTimeStamp(now); + SystemTimeStamp now = GetCurrentTimeStamp(); Event event = m_app->CreateUpdateEvent(now); EXPECT_EQ(EVENT_FRAME, event.type); EXPECT_FLOAT_EQ(relTime, event.rTime); @@ -135,9 +134,7 @@ TEST_F(CApplicationUT, UpdateEventTimeCalculation_SimulationSuspended) { m_app->SuspendSimulation(); - SystemTimeStamp *now = CreateTimeStamp(); - GetCurrentTimeStamp(now); - Event event = m_app->CreateUpdateEvent(now); + Event event = m_app->CreateUpdateEvent(GetCurrentTimeStamp()); EXPECT_EQ(EVENT_NULL, event.type); } @@ -190,9 +187,7 @@ TEST_F(CApplicationUT, UpdateEventTimeCalculation_NegativeTimeOperation) NextInstant(-1111); - SystemTimeStamp *now = CreateTimeStamp(); - GetCurrentTimeStamp(now); - Event event = m_app->CreateUpdateEvent(now); + Event event = m_app->CreateUpdateEvent(GetCurrentTimeStamp()); EXPECT_EQ(EVENT_NULL, event.type); } diff --git a/test/unit/common/system/system_linux_test.cpp b/test/unit/common/system/system_linux_test.cpp deleted file mode 100644 index 6a503c18..00000000 --- a/test/unit/common/system/system_linux_test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#include "common/system/system.h" -#include "common/system/system_linux.h" - -#include - -class CSystemUtilsLinuxUT : public testing::Test -{ -protected: - static const long long SEC = 1000000000; - - CSystemUtilsLinux m_systemUtils; -}; - - -TEST_F(CSystemUtilsLinuxUT, TimeStampDiff) -{ - SystemTimeStamp before, after; - - before.clockTime.tv_sec = 1; - before.clockTime.tv_nsec = 100; - - after.clockTime.tv_sec = 1; - after.clockTime.tv_nsec = 900; - - long long tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 800, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-800, tDiff); - - // ------- - - before.clockTime.tv_sec = 2; - before.clockTime.tv_nsec = 200; - - after.clockTime.tv_sec = 3; - after.clockTime.tv_nsec = 500; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( SEC + 300, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-SEC - 300, tDiff); - - // ------- - - before.clockTime.tv_sec = 3; - before.clockTime.tv_nsec = 200; - - after.clockTime.tv_sec = 4; - after.clockTime.tv_nsec = 100; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( SEC - 100, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-SEC + 100, tDiff); -} diff --git a/test/unit/common/system/system_test.cpp b/test/unit/common/system/system_test.cpp index 60447dd7..f78a4f98 100644 --- a/test/unit/common/system/system_test.cpp +++ b/test/unit/common/system/system_test.cpp @@ -21,11 +21,13 @@ #include -struct SystemTest : ::testing::Test { +struct SystemTest : ::testing::Test +{ CSystemUtilsOther system; }; -TEST_F(SystemTest, TimeStampExactDiff) { +TEST_F(SystemTest, TimeStampExactDiff) +{ auto epoch = SystemTimeStamp{}; EXPECT_EQ(system.TimeStampExactDiff(epoch, epoch), 0); @@ -35,3 +37,43 @@ TEST_F(SystemTest, TimeStampExactDiff) { EXPECT_EQ(system.TimeStampExactDiff(before, after), std::chrono::nanoseconds{duration}.count()); EXPECT_EQ(system.TimeStampExactDiff(after, before), -std::chrono::nanoseconds{duration}.count()); } + +constexpr auto TIMESTAMP_START = SystemTimeStamp{std::chrono::nanoseconds{300}}; +constexpr auto TIMESTAMP_MID = SystemTimeStamp{std::chrono::nanoseconds{600}}; +constexpr auto TIMESTAMP_END = SystemTimeStamp{std::chrono::nanoseconds{900}}; + +constexpr auto LERP_PARAM_ZERO = 0.0f; +constexpr auto LERP_PARAM_HALF = 0.5f; +constexpr auto LERP_PARAM_ONE = 1.0f; + +TEST_F(SystemTest, TimeStampLerpReturnsStartWhenLerpParameterIsZero) +{ + EXPECT_EQ(TIMESTAMP_START, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ZERO)); +} + +TEST_F(SystemTest, TimeStampLerpReturnsEndWhenLerpParameterIsOne) +{ + EXPECT_EQ(TIMESTAMP_END, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ONE)); +} + +TEST_F(SystemTest, TimeStampLerpReturnsValueBetweenStartAndEndWhenLerpParameterIsBetweenZeroAndOne) +{ + EXPECT_EQ(TIMESTAMP_MID, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF)); +} + +TEST_F(SystemTest, TimeStampLerpIsMonotonic) +{ + constexpr auto deltaLerpParam = 0.1f; + auto earlierTimeStamp = system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF - deltaLerpParam); + auto laterTimeStamp = system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF + deltaLerpParam); + EXPECT_TRUE(earlierTimeStamp < laterTimeStamp); +} + +TEST_F(SystemTest, TimeStampLerpIsConsistent) +{ + auto timeStamp = TIMESTAMP_START; + EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_ZERO)); + EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_HALF)); + EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_ONE)); +} + diff --git a/test/unit/common/system/system_windows_test.cpp b/test/unit/common/system/system_windows_test.cpp deleted file mode 100644 index eb959ff0..00000000 --- a/test/unit/common/system/system_windows_test.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#include "common/system/system.h" -#include "common/system/system_windows.h" - -#include - -class CSystemUtilsWindowsWrapper : public CSystemUtilsWindows -{ -public: - void SetFrequency(long long frequency) - { - m_counterFrequency = frequency; - } -}; - -class CSystemUtilsWindowsUT : public testing::Test -{ -protected: - static const long long SEC = 1000000000; - - CSystemUtilsWindowsWrapper m_systemUtils; -}; - -TEST_F(CSystemUtilsWindowsUT, TimeStampDiff) -{ - m_systemUtils.SetFrequency(SEC); - - SystemTimeStamp before, after; - - before.counterValue = 100; - after.counterValue = 200; - - long long tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 100, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-100, tDiff); - - // ------- - - m_systemUtils.SetFrequency(SEC/3); - - before.counterValue = 200; - after.counterValue = 400; - - tDiff = m_systemUtils.TimeStampExactDiff(&before, &after); - EXPECT_EQ( 200*3, tDiff); - - tDiff = m_systemUtils.TimeStampExactDiff(&after, &before); - EXPECT_EQ(-200*3, tDiff); -} From a69b88e09a6a2ecdc739e09ed8ca2afb50dce99f Mon Sep 17 00:00:00 2001 From: MrSimbax Date: Sat, 11 Sep 2021 13:26:38 +0200 Subject: [PATCH 5/7] Move time related functions out of CSystemUtils GetCurrentTimeStamp() has not been moved because of CApplication unit tests. --- src/CMakeLists.txt | 2 + src/app/app.cpp | 26 ++++---- src/app/app.h | 12 ++-- src/common/profiler.cpp | 10 ++-- src/common/profiler.h | 2 +- src/common/system/system.cpp | 29 +-------- src/common/system/system.h | 28 +-------- src/common/system/system_linux.cpp | 11 ---- src/common/timeutils.cpp | 54 +++++++++++++++++ src/common/timeutils.h | 50 ++++++++++++++++ src/graphics/engine/engine.cpp | 4 +- src/graphics/engine/engine.h | 4 +- test/unit/CMakeLists.txt | 5 +- test/unit/app/app_test.cpp | 11 ++-- test/unit/common/system/system_test.cpp | 79 ------------------------- test/unit/common/timeutils_test.cpp | 78 ++++++++++++++++++++++++ 16 files changed, 227 insertions(+), 178 deletions(-) create mode 100644 src/common/timeutils.cpp create mode 100644 src/common/timeutils.h delete mode 100644 test/unit/common/system/system_test.cpp create mode 100644 test/unit/common/timeutils_test.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69de9fe0..105bce70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,6 +83,8 @@ add_library(colobotbase STATIC common/singleton.h common/stringutils.cpp common/stringutils.h + common/timeutils.cpp + common/timeutils.h common/thread/worker_thread.h graphics/core/color.cpp graphics/core/color.h diff --git a/src/app/app.cpp b/src/app/app.cpp index c2264cf8..a30e0ba7 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -61,6 +61,9 @@ #include #include +using TimeUtils::TimeStamp; +using TimeUtils::TimeUnit; + char CApplication::m_languageLocale[] = { 0 }; @@ -70,7 +73,6 @@ const int JOYSTICK_TIMER_INTERVAL = 1000/30; //! Function called by the timer Uint32 JoystickTimerCallback(Uint32 interval, void *); - /** * \struct ApplicationPrivate * \brief Private data of CApplication class @@ -1043,9 +1045,9 @@ int CApplication::Run() MoveMouse(Math::Point(0.5f, 0.5f)); // center mouse on start - SystemTimeStamp previousTimeStamp{}; - SystemTimeStamp currentTimeStamp{}; - SystemTimeStamp interpolatedTimeStamp{}; + TimeStamp previousTimeStamp{}; + TimeStamp currentTimeStamp{}; + TimeStamp interpolatedTimeStamp{}; while (true) { @@ -1153,7 +1155,7 @@ int CApplication::Run() currentTimeStamp = m_systemUtils->GetCurrentTimeStamp(); for(int tickSlice = 0; tickSlice < numTickSlices; tickSlice++) { - interpolatedTimeStamp = m_systemUtils->TimeStampLerp(previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast(numTickSlices)); + interpolatedTimeStamp = TimeUtils::Lerp(previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast(numTickSlices)); Event event = CreateUpdateEvent(interpolatedTimeStamp); if (event.type != EVENT_NULL && m_controller != nullptr) { @@ -1478,7 +1480,7 @@ void CApplication::Render() void CApplication::RenderIfNeeded(int updateRate) { m_manualFrameTime = m_systemUtils->GetCurrentTimeStamp(); - long long diff = m_systemUtils->TimeStampExactDiff(m_manualFrameLast, m_manualFrameTime); + long long diff = TimeUtils::ExactDiff(m_manualFrameLast, m_manualFrameTime); if (diff < 1e9f / updateRate) { return; @@ -1522,13 +1524,13 @@ void CApplication::StartLoadingMusic() std::thread{[this]() { GetLogger()->Debug("Cache sounds...\n"); - SystemTimeStamp musicLoadStart{m_systemUtils->GetCurrentTimeStamp()}; + TimeStamp musicLoadStart{m_systemUtils->GetCurrentTimeStamp()}; m_sound->Reset(); m_sound->CacheAll(); - SystemTimeStamp musicLoadEnd{m_systemUtils->GetCurrentTimeStamp()}; - float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, SystemTimeUnit::MILLISECONDS); + TimeStamp musicLoadEnd{m_systemUtils->GetCurrentTimeStamp()}; + float musicLoadTime = TimeUtils::Diff(musicLoadStart, musicLoadEnd, TimeUnit::MILLISECONDS); GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); }}.detach(); } @@ -1549,7 +1551,7 @@ void CApplication::SetSimulationSpeed(float speed) GetLogger()->Info("Simulation speed = %.2f\n", speed); } -Event CApplication::CreateUpdateEvent(SystemTimeStamp newTimeStamp) +Event CApplication::CreateUpdateEvent(TimeStamp newTimeStamp) { if (m_simulationSuspended) return Event(EVENT_NULL); @@ -1557,9 +1559,9 @@ Event CApplication::CreateUpdateEvent(SystemTimeStamp newTimeStamp) m_lastTimeStamp = m_curTimeStamp; m_curTimeStamp = newTimeStamp; - long long absDiff = m_systemUtils->TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); + long long absDiff = TimeUtils::ExactDiff(m_baseTimeStamp, m_curTimeStamp); long long newRealAbsTime = m_realAbsTimeBase + absDiff; - long long newRealRelTime = m_systemUtils->TimeStampExactDiff(m_lastTimeStamp, m_curTimeStamp); + long long newRealRelTime = TimeUtils::ExactDiff(m_lastTimeStamp, m_curTimeStamp); if (newRealAbsTime < m_realAbsTime || newRealRelTime < 0) { diff --git a/src/app/app.h b/src/app/app.h index 60d11c42..7160be54 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -297,7 +297,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 - TEST_VIRTUAL Event CreateUpdateEvent(SystemTimeStamp newTimeStamp); + TEST_VIRTUAL Event CreateUpdateEvent(TimeUtils::TimeStamp newTimeStamp); //! Logs debug data for event void LogEvent(const Event& event); @@ -354,9 +354,9 @@ protected: //! Animation time stamps, etc. //@{ - SystemTimeStamp m_baseTimeStamp; - SystemTimeStamp m_lastTimeStamp; - SystemTimeStamp m_curTimeStamp; + TimeUtils::TimeStamp m_baseTimeStamp; + TimeUtils::TimeStamp m_lastTimeStamp; + TimeUtils::TimeStamp m_curTimeStamp; long long m_realAbsTimeBase; long long m_realAbsTime; @@ -373,8 +373,8 @@ protected: bool m_simulationSuspended; //@} - SystemTimeStamp m_manualFrameLast; - SystemTimeStamp m_manualFrameTime; + TimeUtils::TimeStamp m_manualFrameLast; + TimeUtils::TimeStamp m_manualFrameTime; //! Graphics device to use bool m_graphicsOverride = false; diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp index d97572d8..56a5996d 100644 --- a/src/common/profiler.cpp +++ b/src/common/profiler.cpp @@ -23,10 +23,12 @@ #include +using TimeUtils::TimeStamp; + CSystemUtils* CProfiler::m_systemUtils = nullptr; long long CProfiler::m_performanceCounters[PCNT_MAX] = {0}; long long CProfiler::m_prevPerformanceCounters[PCNT_MAX] = {0}; -std::stack CProfiler::m_runningPerformanceCounters; +std::stack CProfiler::m_runningPerformanceCounters; std::stack CProfiler::m_runningPerformanceCountersType; void CProfiler::SetSystemUtils(CSystemUtils* systemUtils) @@ -39,7 +41,7 @@ void CProfiler::StartPerformanceCounter(PerformanceCounter counter) if (counter == PCNT_ALL) ResetPerformanceCounters(); - SystemTimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); + TimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); m_runningPerformanceCounters.push(timeStamp); m_runningPerformanceCountersType.push(counter); } @@ -49,8 +51,8 @@ void CProfiler::StopPerformanceCounter(PerformanceCounter counter) assert(m_runningPerformanceCountersType.top() == counter); m_runningPerformanceCountersType.pop(); - SystemTimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); - m_performanceCounters[counter] += m_systemUtils->TimeStampExactDiff(m_runningPerformanceCounters.top(), timeStamp); + TimeStamp timeStamp = m_systemUtils->GetCurrentTimeStamp(); + m_performanceCounters[counter] += TimeUtils::ExactDiff(m_runningPerformanceCounters.top(), timeStamp); m_runningPerformanceCounters.pop(); if (counter == PCNT_ALL) diff --git a/src/common/profiler.h b/src/common/profiler.h index 38956e70..0c3da2b1 100644 --- a/src/common/profiler.h +++ b/src/common/profiler.h @@ -73,7 +73,7 @@ private: static long long m_performanceCounters[PCNT_MAX]; static long long m_prevPerformanceCounters[PCNT_MAX]; - static std::stack m_runningPerformanceCounters; + static std::stack m_runningPerformanceCounters; static std::stack m_runningPerformanceCountersType; }; diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index d007fcb1..b21015d3 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -143,38 +143,11 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons return result; } -SystemTimeStamp CSystemUtils::GetCurrentTimeStamp() +TimeUtils::TimeStamp CSystemUtils::GetCurrentTimeStamp() { return std::chrono::high_resolution_clock::now(); } -SystemTimeStamp CSystemUtils::TimeStampLerp(SystemTimeStamp a, SystemTimeStamp b, float t) -{ - return a + std::chrono::duration_cast((b - a) * t); -} - -long long CSystemUtils::TimeStampExactDiff(SystemTimeStamp before, SystemTimeStamp after) -{ - return std::chrono::duration_cast(after - before).count(); -} - -float CSystemUtils::TimeStampDiff(SystemTimeStamp before, SystemTimeStamp after, SystemTimeUnit unit) -{ - long long exact = TimeStampExactDiff(before, after); - - float result = 0.0f; - if (unit == SystemTimeUnit::SECONDS) - result = exact * 1e-9; - else if (unit == SystemTimeUnit::MILLISECONDS) - result = exact * 1e-6; - else if (unit == SystemTimeUnit::MICROSECONDS) - result = exact * 1e-3; - else - assert(false); - - return result; -} - std::string CSystemUtils::GetBasePath() { if (m_basePath.empty()) diff --git a/src/common/system/system.h b/src/common/system/system.h index 1d0b31eb..b2399cf5 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -25,6 +25,7 @@ #pragma once #include "common/config.h" +#include "common/timeutils.h" #include #include @@ -63,19 +64,6 @@ enum class SystemDialogResult NO }; -/** - * \enum SystemTimeUnit - * \brief Time unit - */ -enum class SystemTimeUnit -{ - SECONDS, - MILLISECONDS, - MICROSECONDS -}; - -using SystemTimeStamp = std::chrono::time_point; - /** * \class CSystemUtils * \brief Platform-specific utils @@ -101,18 +89,7 @@ public: TEST_VIRTUAL SystemDialogResult ConsoleSystemDialog(SystemDialogType type, const std::string& title, const std::string& message); //! Returns a time stamp associated with current time - TEST_VIRTUAL SystemTimeStamp GetCurrentTimeStamp(); - - //! Linearly interpolates between two timestamps. - SystemTimeStamp TimeStampLerp(SystemTimeStamp a, SystemTimeStamp b, float t); - - //! 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 = SystemTimeUnit::SECONDS); - - //! Returns the exact (in nanosecond units) difference between two timestamps - /** The difference is \a after - \a before. */ - long long TimeStampExactDiff(SystemTimeStamp before, SystemTimeStamp after); + TEST_VIRTUAL TimeUtils::TimeStamp GetCurrentTimeStamp(); //! Returns the path where the executable binary is located (ends with the path separator) virtual std::string GetBasePath(); @@ -142,5 +119,4 @@ public: private: std::string m_basePath; - std::vector> m_timeStamps; }; diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index 056e34ad..a5ef14c0 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -83,17 +83,6 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const return result; } -void CSystemUtilsLinux::GetCurrentTimeStamp(SystemTimeStamp *stamp) -{ - clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime); -} - -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; -} - std::string CSystemUtilsLinux::GetSaveDir() { #if PORTABLE_SAVES || DEV_BUILD diff --git a/src/common/timeutils.cpp b/src/common/timeutils.cpp new file mode 100644 index 00000000..96bcaa9c --- /dev/null +++ b/src/common/timeutils.cpp @@ -0,0 +1,54 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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 3 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, see http://gnu.org/licenses + */ + +#include "common/timeutils.h" + +#include + +namespace TimeUtils +{ + +TimeStamp Lerp(TimeStamp a, TimeStamp b, float t) +{ + return a + std::chrono::duration_cast((b - a) * t); +} + +float Diff(TimeStamp before, TimeStamp after, TimeUnit unit) +{ + long long exact = ExactDiff(before, after); + + float result = 0.0f; + if (unit == TimeUnit::SECONDS) + result = exact * 1e-9; + else if (unit == TimeUnit::MILLISECONDS) + result = exact * 1e-6; + else if (unit == TimeUnit::MICROSECONDS) + result = exact * 1e-3; + else + assert(false); + + return result; +} + +long long ExactDiff(TimeStamp before, TimeStamp after) +{ + return std::chrono::duration_cast(after - before).count(); +} + +} // namespace TimeUtils diff --git a/src/common/timeutils.h b/src/common/timeutils.h new file mode 100644 index 00000000..5d67f4d7 --- /dev/null +++ b/src/common/timeutils.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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 3 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, see http://gnu.org/licenses + */ + +/** + * \file common/timeutils.h + * \brief Some useful cross-platform operations on timestamps + */ + +#include + +namespace TimeUtils +{ + +enum class TimeUnit +{ + SECONDS, + MILLISECONDS, + MICROSECONDS +}; + +using TimeStamp = std::chrono::time_point; + +//! Linearly interpolates between two timestamps. +TimeStamp Lerp(TimeStamp a, TimeStamp b, float t); + +//! Returns a difference between two timestamps in given time unit +/** The difference is \a after - \a before. */ +float Diff(TimeStamp before, TimeStamp after, TimeUnit unit = TimeUnit::SECONDS); + +//! Returns the exact (in nanosecond units) difference between two timestamps +/** The difference is \a after - \a before. */ +long long ExactDiff(TimeStamp before, TimeStamp after); + +} // namespace TimeUtils diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 72cc69b4..f241f85d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -63,6 +63,8 @@ #include #include +using TimeUtils::TimeUnit; + // Graphics module namespace namespace Gfx { @@ -3168,7 +3170,7 @@ void CEngine::Render() m_fpsCounter++; m_currentFrameTime = m_systemUtils->GetCurrentTimeStamp(); - float diff = m_systemUtils->TimeStampDiff(m_lastFrameTime, m_currentFrameTime, SystemTimeUnit::SECONDS); + float diff = TimeUtils::Diff(m_lastFrameTime, m_currentFrameTime, TimeUnit::SECONDS); if (diff > 1.0f) { m_lastFrameTime = m_currentFrameTime; diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index b652b3c3..db6eb8e1 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1310,8 +1310,8 @@ protected: //! Last encountered error std::string m_error; - SystemTimeStamp m_lastFrameTime; - SystemTimeStamp m_currentFrameTime; + TimeUtils::TimeStamp m_lastFrameTime; + TimeUtils::TimeStamp m_currentFrameTime; int m_fpsCounter; float m_fps; diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index bcf187d0..b549229e 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -14,13 +14,12 @@ add_executable(colobot_ut CBot/CBotToken_test.cpp CBot/CBot_test.cpp common/config_file_test.cpp - common/system/system_test.cpp + common/timeutils_test.cpp graphics/engine/lightman_test.cpp math/func_test.cpp math/geometry_test.cpp math/matrix_test.cpp - math/vector_test.cpp -) + math/vector_test.cpp) target_include_directories(colobot_ut PRIVATE common diff --git a/test/unit/app/app_test.cpp b/test/unit/app/app_test.cpp index 22fc3eb4..549941c6 100644 --- a/test/unit/app/app_test.cpp +++ b/test/unit/app/app_test.cpp @@ -31,6 +31,7 @@ using namespace HippoMocks; namespace ph = std::placeholders; +using TimeUtils::TimeStamp; class CApplicationWrapper : public CApplication { @@ -47,7 +48,7 @@ public: SDL_Quit(); } - Event CreateUpdateEvent(SystemTimeStamp timestamp) override + Event CreateUpdateEvent(TimeStamp timestamp) override { return CApplication::CreateUpdateEvent(timestamp); } @@ -69,7 +70,7 @@ protected: void NextInstant(long long diff); - SystemTimeStamp GetCurrentTimeStamp(); + TimeStamp GetCurrentTimeStamp(); void TestCreateUpdateEvent(long long relTimeExact, long long absTimeExact, float relTime, float absTime, @@ -103,9 +104,9 @@ void CApplicationUT::TearDown() } -SystemTimeStamp CApplicationUT::GetCurrentTimeStamp() +TimeStamp CApplicationUT::GetCurrentTimeStamp() { - return SystemTimeStamp{SystemTimeStamp::duration{m_currentTime}}; + return TimeStamp{ TimeStamp::duration{m_currentTime}}; } void CApplicationUT::NextInstant(long long diff) @@ -117,7 +118,7 @@ void CApplicationUT::TestCreateUpdateEvent(long long relTimeExact, long long abs float relTime, float absTime, long long relTimeReal, long long absTimeReal) { - SystemTimeStamp now = GetCurrentTimeStamp(); + TimeStamp now = GetCurrentTimeStamp(); Event event = m_app->CreateUpdateEvent(now); EXPECT_EQ(EVENT_FRAME, event.type); EXPECT_FLOAT_EQ(relTime, event.rTime); diff --git a/test/unit/common/system/system_test.cpp b/test/unit/common/system/system_test.cpp deleted file mode 100644 index f78a4f98..00000000 --- a/test/unit/common/system/system_test.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2018, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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 3 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, see http://gnu.org/licenses - */ - -#include "common/system/system_other.h" - -#include - -struct SystemTest : ::testing::Test -{ - CSystemUtilsOther system; -}; - -TEST_F(SystemTest, TimeStampExactDiff) -{ - auto epoch = SystemTimeStamp{}; - EXPECT_EQ(system.TimeStampExactDiff(epoch, epoch), 0); - - auto duration = std::chrono::microseconds{123456789L}; - auto before = std::chrono::high_resolution_clock::now(); - auto after = before + duration; - EXPECT_EQ(system.TimeStampExactDiff(before, after), std::chrono::nanoseconds{duration}.count()); - EXPECT_EQ(system.TimeStampExactDiff(after, before), -std::chrono::nanoseconds{duration}.count()); -} - -constexpr auto TIMESTAMP_START = SystemTimeStamp{std::chrono::nanoseconds{300}}; -constexpr auto TIMESTAMP_MID = SystemTimeStamp{std::chrono::nanoseconds{600}}; -constexpr auto TIMESTAMP_END = SystemTimeStamp{std::chrono::nanoseconds{900}}; - -constexpr auto LERP_PARAM_ZERO = 0.0f; -constexpr auto LERP_PARAM_HALF = 0.5f; -constexpr auto LERP_PARAM_ONE = 1.0f; - -TEST_F(SystemTest, TimeStampLerpReturnsStartWhenLerpParameterIsZero) -{ - EXPECT_EQ(TIMESTAMP_START, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ZERO)); -} - -TEST_F(SystemTest, TimeStampLerpReturnsEndWhenLerpParameterIsOne) -{ - EXPECT_EQ(TIMESTAMP_END, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ONE)); -} - -TEST_F(SystemTest, TimeStampLerpReturnsValueBetweenStartAndEndWhenLerpParameterIsBetweenZeroAndOne) -{ - EXPECT_EQ(TIMESTAMP_MID, system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF)); -} - -TEST_F(SystemTest, TimeStampLerpIsMonotonic) -{ - constexpr auto deltaLerpParam = 0.1f; - auto earlierTimeStamp = system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF - deltaLerpParam); - auto laterTimeStamp = system.TimeStampLerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF + deltaLerpParam); - EXPECT_TRUE(earlierTimeStamp < laterTimeStamp); -} - -TEST_F(SystemTest, TimeStampLerpIsConsistent) -{ - auto timeStamp = TIMESTAMP_START; - EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_ZERO)); - EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_HALF)); - EXPECT_EQ(timeStamp, system.TimeStampLerp(timeStamp, timeStamp, LERP_PARAM_ONE)); -} - diff --git a/test/unit/common/timeutils_test.cpp b/test/unit/common/timeutils_test.cpp new file mode 100644 index 00000000..0f312a53 --- /dev/null +++ b/test/unit/common/timeutils_test.cpp @@ -0,0 +1,78 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2018-2021, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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 3 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, see http://gnu.org/licenses + */ + +#include "common/timeutils.h" + +#include + +namespace TimeUtils +{ + +TEST(TimeUtilsExactDiffTest, ExactDiff) +{ + auto epoch = TimeStamp{}; + EXPECT_EQ(ExactDiff(epoch, epoch), 0); + + auto duration = std::chrono::microseconds{123456789L}; + auto before = std::chrono::high_resolution_clock::now(); + auto after = before + duration; + EXPECT_EQ(ExactDiff(before, after), std::chrono::nanoseconds{duration}.count()); + EXPECT_EQ(ExactDiff(after, before), -std::chrono::nanoseconds{duration}.count()); +} + +constexpr auto TIMESTAMP_START = TimeStamp{std::chrono::nanoseconds{300}}; +constexpr auto TIMESTAMP_MID = TimeStamp{std::chrono::nanoseconds{600}}; +constexpr auto TIMESTAMP_END = TimeStamp{std::chrono::nanoseconds{900}}; + +constexpr auto LERP_PARAM_ZERO = 0.0f; +constexpr auto LERP_PARAM_HALF = 0.5f; +constexpr auto LERP_PARAM_ONE = 1.0f; + +TEST(TimeUtilsLerpTest, LerpReturnsStartWhenLerpParameterIsZero) +{ + EXPECT_EQ(TIMESTAMP_START, Lerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ZERO)); +} + +TEST(TimeUtilsLerpTest, LerpReturnsEndWhenLerpParameterIsOne) +{ + EXPECT_EQ(TIMESTAMP_END, Lerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_ONE)); +} + +TEST(TimeUtilsLerpTest, LerpReturnsValueBetweenStartAndEndWhenLerpParameterIsBetweenZeroAndOne) +{ + EXPECT_EQ(TIMESTAMP_MID, Lerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF)); +} + +TEST(TimeUtilsLerpTest, LerpIsMonotonic) +{ + constexpr auto deltaLerpParam = 0.1f; + auto earlierTimeStamp = Lerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF - deltaLerpParam); + auto laterTimeStamp = Lerp(TIMESTAMP_START, TIMESTAMP_END, LERP_PARAM_HALF + deltaLerpParam); + EXPECT_TRUE(earlierTimeStamp < laterTimeStamp); +} + +TEST(TimeUtilsLerpTest, LerpIsConsistent) +{ + auto timeStamp = TIMESTAMP_START; + EXPECT_EQ(timeStamp, Lerp(timeStamp, timeStamp, LERP_PARAM_ZERO)); + EXPECT_EQ(timeStamp, Lerp(timeStamp, timeStamp, LERP_PARAM_HALF)); + EXPECT_EQ(timeStamp, Lerp(timeStamp, timeStamp, LERP_PARAM_ONE)); +} + +} // namespace TimeUtils From 6aa83c93acae1ddf1ae0ce92af6a25fe7f676ba2 Mon Sep 17 00:00:00 2001 From: MrSimbax Date: Sat, 11 Sep 2021 13:28:37 +0200 Subject: [PATCH 6/7] Update data submodule --- data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data b/data index 0ac8197b..21a45c0b 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 0ac8197b7a8a005c714b7696d36c642cf0e81474 +Subproject commit 21a45c0b8809accd142a83a81f1a3c92a327f319 From c9dca4cebdac4123b00c1c92dbb6f1f6b5ccae4b Mon Sep 17 00:00:00 2001 From: MrSimbax Date: Sat, 11 Sep 2021 13:40:22 +0200 Subject: [PATCH 7/7] Rename SystemDialogType::ERROR to ERROR_MSG Unfortunately, the ERROR name collides with a preprocessor definition in windows.h --- src/app/app.cpp | 2 +- src/app/main.cpp | 4 ++-- src/app/signal_handlers.cpp | 2 +- src/common/system/system.cpp | 6 +++--- src/common/system/system.h | 2 +- src/common/system/system_linux.cpp | 2 +- src/common/system/system_windows.cpp | 6 +----- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index a30e0ba7..9abd16f8 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -662,7 +662,7 @@ bool CApplication::Create() { GetLogger()->Error("Unknown graphics device: %s\n", graphics.c_str()); GetLogger()->Info("Changing to default device\n"); - m_systemUtils->SystemDialog(SystemDialogType::ERROR, "Graphics initialization error", "You have selected invalid graphics device with -graphics switch. Game will use default OpenGL device instead."); + m_systemUtils->SystemDialog(SystemDialogType::ERROR_MSG, "Graphics initialization error", "You have selected invalid graphics device with -graphics switch. Game will use default OpenGL device instead."); m_device = Gfx::CreateDevice(m_deviceConfig, "opengl"); } } diff --git a/src/app/main.cpp b/src/app/main.cpp index 002bd4f8..7c6173b0 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -177,7 +177,7 @@ int main(int argc, char *argv[]) ParseArgsStatus status = app.ParseArguments(argc, argv); if (status == PARSE_ARGS_FAIL) { - systemUtils->SystemDialog(SystemDialogType::ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); + systemUtils->SystemDialog(SystemDialogType::ERROR_MSG, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); return app.GetExitCode(); } else if (status == PARSE_ARGS_HELP) @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) code = app.GetExitCode(); if (code != 0 && !app.GetErrorMessage().empty()) { - systemUtils->SystemDialog(SystemDialogType::ERROR, "COLOBOT - Fatal Error", app.GetErrorMessage()); + systemUtils->SystemDialog(SystemDialogType::ERROR_MSG, "COLOBOT - Fatal Error", app.GetErrorMessage()); } logger.Info("Didn't run main loop. Exiting with code %d\n", code); return code; diff --git a/src/app/signal_handlers.cpp b/src/app/signal_handlers.cpp index 99c04d5d..f0e9f95e 100644 --- a/src/app/signal_handlers.cpp +++ b/src/app/signal_handlers.cpp @@ -162,7 +162,7 @@ void CSignalHandlers::ReportError(const std::string& errorMessage) std::cerr << std::endl << msg.str() << std::endl; - m_systemUtils->SystemDialog(SystemDialogType::ERROR, "Unhandled exception occurred!", msg.str()); + m_systemUtils->SystemDialog(SystemDialogType::ERROR_MSG, "Unhandled exception occurred!", msg.str()); if (canSave && !triedSaving) { diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index b21015d3..42242565 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -67,7 +67,7 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons case SystemDialogType::WARNING: std::cout << "WARNING:"; break; - case SystemDialogType::ERROR: + case SystemDialogType::ERROR_MSG: std::cout << "ERROR: "; break; case SystemDialogType::YES_NO: @@ -89,7 +89,7 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons { case SystemDialogType::INFO: case SystemDialogType::WARNING: - case SystemDialogType::ERROR: + case SystemDialogType::ERROR_MSG: std::cout << "Press ENTER to continue"; break; @@ -108,7 +108,7 @@ SystemDialogResult CSystemUtils::ConsoleSystemDialog(SystemDialogType type, cons { case SystemDialogType::INFO: case SystemDialogType::WARNING: - case SystemDialogType::ERROR: + case SystemDialogType::ERROR_MSG: done = true; break; diff --git a/src/common/system/system.h b/src/common/system/system.h index b2399cf5..d5bf3d99 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -43,7 +43,7 @@ enum class SystemDialogType //! Warning message WARNING, //! Error message - ERROR, + ERROR_MSG, // windows.h defines ERROR which collides with the "ERROR" enum name //! Yes/No question YES_NO, //! Ok/Cancel question diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index a5ef14c0..0f9efeee 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -53,7 +53,7 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const case SystemDialogType::WARNING: options = "--warning"; break; - case SystemDialogType::ERROR: + case SystemDialogType::ERROR_MSG: options = "--error"; break; case SystemDialogType::YES_NO: diff --git a/src/common/system/system_windows.cpp b/src/common/system/system_windows.cpp index 3f2bb171..773bd62d 100644 --- a/src/common/system/system_windows.cpp +++ b/src/common/system/system_windows.cpp @@ -44,11 +44,7 @@ SystemDialogResult CSystemUtilsWindows::SystemDialog(SystemDialogType type, cons case SystemDialogType::WARNING: windowsType = MB_ICONWARNING|MB_OK; break; -// windows.h defines ERROR which collides with the enum name -#pragma push_macro("ERROR") -#undef ERROR - case SystemDialogType::ERROR: -#pragma pop_macro("ERROR") + case SystemDialogType::ERROR_MSG: windowsType = MB_ICONERROR|MB_OK; break; case SystemDialogType::YES_NO: