// This file is part of Desktop App Toolkit, // a set of libraries for developing nice desktop applications. // // For license and copyright information please follow this link: // https://github.com/desktop-app/legal/blob/master/LEGAL // #include #include #include #include namespace crl { namespace details { namespace { time LastAdjustmentTime/* = 0*/; std::time_t LastAdjustmentUnixtime/* = 0*/; using seconds_type = std::uint32_t; std::atomic AdjustSeconds/* = 0*/; inner_time_type StartValue/* = 0*/; inner_profile_type StartProfileValue/* = 0*/; struct StaticInit { StaticInit(); }; StaticInit::StaticInit() { StartValue = current_value(); StartProfileValue = current_profile_value(); init(); LastAdjustmentUnixtime = ::time(nullptr); } StaticInit StaticInitObject; bool adjust_time() { const auto now = crl::now(); const auto delta = (now - LastAdjustmentTime); const auto unixtime = ::time(nullptr); const auto real = (unixtime - LastAdjustmentUnixtime); const auto seconds = (time(real) * 1000 - delta) / 1000; LastAdjustmentUnixtime = unixtime; LastAdjustmentTime = now; if (seconds <= 0) { return false; } auto current = seconds_type(0); static constexpr auto max = std::numeric_limits::max(); while (true) { if (time(current) + seconds > time(max)) { return false; } const auto next = current + seconds_type(seconds); if (AdjustSeconds.compare_exchange_weak(current, next)) { return true; } } return false; } time compute_adjustment() { return time(AdjustSeconds.load()) * 1000; } profile_time compute_profile_adjustment() { return compute_adjustment() * 1000; } } // namespace } // namespace details time now() { const auto elapsed = details::current_value() - details::StartValue; return details::convert(elapsed) + details::compute_adjustment(); } profile_time profile() { const auto elapsed = details::current_profile_value() - details::StartProfileValue; return details::convert_profile(elapsed) + details::compute_profile_adjustment(); } bool adjust_time() { return details::adjust_time(); } } // namespace crl