| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ |
| #define CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ |
| |
| #include <stdint.h> |
| |
| #include "base/time/time.h" |
| #include "content/common/content_export.h" |
| |
| namespace content { |
| |
| // SiteSpecificTimeDelta<T> is base::TimeDelta with a type tag. It it |
| // essentially base::TimeDelta, but SiteSpecificTimeDelta<T> is different from |
| // SiteSpecificTimeDelta<U> if T is different from U. |
| template <typename T> |
| class SiteSpecificTimeDelta final { |
| public: |
| SiteSpecificTimeDelta() = default; |
| static SiteSpecificTimeDelta<T> FromTimeDelta(base::TimeDelta delta) { |
| return SiteSpecificTimeDelta<T>(delta); |
| } |
| static SiteSpecificTimeDelta<T> FromMicroseconds(int64_t usec) { |
| return SiteSpecificTimeDelta<T>(base::TimeDelta::FromMicroseconds(usec)); |
| } |
| |
| base::TimeDelta ToTimeDelta() const { return delta_; } |
| bool operator==(const SiteSpecificTimeDelta<T> rhs) const { |
| return delta_ == rhs.delta_; |
| } |
| bool operator<(const SiteSpecificTimeDelta<T> rhs) const { |
| return delta_ < rhs.delta_; |
| } |
| bool operator<=(const SiteSpecificTimeDelta<T> rhs) const { |
| return delta_ <= rhs.delta_; |
| } |
| |
| private: |
| explicit SiteSpecificTimeDelta(base::TimeDelta delta) : delta_(delta) {} |
| |
| base::TimeDelta delta_; |
| }; |
| |
| // For logging use only. |
| template <typename T> |
| std::ostream& operator<<(std::ostream& os, SiteSpecificTimeDelta<T> delta) { |
| return os << delta.ToTimeDelta(); |
| } |
| |
| // SiteSpecificTimeTicks<T> is base::TimeTicks with a type tag. It is |
| // essentially base::TimeTicks, but SiteSpecificTimeTicks<T> is different from |
| // SiteSpecificTimeTicks<U> if T is different from U. |
| template <typename T> |
| class SiteSpecificTimeTicks final { |
| public: |
| SiteSpecificTimeTicks() = default; |
| static SiteSpecificTimeTicks<T> FromTimeTicks(base::TimeTicks time_ticks) { |
| return SiteSpecificTimeTicks<T>(time_ticks); |
| } |
| |
| base::TimeTicks ToTimeTicks() const { return time_ticks_; } |
| bool is_null() const { return time_ticks_.is_null(); } |
| |
| SiteSpecificTimeTicks<T> operator+(SiteSpecificTimeDelta<T> delta) const { |
| return SiteSpecificTimeTicks<T>(time_ticks_ + delta.ToTimeDelta()); |
| } |
| SiteSpecificTimeDelta<T> operator-(SiteSpecificTimeTicks<T> rhs) const { |
| return SiteSpecificTimeDelta<T>::FromTimeDelta(time_ticks_ - |
| rhs.time_ticks_); |
| } |
| bool operator<(const SiteSpecificTimeTicks<T> rhs) const { |
| return time_ticks_ < rhs.time_ticks_; |
| } |
| bool operator==(const SiteSpecificTimeTicks<T> rhs) const { |
| return time_ticks_ == rhs.time_ticks_; |
| } |
| bool operator<=(const SiteSpecificTimeTicks<T> rhs) const { |
| return time_ticks_ <= rhs.time_ticks_; |
| } |
| |
| private: |
| explicit SiteSpecificTimeTicks(base::TimeTicks time_ticks) |
| : time_ticks_(time_ticks) {} |
| |
| base::TimeTicks time_ticks_; |
| }; |
| |
| // For logging use only. |
| template <typename T> |
| std::ostream& operator<<(std::ostream& os, |
| SiteSpecificTimeTicks<T> time_ticks) { |
| return os << time_ticks.ToTimeTicks(); |
| } |
| |
| class SiteSpecificTimeLocalTag; |
| using LocalTimeTicks = SiteSpecificTimeTicks<SiteSpecificTimeLocalTag>; |
| using LocalTimeDelta = SiteSpecificTimeDelta<SiteSpecificTimeLocalTag>; |
| |
| class SiteSpecificTimeRemoteTag; |
| using RemoteTimeTicks = SiteSpecificTimeTicks<SiteSpecificTimeRemoteTag>; |
| using RemoteTimeDelta = SiteSpecificTimeDelta<SiteSpecificTimeRemoteTag>; |
| |
| // On Windows, TimeTicks are not always consistent between processes as |
| // indicated by |TimeTicks::IsConsistentAcrossProcesses()|. Often, the values on |
| // one process have a static offset relative to another. Occasionally, these |
| // offsets shift while running. |
| // |
| // To combat this, any TimeTicks values sent from the remote process to the |
| // local process must be tweaked in order to appear monotonic. |
| // |
| // In order to properly tweak ticks, we need 4 reference points: |
| // |
| // - |local_lower_bound|: A known point, recorded on the local process, that |
| // occurs before any remote values that will be |
| // converted. |
| // - |remote_lower_bound|: The equivalent point on the remote process. This |
| // should be recorded immediately after |
| // |local_lower_bound|. |
| // - |local_upper_bound|: A known point, recorded on the local process, that |
| // occurs after any remote values that will be |
| // converted. |
| // - |remote_upper_bound|: The equivalent point on the remote process. This |
| // should be recorded immediately before |
| // |local_upper_bound|. |
| // |
| // Once these bounds are determined, values within the remote process's range |
| // can be converted to the local process's range. The values are converted as |
| // follows: |
| // |
| // 1. If the remote's range exceeds the local's range, it is scaled to fit. |
| // Any values converted will have the same scale factor applied. |
| // |
| // 2. The remote's range is shifted so that it is centered within the |
| // local's range. Any values converted will be shifted the same amount. |
| class CONTENT_EXPORT InterProcessTimeTicksConverter { |
| public: |
| InterProcessTimeTicksConverter(LocalTimeTicks local_lower_bound, |
| LocalTimeTicks local_upper_bound, |
| RemoteTimeTicks remote_lower_bound, |
| RemoteTimeTicks remote_upper_bound); |
| |
| // Returns the value within the local's bounds that correlates to |
| // |remote_ms|. |
| LocalTimeTicks ToLocalTimeTicks(RemoteTimeTicks remote_ms) const; |
| |
| // Returns the equivalent delta after applying remote-to-local scaling to |
| // |remote_delta|. |
| LocalTimeDelta ToLocalTimeDelta(RemoteTimeDelta remote_delta) const; |
| |
| // Returns the (remote time) - (local time) difference estimated by the |
| // converter. This is the constant that is subtracted from remote TimeTicks to |
| // get local TimeTicks when no scaling is applied. |
| base::TimeDelta GetSkewForMetrics() const; |
| |
| private: |
| // The local time which |remote_lower_bound_| is mapped to. |
| LocalTimeTicks local_base_time_; |
| LocalTimeDelta local_range_; |
| |
| double range_conversion_rate_; |
| |
| RemoteTimeTicks remote_lower_bound_; |
| RemoteTimeTicks remote_upper_bound_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ |