Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
      6 #define CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
      7 
      8 #include "base/time/time.h"
      9 #include "content/common/content_export.h"
     10 
     11 namespace content {
     12 
     13 class LocalTimeDelta;
     14 class LocalTimeTicks;
     15 class RemoteTimeDelta;
     16 class RemoteTimeTicks;
     17 
     18 // On Windows, TimeTicks are not consistent between processes. Often, the values
     19 // on one process have a static offset relative to another. Occasionally, these
     20 // offsets shift while running.
     21 //
     22 // To combat this, any TimeTicks values sent from the remote process to the
     23 // local process must be tweaked in order to appear monotonic.
     24 //
     25 // In order to properly tweak ticks, we need 4 reference points:
     26 //
     27 // - |local_lower_bound|:  A known point, recorded on the local process, that
     28 //                         occurs before any remote values that will be
     29 //                         converted.
     30 // - |remote_lower_bound|: The equivalent point on the remote process. This
     31 //                         should be recorded immediately after
     32 //                         |local_lower_bound|.
     33 // - |local_upper_bound|:  A known point, recorded on the local process, that
     34 //                         occurs after any remote values that will be
     35 //                         converted.
     36 // - |remote_upper_bound|: The equivalent point on the remote process. This
     37 //                         should be recorded immediately before
     38 //                         |local_upper_bound|.
     39 //
     40 // Once these bounds are determined, values within the remote process's range
     41 // can be converted to the local process's range. The values are converted as
     42 // follows:
     43 //
     44 // 1. If the remote's range exceeds the local's range, it is scaled to fit.
     45 //    Any values converted will have the same scale factor applied.
     46 //
     47 // 2. The remote's range is shifted so that it is centered within the
     48 //    local's range. Any values converted will be shifted the same amount.
     49 class CONTENT_EXPORT InterProcessTimeTicksConverter {
     50  public:
     51   InterProcessTimeTicksConverter(const LocalTimeTicks& local_lower_bound,
     52                                  const LocalTimeTicks& local_upper_bound,
     53                                  const RemoteTimeTicks& remote_lower_bound,
     54                                  const RemoteTimeTicks& remote_upper_bound);
     55 
     56   // Returns the value within the local's bounds that correlates to
     57   // |remote_ms|.
     58   LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms) const;
     59 
     60   // Returns the equivalent delta after applying remote-to-local scaling to
     61   // |remote_delta|.
     62   LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta) const;
     63 
     64   // Returns true iff the TimeTicks are converted by adding a constant, without
     65   // scaling. This is the case whenever the remote timespan is smaller than the
     66   // local timespan, which should be the majority of cases due to IPC overhead.
     67   bool IsSkewAdditiveForMetrics() const;
     68 
     69   // Returns the (remote time) - (local time) difference estimated by the
     70   // converter. This is the constant that is subtracted from remote TimeTicks to
     71   // get local TimeTicks when no scaling is applied.
     72   base::TimeDelta GetSkewForMetrics() const;
     73 
     74  private:
     75   int64 Convert(int64 value) const;
     76 
     77   // The local time which |remote_lower_bound_| is mapped to.
     78   int64 local_base_time_;
     79 
     80   int64 numerator_;
     81   int64 denominator_;
     82 
     83   int64 remote_lower_bound_;
     84   int64 remote_upper_bound_;
     85 };
     86 
     87 class CONTENT_EXPORT LocalTimeDelta {
     88  public:
     89   int ToInt32() const { return value_; }
     90 
     91  private:
     92   friend class InterProcessTimeTicksConverter;
     93   friend class LocalTimeTicks;
     94 
     95   LocalTimeDelta(int value) : value_(value) {}
     96 
     97   int value_;
     98 };
     99 
    100 class CONTENT_EXPORT LocalTimeTicks {
    101  public:
    102   static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) {
    103     return LocalTimeTicks(value.ToInternalValue());
    104   }
    105 
    106   base::TimeTicks ToTimeTicks() {
    107     return base::TimeTicks::FromInternalValue(value_);
    108   }
    109 
    110   LocalTimeTicks operator+(const LocalTimeDelta& delta) {
    111     return LocalTimeTicks(value_ + delta.value_);
    112   }
    113 
    114  private:
    115   friend class InterProcessTimeTicksConverter;
    116 
    117   LocalTimeTicks(int64 value) : value_(value) {}
    118 
    119   int64 value_;
    120 };
    121 
    122 class CONTENT_EXPORT RemoteTimeDelta {
    123  public:
    124   static RemoteTimeDelta FromRawDelta(int delta) {
    125     return RemoteTimeDelta(delta);
    126   }
    127 
    128  private:
    129   friend class InterProcessTimeTicksConverter;
    130   friend class RemoteTimeTicks;
    131 
    132   RemoteTimeDelta(int value) : value_(value) {}
    133 
    134   int value_;
    135 };
    136 
    137 class CONTENT_EXPORT RemoteTimeTicks {
    138  public:
    139   static RemoteTimeTicks FromTimeTicks(const base::TimeTicks& ticks) {
    140     return RemoteTimeTicks(ticks.ToInternalValue());
    141   }
    142 
    143   RemoteTimeDelta operator-(const RemoteTimeTicks& rhs) const {
    144     return RemoteTimeDelta(value_ - rhs.value_);
    145   }
    146 
    147  private:
    148   friend class InterProcessTimeTicksConverter;
    149 
    150   RemoteTimeTicks(int64 value) : value_(value) {}
    151 
    152   int64 value_;
    153 };
    154 
    155 }  // namespace content
    156 
    157 #endif  // CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_
    158