Source/WTF:
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Mar 2017 13:20:52 +0000 (13:20 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Mar 2017 13:20:52 +0000 (13:20 +0000)
Add secondsAs<T> methods to Seconds to convert it to integers with clamp
https://bugs.webkit.org/show_bug.cgi?id=169537

Reviewed by Carlos Garcia Campos.

When using the usual static_cast, infinity becomes 0 accidentally.
It is not intended value when using Seconds for timeout value.
Instead, we use clampToAccepting64 to convert Seconds to
integer values to pass them to the system functions.

* wtf/MathExtras.h:
(clampToAccepting64):
* wtf/Seconds.h:
(WTF::Seconds::minutesAs):
(WTF::Seconds::secondsAs):
(WTF::Seconds::millisecondsAs):
(WTF::Seconds::microsecondsAs):
(WTF::Seconds::nanosecondsAs):
* wtf/cocoa/WorkQueueCocoa.cpp:
(WTF::WorkQueue::dispatchAfter):
* wtf/glib/RunLoopGLib.cpp:
(WTF::RunLoop::dispatchAfter):
(WTF::RunLoop::TimerBase::updateReadyTime):

Tools:
[WTF] Clean up RunLoop and WorkQueue with Seconds and Function
https://bugs.webkit.org/show_bug.cgi?id=169537

Reviewed by Carlos Garcia Campos.

* TestWebKitAPI/Tests/WTF/Time.cpp:
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213896 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WTF/ChangeLog
Source/WTF/wtf/MathExtras.h
Source/WTF/wtf/Seconds.h
Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp
Source/WTF/wtf/glib/RunLoopGLib.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/Time.cpp

index c2fff70..b9145c7 100644 (file)
@@ -1,3 +1,29 @@
+2017-03-14  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Add secondsAs<T> methods to Seconds to convert it to integers with clamp
+        https://bugs.webkit.org/show_bug.cgi?id=169537
+
+        Reviewed by Carlos Garcia Campos.
+
+        When using the usual static_cast, infinity becomes 0 accidentally.
+        It is not intended value when using Seconds for timeout value.
+        Instead, we use clampToAccepting64 to convert Seconds to
+        integer values to pass them to the system functions.
+
+        * wtf/MathExtras.h:
+        (clampToAccepting64):
+        * wtf/Seconds.h:
+        (WTF::Seconds::minutesAs):
+        (WTF::Seconds::secondsAs):
+        (WTF::Seconds::millisecondsAs):
+        (WTF::Seconds::microsecondsAs):
+        (WTF::Seconds::nanosecondsAs):
+        * wtf/cocoa/WorkQueueCocoa.cpp:
+        (WTF::WorkQueue::dispatchAfter):
+        * wtf/glib/RunLoopGLib.cpp:
+        (WTF::RunLoop::dispatchAfter):
+        (WTF::RunLoop::TimerBase::updateReadyTime):
+
 2017-03-13  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC][Linux] Implement VMTrap in Linux ports
index c1093fa..2c7b148 100644 (file)
@@ -193,6 +193,17 @@ inline int clampToInteger(T x)
     return static_cast<int>(x);
 }
 
+// Explicitly accept 64bit result when clamping double value.
+// Keep in mind that double can only represent 53bit integer precisely.
+template<typename T> inline T clampToAccepting64(double value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>())
+{
+    if (value >= static_cast<double>(max))
+        return max;
+    if (value <= static_cast<double>(min))
+        return min;
+    return static_cast<T>(value);
+}
+
 inline bool isWithinIntRange(float x)
 {
     return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
index 6268761..d07ffef 100644 (file)
@@ -51,6 +51,13 @@ public:
     double milliseconds() const { return seconds() * 1000; }
     double microseconds() const { return milliseconds() * 1000; }
     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)
     {
index ffdfba5..1a7219a 100644 (file)
@@ -39,7 +39,7 @@ void WorkQueue::dispatch(Function<void()>&& function)
 
 void WorkQueue::dispatchAfter(Seconds duration, Function<void()>&& function)
 {
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration.nanoseconds()), m_dispatchQueue, BlockPtr<void()>::fromCallable([protectedThis = makeRef(*this), function = WTFMove(function)] {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration.nanosecondsAs<int64_t>()), m_dispatchQueue, BlockPtr<void()>::fromCallable([protectedThis = makeRef(*this), function = WTFMove(function)] {
         function();
     }).get());
 }
index f5af690..258741f 100644 (file)
@@ -140,7 +140,7 @@ private:
 
 void RunLoop::dispatchAfter(Seconds duration, Function<void()>&& function)
 {
-    GRefPtr<GSource> source = adoptGRef(g_timeout_source_new(duration.milliseconds()));
+    GRefPtr<GSource> source = adoptGRef(g_timeout_source_new(duration.millisecondsAs<guint>()));
     g_source_set_name(source.get(), "[WebKit] RunLoop dispatchAfter");
 
     std::unique_ptr<DispatchAfterContext> context = std::make_unique<DispatchAfterContext>(WTFMove(function));
@@ -185,7 +185,7 @@ void RunLoop::TimerBase::updateReadyTime()
     }
 
     gint64 currentTime = g_get_monotonic_time();
