| /* |
| * Copyright (C) 2016 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include <wtf/MathExtras.h> |
| #include <wtf/Optional.h> |
| |
| namespace WTF { |
| |
| class MonotonicTime; |
| class PrintStream; |
| class TimeWithDynamicClockType; |
| class WallTime; |
| |
| class Seconds final { |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| constexpr Seconds() { } |
| |
| explicit constexpr Seconds(double value) |
| : m_value(value) |
| { |
| } |
| |
| constexpr double value() const { return m_value; } |
| |
| constexpr double minutes() const { return m_value / 60; } |
| constexpr double seconds() const { return m_value; } |
| constexpr double milliseconds() const { return seconds() * 1000; } |
| constexpr double microseconds() const { return milliseconds() * 1000; } |
| constexpr double nanoseconds() const { return microseconds() * 1000; } |
| |
| // Keep in mind that Seconds is held in double. If the value is not in range of 53bit integer, the result may not be precise. |
| template<typename T> T minutesAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(minutes()); } |
| template<typename T> T secondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(seconds()); } |
| template<typename T> T millisecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(milliseconds()); } |
| template<typename T> T microsecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(microseconds()); } |
| template<typename T> T nanosecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(nanoseconds()); } |
| |
| static constexpr Seconds fromMinutes(double minutes) |
| { |
| return Seconds(minutes * 60); |
| } |
| |
| static constexpr Seconds fromHours(double hours) |
| { |
| return Seconds(hours * 3600); |
| } |
| |
| static constexpr Seconds fromMilliseconds(double milliseconds) |
| { |
| return Seconds(milliseconds / 1000); |
| } |
| |
| static constexpr Seconds fromMicroseconds(double microseconds) |
| { |
| return fromMilliseconds(microseconds / 1000); |
| } |
| |
| static constexpr Seconds fromNanoseconds(double nanoseconds) |
| { |
| return fromMicroseconds(nanoseconds / 1000); |
| } |
| |
| static constexpr Seconds infinity() |
| { |
| return Seconds(std::numeric_limits<double>::infinity()); |
| } |
| |
| static constexpr Seconds nan() |
| { |
| return Seconds(std::numeric_limits<double>::quiet_NaN()); |
| } |
| |
| explicit constexpr operator bool() const { return !!m_value; } |
| |
| constexpr Seconds operator+(Seconds other) const |
| { |
| return Seconds(value() + other.value()); |
| } |
| |
| constexpr Seconds operator-(Seconds other) const |
| { |
| return Seconds(value() - other.value()); |
| } |
| |
| constexpr Seconds operator-() const |
| { |
| return Seconds(-value()); |
| } |
| |
| // It makes sense to consider scaling a duration, like, "I want to wait 5 times as long as |
| // last time!". |
| constexpr Seconds operator*(double scalar) const |
| { |
| return Seconds(value() * scalar); |
| } |
| |
| constexpr Seconds operator/(double scalar) const |
| { |
| return Seconds(value() / scalar); |
| } |
| |
| // It's reasonable to think about ratios between Seconds. |
| constexpr double operator/(Seconds other) const |
| { |
| return value() / other.value(); |
| } |
| |
| Seconds operator%(double scalar) const |
| { |
| return Seconds(fmod(value(), scalar)); |
| } |
| |
| // This solves for r, where: |
| // |
| // floor(this / other) + r / other = this / other |
| // |
| // Therefore, if this is Seconds then r is Seconds. |
| Seconds operator%(Seconds other) const |
| { |
| return Seconds(fmod(value(), other.value())); |
| } |
| |
| Seconds& operator+=(Seconds other) |
| { |
| return *this = *this + other; |
| } |
| |
| Seconds& operator-=(Seconds other) |
| { |
| return *this = *this - other; |
| } |
| |
| Seconds& operator*=(double scalar) |
| { |
| return *this = *this * scalar; |
| } |
| |
| Seconds& operator/=(double scalar) |
| { |
| return *this = *this / scalar; |
| } |
| |
| Seconds& operator%=(double scalar) |
| { |
| return *this = *this % scalar; |
| } |
| |
| Seconds& operator%=(Seconds other) |
| { |
| return *this = *this % other; |
| } |
| |
| WTF_EXPORT_PRIVATE WallTime operator+(WallTime) const; |
| WTF_EXPORT_PRIVATE MonotonicTime operator+(MonotonicTime) const; |
| WTF_EXPORT_PRIVATE TimeWithDynamicClockType operator+(const TimeWithDynamicClockType&) const; |
| |
| WTF_EXPORT_PRIVATE WallTime operator-(WallTime) const; |
| WTF_EXPORT_PRIVATE MonotonicTime operator-(MonotonicTime) const; |
| WTF_EXPORT_PRIVATE TimeWithDynamicClockType operator-(const TimeWithDynamicClockType&) const; |
| |
| constexpr bool operator==(Seconds other) const |
| { |
| return m_value == other.m_value; |
| } |
| |
| constexpr bool operator!=(Seconds other) const |
| { |
| return m_value != other.m_value; |
| } |
| |
| constexpr bool operator<(Seconds other) const |
| { |
| return m_value < other.m_value; |
| } |
| |
| constexpr bool operator>(Seconds other) const |
| { |
| return m_value > other.m_value; |
| } |
| |
| constexpr bool operator<=(Seconds other) const |
| { |
| return m_value <= other.m_value; |
| } |
| |
| constexpr bool operator>=(Seconds other) const |
| { |
| return m_value >= other.m_value; |
| } |
| |
| WTF_EXPORT_PRIVATE void dump(PrintStream&) const; |
| |
| Seconds isolatedCopy() const |
| { |
| return *this; |
| } |
| |
| template<class Encoder> |
| void encode(Encoder& encoder) const |
| { |
| encoder << m_value; |
| } |
| |
| template<class Decoder> |
| static Optional<Seconds> decode(Decoder& decoder) |
| { |
| Optional<double> seconds; |
| decoder >> seconds; |
| if (!seconds) |
| return WTF::nullopt; |
| return Seconds(*seconds); |
| } |
| |
| template<class Decoder> |
| static bool decode(Decoder& decoder, Seconds& seconds) |
| { |
| double value; |
| if (!decoder.decode(value)) |
| return false; |
| |
| seconds = Seconds(value); |
| return true; |
| } |
| |
| struct MarkableTraits; |
| |
| private: |
| double m_value { 0 }; |
| }; |
| |
| WTF_EXPORT_PRIVATE void sleep(Seconds); |
| |
| struct Seconds::MarkableTraits { |
| static bool isEmptyValue(Seconds seconds) |
| { |
| return std::isnan(seconds.value()); |
| } |
| |
| static constexpr Seconds emptyValue() |
| { |
| return Seconds::nan(); |
| } |
| }; |
| |
| inline namespace seconds_literals { |
| |
| constexpr Seconds operator"" _min(long double minutes) |
| { |
| return Seconds::fromMinutes(minutes); |
| } |
| |
| constexpr Seconds operator"" _h(long double hours) |
| { |
| return Seconds::fromHours(hours); |
| } |
| |
| constexpr Seconds operator"" _s(long double seconds) |
| { |
| return Seconds(seconds); |
| } |
| |
| constexpr Seconds operator"" _ms(long double milliseconds) |
| { |
| return Seconds::fromMilliseconds(milliseconds); |
| } |
| |
| constexpr Seconds operator"" _us(long double microseconds) |
| { |
| return Seconds::fromMicroseconds(microseconds); |
| } |
| |
| constexpr Seconds operator"" _ns(long double nanoseconds) |
| { |
| return Seconds::fromNanoseconds(nanoseconds); |
| } |
| |
| constexpr Seconds operator"" _min(unsigned long long minutes) |
| { |
| return Seconds::fromMinutes(minutes); |
| } |
| |
| constexpr Seconds operator"" _h(unsigned long long hours) |
| { |
| return Seconds::fromHours(hours); |
| } |
| |
| constexpr Seconds operator"" _s(unsigned long long seconds) |
| { |
| return Seconds(seconds); |
| } |
| |
| constexpr Seconds operator"" _ms(unsigned long long milliseconds) |
| { |
| return Seconds::fromMilliseconds(milliseconds); |
| } |
| |
| constexpr Seconds operator"" _us(unsigned long long microseconds) |
| { |
| return Seconds::fromMicroseconds(microseconds); |
| } |
| |
| constexpr Seconds operator"" _ns(unsigned long long nanoseconds) |
| { |
| return Seconds::fromNanoseconds(nanoseconds); |
| } |
| |
| } // inline seconds_literals |
| |
| } // namespace WTF |
| |
| using WTF::sleep; |
| |
| namespace std { |
| |
| inline bool isnan(WTF::Seconds seconds) |
| { |
| return std::isnan(seconds.value()); |
| } |
| |
| inline bool isinf(WTF::Seconds seconds) |
| { |
| return std::isinf(seconds.value()); |
| } |
| |
| inline bool isfinite(WTF::Seconds seconds) |
| { |
| return std::isfinite(seconds.value()); |
| } |
| |
| } // namespace std |
| |
| using namespace WTF::seconds_literals; |
| using WTF::Seconds; |