Bug 1039924 part 4 - Fill out TimeDurationValueCalculator and use it; r=froydnj
authorBrian Birtles <birtles@gmail.com>
Thu, 25 Sep 2014 14:25:49 +0900
changeset 207152 82fbeb45b3d6bb6560ca4ee15138dcc46a2982bf
parent 207151 af942cc33a8385e684ecc850f74af424482211b3
child 207153 2dd874cbd5f794bbfb6879c14464ef03018275ab
push id27546
push usercbook@mozilla.com
push dateThu, 25 Sep 2014 12:23:21 +0000
treeherdermozilla-central@c3660fb07ffd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1039924
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1039924 part 4 - Fill out TimeDurationValueCalculator and use it; r=froydnj This patch builds on the templatization from the previous patch to move arithmetic on the mValue member of BaseTimeDuration to the ValueCalculator template parameter.
xpcom/ds/TimeStamp.h
--- a/xpcom/ds/TimeStamp.h
+++ b/xpcom/ds/TimeStamp.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_TimeStamp_h
 #define mozilla_TimeStamp_h
 
 #include <stdint.h>
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/TypeTraits.h"
 #include "nscore.h"
 #include "nsDebug.h"
 
 namespace IPC {
 template<typename T> struct ParamTraits;
 }
 
 #ifdef XP_WIN
@@ -138,75 +139,80 @@ public:
 
   static BaseTimeDuration Forever()
   {
     return FromTicks(INT64_MAX);
   }
 
   BaseTimeDuration operator+(const BaseTimeDuration& aOther) const
   {
-    return FromTicks(mValue + aOther.mValue);
+    return FromTicks(ValueCalculator::Add(mValue, aOther.mValue));
   }
   BaseTimeDuration operator-(const BaseTimeDuration& aOther) const
   {
-    return FromTicks(mValue - aOther.mValue);
+    return FromTicks(ValueCalculator::Subtract(mValue, aOther.mValue));
   }
   BaseTimeDuration& operator+=(const BaseTimeDuration& aOther)
   {
-    mValue += aOther.mValue;
+    mValue = ValueCalculator::Add(mValue, aOther.mValue);
     return *this;
   }
   BaseTimeDuration& operator-=(const BaseTimeDuration& aOther)
   {
-    mValue -= aOther.mValue;
+    mValue = ValueCalculator::Subtract(mValue, aOther.mValue);
     return *this;
   }
 
 private:
   // Block double multiplier (slower, imprecise if long duration) - Bug 853398.
   // If required, use MultDouble explicitly and with care.
   BaseTimeDuration operator*(const double aMultiplier) const MOZ_DELETE;
 
 public:
   BaseTimeDuration MultDouble(double aMultiplier) const
   {
-    return FromTicks(static_cast<int64_t>(mValue * aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const int32_t aMultiplier) const
   {
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const uint32_t aMultiplier) const
   {
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const int64_t aMultiplier) const
   {
-    return FromTicks(mValue * aMultiplier);
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const uint64_t aMultiplier) const
   {
     if (aMultiplier > INT64_MAX) {
       NS_WARNING("Out-of-range multiplier when multiplying BaseTimeDuration");
       return Forever();
     }
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator/(const int64_t aDivisor) const
   {
-    return FromTicks(mValue / aDivisor);
+    MOZ_ASSERT(aDivisor != 0, "Division by zero");
+    return FromTicks(ValueCalculator::Divide(mValue, aDivisor));
   }
   double operator/(const BaseTimeDuration& aOther) const
   {
-    return static_cast<double>(mValue) / aOther.mValue;
+#ifndef MOZ_B2G
+    // Bug 1066388 - This fails on B2G ICS Emulator
+    MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
+#endif
+    return ValueCalculator::DivideDouble(mValue, aOther.mValue);
   }
   BaseTimeDuration operator%(const BaseTimeDuration& aOther) const
   {
     MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
-    return FromTicks(mValue % aOther.mValue);
+    return FromTicks(ValueCalculator::Modulo(mValue, aOther.mValue));
   }
 
   template<typename E>
   bool operator<(const BaseTimeDuration<E>& aOther) const
   {
     return mValue < aOther.mValue;
   }
   template<typename E>
@@ -278,20 +284,58 @@ private:
 
     return FromTicks(int64_t(aTicks));
   }
 
   // Duration, result is implementation-specific difference of two TimeStamps
   int64_t mValue;
 };
 
-// FIXME: To be filled-in a subsequent patch in this series.
+/**
+ * Perform arithmetic operations on the value of a BaseTimeDuration without
+ * doing strict checks on the range of values.
+ */
 class TimeDurationValueCalculator
-{ };
+{
+public:
+  static int64_t Add(int64_t aA, int64_t aB) { return aA + aB; }
+  static int64_t Subtract(int64_t aA, int64_t aB) { return aA - aB; }
+
+  template <typename T>
+  static int64_t Multiply(int64_t aA, T aB)
+  {
+    static_assert(IsIntegral<T>::value,
+                  "Using integer multiplication routine with non-integer type."
+                  " Further specialization required");
+    return aA * static_cast<int64_t>(aB);
+  }
 
+  static int64_t Divide(int64_t aA, int64_t aB) { return aA / aB; }
+  static double DivideDouble(int64_t aA, int64_t aB)
+  {
+    return static_cast<double>(aA) / aB;
+  }
+  static int64_t Modulo(int64_t aA, int64_t aB) { return aA % aB; }
+};
+
+template <>
+inline int64_t
+TimeDurationValueCalculator::Multiply<double>(int64_t aA, double aB)
+{
+  return static_cast<int64_t>(aA * aB);
+}
+
+/**
+ * Specialization of BaseTimeDuration that uses TimeDurationValueCalculator for
+ * arithmetic on the mValue member.
+ *
+ * Use this class for time durations that are *not* expected to hold values of
+ * Forever (or the negative equivalent) or when such time duration are *not*
+ * expected to be used in arithmetic operations.
+ */
 typedef BaseTimeDuration<TimeDurationValueCalculator> TimeDuration;
 
 /**
  * Instances of this class represent moments in time, or a special
  * "null" moment. We do not use the non-monotonic system clock or
  * local time, since they can be reset, causing apparent backward
  * travel in time, which can confuse algorithms. Instead we measure
  * elapsed time according to the system.  This time can never go