mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Introduce MonotonicTime
This class takes on the duties of CLOCK_MONOTONIC, a time without a defined reference point that always increases. This informs some important design decisions about the class API: MonotonicTime cannot be constructed from external time data, except as a computation based on other monotonic time, or the current monotonic time. Importantly, there is no default constructor, since the reference point of monotonic time is unspecified and therefore without meaning as a default. The current use of monotonic time (via Duration) includes some potential problems that may be caught when we move most to all code to MonotonicTime in the next commit. The API restrictions have one important relaxation: Kernel::TimeManagement is allowed to exchange raw time data within MonotonicTime freely. This is required for the clock-agnostic time accessors for timeouts and syscalls, as well as creating monotonic time data from hardware in the first place.
This commit is contained in:
parent
69e27169c4
commit
b2e7b8cdff
Notes:
sideshowbarker
2024-07-17 07:31:31 +09:00
Author: https://github.com/kleinesfilmroellchen Commit: https://github.com/SerenityOS/serenity/commit/b2e7b8cdff Pull-request: https://github.com/SerenityOS/serenity/pull/17842 Reviewed-by: https://github.com/me-minus Reviewed-by: https://github.com/timschumi
2 changed files with 79 additions and 0 deletions
10
AK/Time.cpp
10
AK/Time.cpp
|
@ -227,6 +227,16 @@ Duration Duration::now_monotonic_coarse()
|
|||
return now_time_from_clock(CLOCK_MONOTONIC_COARSE);
|
||||
}
|
||||
|
||||
MonotonicTime MonotonicTime::now()
|
||||
{
|
||||
return MonotonicTime { now_time_from_clock(CLOCK_MONOTONIC) };
|
||||
}
|
||||
|
||||
MonotonicTime MonotonicTime::now_coarse()
|
||||
{
|
||||
return MonotonicTime { now_time_from_clock(CLOCK_MONOTONIC_COARSE) };
|
||||
}
|
||||
|
||||
UnixDateTime UnixDateTime::now()
|
||||
{
|
||||
return UnixDateTime { now_time_from_clock(CLOCK_REALTIME) };
|
||||
|
|
69
AK/Time.h
69
AK/Time.h
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/Array.h>
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/Badge.h>
|
||||
#include <AK/Checked.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/Types.h>
|
||||
|
@ -15,6 +16,12 @@
|
|||
#if defined(AK_OS_SERENITY) && defined(KERNEL)
|
||||
# include <Kernel/API/POSIX/sys/time.h>
|
||||
# include <Kernel/API/POSIX/time.h>
|
||||
|
||||
// We need a Badge<TimeManagement> for some MonotonicTime operations.
|
||||
namespace Kernel {
|
||||
class TimeManagement;
|
||||
}
|
||||
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
|
@ -456,6 +463,67 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
// Monotonic time represents time returned from the CLOCK_MONOTONIC clock, which has an arbitrary fixed reference point.
|
||||
class MonotonicTime : private Detail::UnawareTime {
|
||||
public:
|
||||
// Monotonic time does not have a defined reference point.
|
||||
// A MonotonicTime at the reference point is therefore meaningless.
|
||||
MonotonicTime() = delete;
|
||||
constexpr MonotonicTime(MonotonicTime const&) = default;
|
||||
constexpr MonotonicTime(MonotonicTime&&) = default;
|
||||
constexpr MonotonicTime& operator=(MonotonicTime const&) = default;
|
||||
constexpr MonotonicTime& operator=(MonotonicTime&&) = default;
|
||||
|
||||
#ifndef KERNEL
|
||||
[[nodiscard]] static MonotonicTime now();
|
||||
[[nodiscard]] static MonotonicTime now_coarse();
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
// Clang-format likes to expand this function for some reason.
|
||||
[[nodiscard]] i64 seconds() const { return m_offset.to_seconds(); }
|
||||
// clang-format on
|
||||
[[nodiscard]] i64 milliseconds() const { return m_offset.to_milliseconds(); }
|
||||
[[nodiscard]] i64 nanoseconds() const { return m_offset.to_nanoseconds(); }
|
||||
// Never returns a point in the future, since fractional seconds are cut off.
|
||||
[[nodiscard]] i64 truncated_seconds() const { return m_offset.to_truncated_seconds(); }
|
||||
[[nodiscard]] i64 nanoseconds_within_second() const { return to_timespec().tv_nsec; }
|
||||
|
||||
// clang-format off
|
||||
constexpr bool operator==(MonotonicTime const& other) const { return this->m_offset == other.m_offset; }
|
||||
// clang-format on
|
||||
constexpr int operator<=>(MonotonicTime const& other) const { return this->m_offset <=> other.m_offset; }
|
||||
|
||||
constexpr MonotonicTime operator+(Duration const& other) const { return MonotonicTime { m_offset + other }; }
|
||||
constexpr MonotonicTime& operator+=(Duration const& other)
|
||||
{
|
||||
this->m_offset = this->m_offset + other;
|
||||
return *this;
|
||||
}
|
||||
constexpr MonotonicTime operator-(Duration const& other) const { return MonotonicTime { m_offset - other }; }
|
||||
constexpr Duration operator-(MonotonicTime const& other) const { return m_offset - other.m_offset; }
|
||||
|
||||
#ifdef KERNEL
|
||||
// Required in the Kernel in order to create monotonic time information from hardware timers.
|
||||
[[nodiscard]] static MonotonicTime from_hardware_time(Badge<Kernel::TimeManagement>, time_t seconds, long nanoseconds)
|
||||
{
|
||||
return MonotonicTime { Duration::from_timespec({ seconds, nanoseconds }) };
|
||||
}
|
||||
|
||||
// "Start" is whenever the hardware timers started counting (e.g. for HPET it's most certainly boot).
|
||||
[[nodiscard]] Duration time_since_start(Badge<Kernel::TimeManagement>)
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
constexpr explicit MonotonicTime(Duration offset)
|
||||
: Detail::UnawareTime(offset)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TimevalType>
|
||||
inline void timeval_sub(TimevalType const& a, TimevalType const& b, TimevalType& result)
|
||||
{
|
||||
|
@ -545,6 +613,7 @@ using AK::days_in_year;
|
|||
using AK::days_since_epoch;
|
||||
using AK::Duration;
|
||||
using AK::is_leap_year;
|
||||
using AK::MonotonicTime;
|
||||
using AK::seconds_since_epoch_to_year;
|
||||
using AK::timespec_add;
|
||||
using AK::timespec_add_timeval;
|
||||
|
|
Loading…
Reference in a new issue