From 38a11136744b814b12036527f84b71eae0ef6ea6 Mon Sep 17 00:00:00 2001
From: zhupengfei <zhupengfei321@sina.cn>
Date: Sat, 21 Jul 2018 17:09:15 +0800
Subject: [PATCH] Port #3972 from Citra: "common/timer: use std::chrono, avoid
 platform-dependent code"

---
 src/common/timer.cpp | 95 +++++++++++---------------------------------
 src/common/timer.h   | 17 ++++----
 2 files changed, 31 insertions(+), 81 deletions(-)

diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index f0c5b1a43..2dc15e434 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -3,31 +3,16 @@
 // Refer to the license.txt file included.
 
 #include <ctime>
-
 #include <fmt/format.h>
-
-#ifdef _WIN32
-#include <windows.h>
-// windows.h needs to be included before other windows headers
-#include <mmsystem.h>
-#include <sys/timeb.h>
-#else
-#include <sys/time.h>
-#endif
 #include "common/common_types.h"
 #include "common/string_util.h"
 #include "common/timer.h"
 
 namespace Common {
 
-u32 Timer::GetTimeMs() {
-#ifdef _WIN32
-    return timeGetTime();
-#else
-    struct timeval t;
-    (void)gettimeofday(&t, nullptr);
-    return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
-#endif
+std::chrono::milliseconds Timer::GetTimeMs() {
+    return std::chrono::duration_cast<std::chrono::milliseconds>(
+        std::chrono::system_clock::now().time_since_epoch());
 }
 
 // --------------------------------------------
@@ -63,7 +48,7 @@ void Timer::Update() {
 // -------------------------------------
 
 // Get the number of milliseconds since the last Update()
-u64 Timer::GetTimeDifference() {
+std::chrono::milliseconds Timer::GetTimeDifference() {
     return GetTimeMs() - m_LastTime;
 }
 
@@ -74,11 +59,11 @@ void Timer::AddTimeDifference() {
 }
 
 // Get the time elapsed since the Start()
-u64 Timer::GetTimeElapsed() {
+std::chrono::milliseconds Timer::GetTimeElapsed() {
     // If we have not started yet, return 1 (because then I don't
     // have to change the FPS calculation in CoreRerecording.cpp .
-    if (m_StartTime == 0)
-        return 1;
+    if (m_StartTime.count() == 0)
+        return std::chrono::milliseconds(1);
 
     // Return the final timer time if the timer is stopped
     if (!m_Running)
@@ -90,49 +75,34 @@ u64 Timer::GetTimeElapsed() {
 // Get the formatted time elapsed since the Start()
 std::string Timer::GetTimeElapsedFormatted() const {
     // If we have not started yet, return zero
-    if (m_StartTime == 0)
+    if (m_StartTime.count() == 0)
         return "00:00:00:000";
 
     // The number of milliseconds since the start.
     // Use a different value if the timer is stopped.
-    u64 Milliseconds;
+    std::chrono::milliseconds Milliseconds;
     if (m_Running)
         Milliseconds = GetTimeMs() - m_StartTime;
     else
         Milliseconds = m_LastTime - m_StartTime;
     // Seconds
-    u32 Seconds = (u32)(Milliseconds / 1000);
+    std::chrono::seconds Seconds = std::chrono::duration_cast<std::chrono::seconds>(Milliseconds);
     // Minutes
-    u32 Minutes = Seconds / 60;
+    std::chrono::minutes Minutes = std::chrono::duration_cast<std::chrono::minutes>(Milliseconds);
     // Hours
-    u32 Hours = Minutes / 60;
+    std::chrono::hours Hours = std::chrono::duration_cast<std::chrono::hours>(Milliseconds);
 
-    std::string TmpStr = fmt::format("{:02}:{:02}:{:02}:{:03}", Hours, Minutes % 60, Seconds % 60,
-                                     Milliseconds % 1000);
+    std::string TmpStr = fmt::format("{:02}:{:02}:{:02}:{:03}", Hours.count(), Minutes.count() % 60,
+                                     Seconds.count() % 60, Milliseconds.count() % 1000);
     return TmpStr;
 }
 
-// Get current time
-void Timer::IncreaseResolution() {
-#ifdef _WIN32
-    timeBeginPeriod(1);
-#endif
-}
-
-void Timer::RestoreResolution() {
-#ifdef _WIN32
-    timeEndPeriod(1);
-#endif
-}
-
 // Get the number of seconds since January 1 1970
-u64 Timer::GetTimeSinceJan1970() {
-    time_t ltime;
-    time(&ltime);
-    return ((u64)ltime);
+std::chrono::seconds Timer::GetTimeSinceJan1970() {
+    return std::chrono::duration_cast<std::chrono::seconds>(GetTimeMs());
 }
 
-u64 Timer::GetLocalTimeSinceJan1970() {
+std::chrono::seconds Timer::GetLocalTimeSinceJan1970() {
     time_t sysTime, tzDiff, tzDST;
     struct tm* gmTime;
 
@@ -149,7 +119,7 @@ u64 Timer::GetLocalTimeSinceJan1970() {
     gmTime = gmtime(&sysTime);
     tzDiff = sysTime - mktime(gmTime);
 
-    return (u64)(sysTime + tzDiff + tzDST);
+    return std::chrono::seconds(sysTime + tzDiff + tzDST);
 }
 
 // Return the current time formatted as Minutes:Seconds:Milliseconds
@@ -164,30 +134,16 @@ std::string Timer::GetTimeFormatted() {
 
     strftime(tmp, 6, "%M:%S", gmTime);
 
-// Now tack on the milliseconds
-#ifdef _WIN32
-    struct timeb tp;
-    (void)::ftime(&tp);
-    return fmt::format("{}:{:03}", tmp, tp.millitm);
-#else
-    struct timeval t;
-    (void)gettimeofday(&t, nullptr);
-    return fmt::format("{}:{:03}", tmp, static_cast<int>(t.tv_usec / 1000));
-#endif
+    u64 milliseconds = static_cast<u64>(GetTimeMs().count()) % 1000;
+    return fmt::format("{}:{:03}", tmp, milliseconds);
 }
 
 // Returns a timestamp with decimals for precise time comparisons
 // ----------------
 double Timer::GetDoubleTime() {
-#ifdef _WIN32
-    struct timeb tp;
-    (void)::ftime(&tp);
-#else
-    struct timeval t;
-    (void)gettimeofday(&t, nullptr);
-#endif
     // Get continuous timestamp
-    u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
+    u64 TmpSeconds = static_cast<u64>(Common::Timer::GetTimeSinceJan1970().count());
+    double ms = static_cast<u64>(GetTimeMs().count()) % 1000;
 
     // Remove a few years. We only really want enough seconds to make
     // sure that we are detecting actual actions, perhaps 60 seconds is
@@ -196,12 +152,7 @@ double Timer::GetDoubleTime() {
     TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
 
     // Make a smaller integer that fits in the double
-    u32 Seconds = (u32)TmpSeconds;
-#ifdef _WIN32
-    double ms = tp.millitm / 1000.0 / 1000.0;
-#else
-    double ms = t.tv_usec / 1000000.0;
-#endif
+    u32 Seconds = static_cast<u32>(TmpSeconds);
     double TmpTime = Seconds + ms;
 
     return TmpTime;
diff --git a/src/common/timer.h b/src/common/timer.h
index 78d37426b..27b521baa 100644
--- a/src/common/timer.h
+++ b/src/common/timer.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <string>
 #include "common/common_types.h"
 
@@ -18,24 +19,22 @@ public:
 
     // The time difference is always returned in milliseconds, regardless of alternative internal
     // representation
-    u64 GetTimeDifference();
+    std::chrono::milliseconds GetTimeDifference();
     void AddTimeDifference();
 
-    static void IncreaseResolution();
-    static void RestoreResolution();
-    static u64 GetTimeSinceJan1970();
-    static u64 GetLocalTimeSinceJan1970();
+    static std::chrono::seconds GetTimeSinceJan1970();
+    static std::chrono::seconds GetLocalTimeSinceJan1970();
     static double GetDoubleTime();
 
     static std::string GetTimeFormatted();
     std::string GetTimeElapsedFormatted() const;
-    u64 GetTimeElapsed();
+    std::chrono::milliseconds GetTimeElapsed();
 
-    static u32 GetTimeMs();
+    static std::chrono::milliseconds GetTimeMs();
 
 private:
-    u64 m_LastTime;
-    u64 m_StartTime;
+    std::chrono::milliseconds m_LastTime;
+    std::chrono::milliseconds m_StartTime;
     bool m_Running;
 };