mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-26 23:11:01 +00:00
Use clock interfaces to precisely control time
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
|
||||
namespace utils
|
||||
{
|
||||
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval)
|
||||
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(steady_clock& steady_time,
|
||||
system_clock& system_time,
|
||||
const LARGE_INTEGER delay_interval)
|
||||
{
|
||||
if (delay_interval.QuadPart <= 0)
|
||||
{
|
||||
@@ -13,7 +15,7 @@ namespace utils
|
||||
const auto relative_duration =
|
||||
std::chrono::microseconds(relative_ticks_in_ms) + std::chrono::nanoseconds(relative_fraction_ns);
|
||||
|
||||
return std::chrono::steady_clock::now() + relative_duration;
|
||||
return steady_time.now() + relative_duration;
|
||||
}
|
||||
|
||||
const auto delay_seconds_since_1601 = delay_interval.QuadPart / HUNDRED_NANOSECONDS_IN_ONE_SECOND;
|
||||
@@ -24,12 +26,12 @@ namespace utils
|
||||
const auto target_time = std::chrono::system_clock::from_time_t(delay_seconds_since_1970) +
|
||||
std::chrono::nanoseconds(delay_fraction_ns);
|
||||
|
||||
const auto now_system = std::chrono::system_clock::now();
|
||||
const auto now_system = system_time.now();
|
||||
|
||||
const auto duration_until_target =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(target_time - now_system);
|
||||
|
||||
return std::chrono::steady_clock::now() + duration_until_target;
|
||||
return steady_time.now() + duration_until_target;
|
||||
}
|
||||
|
||||
KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp)
|
||||
|
||||
@@ -10,7 +10,62 @@ constexpr auto WINDOWS_EPOCH_DIFFERENCE = EPOCH_DIFFERENCE_1601_TO_1970_SECONDS
|
||||
|
||||
namespace utils
|
||||
{
|
||||
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval);
|
||||
template <typename Clock>
|
||||
struct clock
|
||||
{
|
||||
using base_clock = Clock;
|
||||
using time_point = typename base_clock::time_point;
|
||||
using duration = typename base_clock::duration;
|
||||
|
||||
virtual ~clock() = default;
|
||||
virtual time_point now()
|
||||
{
|
||||
return base_clock::now();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Clock>
|
||||
class tick_clock : public clock<Clock>
|
||||
{
|
||||
public:
|
||||
tick_clock(const typename tick_clock::time_point start, const uint64_t frequency)
|
||||
: frequency_(frequency),
|
||||
start_(start)
|
||||
{
|
||||
if (this->frequency_ == 0)
|
||||
{
|
||||
throw std::invalid_argument("Frequency can not be 0");
|
||||
}
|
||||
}
|
||||
|
||||
typename tick_clock::time_point now() override
|
||||
{
|
||||
const auto passed_ticks = this->ticks();
|
||||
const auto passed_time =
|
||||
tick_clock::duration(passed_ticks * tick_clock::duration::period::den / this->frequency_);
|
||||
|
||||
return this->start_ + passed_time;
|
||||
}
|
||||
|
||||
virtual uint64_t ticks() = 0;
|
||||
|
||||
uint64_t get_frequency() const
|
||||
{
|
||||
return this->frequency_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t frequency_{1};
|
||||
typename tick_clock::time_point start_{};
|
||||
};
|
||||
|
||||
using system_clock = clock<std::chrono::system_clock>;
|
||||
using steady_clock = clock<std::chrono::steady_clock>;
|
||||
|
||||
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(steady_clock& steady_time,
|
||||
system_clock& system_time,
|
||||
LARGE_INTEGER delay_interval);
|
||||
|
||||
KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp);
|
||||
void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp);
|
||||
std::chrono::system_clock::time_point convert_from_ksystem_time(const KSYSTEM_TIME& time);
|
||||
@@ -18,5 +73,5 @@ namespace utils
|
||||
#ifndef OS_WINDOWS
|
||||
using __time64_t = int64_t;
|
||||
#endif
|
||||
LARGE_INTEGER convert_unix_to_windows_time(const __time64_t unix_time);
|
||||
LARGE_INTEGER convert_unix_to_windows_time(__time64_t unix_time);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user