-    gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, m_fireInterval.microseconds());
+    gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, m_fireInterval.microsecondsAs<gint64>());
     ASSERT(targetTime >= currentTime);
     g_source_set_ready_time(m_source.get(), targetTime);
 }
index 3780f47..4a42e9f 100644 (file)
@@ -1,3 +1,13 @@
+2017-03-14  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WTF] Clean up RunLoop and WorkQueue with Seconds and Function
+        https://bugs.webkit.org/show_bug.cgi?id=169537
+
+        Reviewed by Carlos Garcia Campos.
+
+        * TestWebKitAPI/Tests/WTF/Time.cpp:
+        (TestWebKitAPI::TEST):
+
 2017-03-13  Brady Eidson  <beidson@apple.com>
 
         WKWebView provides no access to cookies.
index 52e7149..756c4f5 100644 (file)
@@ -314,5 +314,44 @@ TEST(WTF_Time, literals)
     EXPECT_TRUE(Seconds::fromNanoseconds(2.5) == 2.5_ns);
 }
 
+TEST(WTF_Time, clamp)
+{
+    Seconds positiveInfinity = Seconds::infinity();
+    EXPECT_TRUE(positiveInfinity.secondsAs<int32_t>() == INT32_MAX);
+    EXPECT_TRUE(positiveInfinity.secondsAs<uint32_t>() == UINT32_MAX);
+    EXPECT_TRUE(positiveInfinity.secondsAs<int64_t>() == INT64_MAX);
+    EXPECT_TRUE(positiveInfinity.secondsAs<uint64_t>() == UINT64_MAX);
+    EXPECT_TRUE(positiveInfinity.millisecondsAs<int32_t>() == INT32_MAX);
+    EXPECT_TRUE(positiveInfinity.millisecondsAs<uint32_t>() == UINT32_MAX);
+    EXPECT_TRUE(positiveInfinity.millisecondsAs<int64_t>() == INT64_MAX);
+    EXPECT_TRUE(positiveInfinity.millisecondsAs<uint64_t>() == UINT64_MAX);
+    EXPECT_TRUE(positiveInfinity.microsecondsAs<int32_t>() == INT32_MAX);
+    EXPECT_TRUE(positiveInfinity.microsecondsAs<uint32_t>() == UINT32_MAX);
+    EXPECT_TRUE(positiveInfinity.microsecondsAs<int64_t>() == INT64_MAX);
+    EXPECT_TRUE(positiveInfinity.microsecondsAs<uint64_t>() == UINT64_MAX);
+    EXPECT_TRUE(positiveInfinity.nanosecondsAs<int32_t>() == INT32_MAX);
+    EXPECT_TRUE(positiveInfinity.nanosecondsAs<uint32_t>() == UINT32_MAX);
+    EXPECT_TRUE(positiveInfinity.nanosecondsAs<int64_t>() == INT64_MAX);
+    EXPECT_TRUE(positiveInfinity.nanosecondsAs<uint64_t>() == UINT64_MAX);
+
+    Seconds negativeInfinity = -Seconds::infinity();
+    EXPECT_TRUE(negativeInfinity.secondsAs<int32_t>() == INT32_MIN);
+    EXPECT_TRUE(negativeInfinity.secondsAs<uint32_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.secondsAs<int64_t>() == INT64_MIN);
+    EXPECT_TRUE(negativeInfinity.secondsAs<uint64_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.millisecondsAs<int32_t>() == INT32_MIN);
+    EXPECT_TRUE(negativeInfinity.millisecondsAs<uint32_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.millisecondsAs<int64_t>() == INT64_MIN);
+    EXPECT_TRUE(negativeInfinity.millisecondsAs<uint64_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.microsecondsAs<int32_t>() == INT32_MIN);
+    EXPECT_TRUE(negativeInfinity.microsecondsAs<uint32_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.microsecondsAs<int64_t>() == INT64_MIN);
+    EXPECT_TRUE(negativeInfinity.microsecondsAs<uint64_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.nanosecondsAs<int32_t>() == INT32_MIN);
+    EXPECT_TRUE(negativeInfinity.nanosecondsAs<uint32_t>() == 0);
+    EXPECT_TRUE(negativeInfinity.nanosecondsAs<int64_t>() == INT64_MIN);
+    EXPECT_TRUE(negativeInfinity.nanosecondsAs<uint64_t>() == 0);
+}
+
 } // namespace TestWebKitAPI