2015-05-24 06:55:12 +02:00
|
|
|
// Copyright 2008 Dolphin Emulator Project
|
2021-07-05 03:22:19 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2008-12-08 06:30:24 +01:00
|
|
|
|
2019-06-14 16:53:46 +02:00
|
|
|
#include "Common/Timer.h"
|
|
|
|
|
2020-07-12 19:36:58 +02:00
|
|
|
#include <chrono>
|
2014-02-20 04:11:52 +01:00
|
|
|
#include <string>
|
2008-12-08 06:30:24 +01:00
|
|
|
|
2010-01-21 20:55:01 +01:00
|
|
|
#ifdef _WIN32
|
2018-10-26 14:19:16 +02:00
|
|
|
#include <cwchar>
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
#include <Windows.h>
|
2010-01-21 20:55:01 +01:00
|
|
|
#include <mmsystem.h>
|
2010-07-22 06:15:11 +02:00
|
|
|
#include <sys/timeb.h>
|
2010-11-20 04:24:51 +01:00
|
|
|
#else
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
2010-01-21 20:55:01 +01:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
#include <fmt/chrono.h>
|
2019-06-14 16:53:46 +02:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
2014-02-20 04:11:52 +01:00
|
|
|
#include "Common/CommonTypes.h"
|
2014-02-17 11:18:15 +01:00
|
|
|
#include "Common/StringUtil.h"
|
2008-12-08 06:30:24 +01:00
|
|
|
|
2010-01-21 20:55:01 +01:00
|
|
|
namespace Common
|
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
template <typename Clock, typename Duration>
|
|
|
|
static typename Clock::rep time_now()
|
2010-07-22 06:15:11 +02:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
return std::chrono::time_point_cast<Duration>(Clock::now()).time_since_epoch().count();
|
2010-07-22 06:15:11 +02:00
|
|
|
}
|
2009-02-16 07:18:18 +01:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
template <typename Duration>
|
|
|
|
static auto steady_time_now()
|
2014-11-19 19:57:12 +01:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
return time_now<std::chrono::steady_clock, Duration>();
|
2014-11-19 19:57:12 +01:00
|
|
|
}
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
u64 Timer::NowUs()
|
2014-11-19 19:57:12 +01:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
return steady_time_now<std::chrono::microseconds>();
|
2014-11-19 19:57:12 +01:00
|
|
|
}
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
u64 Timer::NowMs()
|
2008-07-12 19:40:22 +02:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
return steady_time_now<std::chrono::milliseconds>();
|
2008-07-12 19:40:22 +02:00
|
|
|
}
|
2008-12-08 06:30:24 +01:00
|
|
|
|
2009-02-16 07:18:18 +01:00
|
|
|
void Timer::Start()
|
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
m_start_ms = NowMs();
|
|
|
|
m_end_ms = 0;
|
|
|
|
m_running = true;
|
2009-02-16 07:18:18 +01:00
|
|
|
}
|
2008-12-08 06:30:24 +01:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
void Timer::StartWithOffset(u64 offset)
|
2009-02-16 07:18:18 +01:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
Start();
|
|
|
|
if (m_start_ms > offset)
|
|
|
|
m_start_ms -= offset;
|
2009-02-16 07:18:18 +01:00
|
|
|
}
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
void Timer::Stop()
|
2009-02-16 07:18:18 +01:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
m_end_ms = NowMs();
|
|
|
|
m_running = false;
|
2009-02-16 07:18:18 +01:00
|
|
|
}
|
2010-07-22 06:15:11 +02:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
u64 Timer::ElapsedMs() const
|
2009-02-16 07:18:18 +01:00
|
|
|
{
|
2020-07-01 21:29:30 +02:00
|
|
|
// If we have not started yet, return zero
|
2022-07-18 05:43:47 +02:00
|
|
|
if (m_start_ms == 0)
|
2020-07-01 21:29:30 +02:00
|
|
|
return 0;
|
2009-02-16 07:18:18 +01:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
if (m_running)
|
|
|
|
{
|
|
|
|
u64 now = NowMs();
|
|
|
|
if (m_start_ms >= now)
|
|
|
|
return 0;
|
|
|
|
return now - m_start_ms;
|
|
|
|
}
|
2009-02-16 07:18:18 +01:00
|
|
|
else
|
2022-07-18 05:43:47 +02:00
|
|
|
{
|
|
|
|
if (m_start_ms >= m_end_ms)
|
|
|
|
return 0;
|
|
|
|
return m_end_ms - m_start_ms;
|
|
|
|
}
|
2008-07-12 19:40:22 +02:00
|
|
|
}
|
2008-12-13 12:57:01 +01:00
|
|
|
|
2009-02-22 13:43:25 +01:00
|
|
|
u64 Timer::GetLocalTimeSinceJan1970()
|
2008-12-13 12:57:01 +01:00
|
|
|
{
|
2010-08-26 21:24:47 +02:00
|
|
|
time_t sysTime, tzDiff, tzDST;
|
2008-12-13 12:57:01 +01:00
|
|
|
time(&sysTime);
|
2016-07-13 22:46:14 +02:00
|
|
|
tm* gmTime = localtime(&sysTime);
|
2010-08-26 21:24:47 +02:00
|
|
|
|
|
|
|
// Account for DST where needed
|
2014-03-10 12:30:55 +01:00
|
|
|
if (gmTime->tm_isdst == 1)
|
2010-08-26 21:24:47 +02:00
|
|
|
tzDST = 3600;
|
|
|
|
else
|
|
|
|
tzDST = 0;
|
|
|
|
|
2008-12-13 12:57:01 +01:00
|
|
|
// Lazy way to get local time in sec
|
|
|
|
gmTime = gmtime(&sysTime);
|
|
|
|
tzDiff = sysTime - mktime(gmTime);
|
|
|
|
|
2016-07-13 22:46:14 +02:00
|
|
|
return static_cast<u64>(sysTime + tzDiff + tzDST);
|
2008-12-13 12:57:01 +01:00
|
|
|
}
|
2009-01-15 07:48:15 +01:00
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
double Timer::GetSystemTimeAsDouble()
|
2009-08-25 08:34:58 +02:00
|
|
|
{
|
2020-07-12 19:36:58 +02:00
|
|
|
// FYI: std::chrono::system_clock epoch is not required to be 1970 until c++20.
|
|
|
|
// We will however assume time_t IS unix time.
|
|
|
|
using Clock = std::chrono::system_clock;
|
2009-08-25 08:34:58 +02:00
|
|
|
|
2020-07-12 19:36:58 +02:00
|
|
|
// TODO: Use this on switch to c++20:
|
|
|
|
// const auto since_epoch = Clock::now().time_since_epoch();
|
|
|
|
const auto unix_epoch = Clock::from_time_t({});
|
|
|
|
const auto since_epoch = Clock::now() - unix_epoch;
|
2010-07-22 06:15:11 +02:00
|
|
|
|
2020-07-12 19:36:58 +02:00
|
|
|
const auto since_double_time_epoch = since_epoch - std::chrono::seconds(DOUBLE_TIME_OFFSET);
|
|
|
|
return std::chrono::duration_cast<std::chrono::duration<double>>(since_double_time_epoch).count();
|
2009-08-25 08:34:58 +02:00
|
|
|
}
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
std::string Timer::SystemTimeAsDoubleToString(double time)
|
2015-07-12 01:49:12 +02:00
|
|
|
{
|
2022-07-18 05:43:47 +02:00
|
|
|
// revert adjustments from GetSystemTimeAsDouble() to get a normal Unix timestamp again
|
2015-07-12 01:49:12 +02:00
|
|
|
time_t seconds = (time_t)time + DOUBLE_TIME_OFFSET;
|
|
|
|
tm* localTime = localtime(&seconds);
|
|
|
|
|
2018-10-26 14:19:16 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
wchar_t tmp[32] = {};
|
2020-08-18 02:26:38 +02:00
|
|
|
wcsftime(tmp, std::size(tmp), L"%x %X", localTime);
|
2020-06-28 18:15:30 +02:00
|
|
|
return WStringToUTF8(tmp);
|
2018-10-26 14:19:16 +02:00
|
|
|
#else
|
2015-07-12 01:49:12 +02:00
|
|
|
char tmp[32] = {};
|
|
|
|
strftime(tmp, sizeof(tmp), "%x %X", localTime);
|
|
|
|
return tmp;
|
2018-10-26 14:19:16 +02:00
|
|
|
#endif
|
2015-07-12 01:49:12 +02:00
|
|
|
}
|
|
|
|
|
2022-07-18 05:43:47 +02:00
|
|
|
void Timer::IncreaseResolution()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
timeBeginPeriod(1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void Timer::RestoreResolution()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
timeEndPeriod(1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-03-28 09:57:34 +01:00
|
|
|
} // Namespace Common
|