OLD | NEW |
---|---|
(Empty) | |
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.h" | |
9 | |
10 namespace content { | |
11 | |
12 class LocalTimeDelta; | |
13 class LocalTimeTicks; | |
14 class RemoteTimeDelta; | |
15 class RemoteTimeTicks; | |
16 | |
17 // On Windows, TimeTicks are not consistent between processes. Often, the values | |
18 // on one process have a static offset relative to another. Occasionally, these | |
19 // offsets shift while running. | |
20 // | |
21 // To combat this, any TimeTicks values sent from the remote process to the | |
22 // local process must be tweaked in order to appear monotonic. | |
23 // | |
24 // In order to properly tweak ticks, we need 4 reference points: | |
25 // | |
26 // - |local_lower_bound|: A known point, recorded on the local process, that | |
27 // occurs before any remote values that will be | |
28 // converted. | |
29 // - |remote_lower_bound|: The equivalent point on the remote process. This | |
30 // should be recorded immediately after | |
31 // |local_lower_bound|. | |
32 // - |local_upper_bound|: A known point, recorded on the local process, that | |
33 // occurs after any remote values that will be | |
34 // converted. | |
35 // - |remote_upper_bound|: The equivalent point on the remote process. This | |
36 // should be recorded immediately before | |
37 // |local_upper_bound|. | |
38 // | |
39 // Once these bounds are determined, values within the remote process's range | |
40 // can be converted to the local process's range. The values are converted as | |
41 // follows: | |
42 // | |
43 // 1. If the remote's range exceeds the local's range, it is scaled to fit. | |
44 // Any values converted will have the same scale factor applied. | |
45 // | |
46 // 2. The remote's range is shifted so that it is centered within the | |
47 // local's range. Any values converted will be shifted the same amount. | |
48 class InterProcessTimeTicksConverter { | |
49 public: | |
50 InterProcessTimeTicksConverter(const LocalTimeTicks& local_lower_bound, | |
51 const LocalTimeTicks& local_upper_bound, | |
52 const RemoteTimeTicks& remote_lower_bound, | |
53 const RemoteTimeTicks& remote_upper_bound); | |
54 | |
55 // Returns the value within the local's bounds that correlates to | |
56 // |remote_ms|. | |
57 LocalTimeTicks ConvertMilliseconds(const RemoteTimeTicks& remote_ms); | |
darin (slow to review)
2011/12/12 22:25:46
nit: What do you think about renaming this ToLocal
James Simonsen
2011/12/12 23:35:34
Agreed. Done.
| |
58 | |
59 // Returns the equivalent delta after applying remote-to-local scaling to | |
60 // |remote_delta|. | |
61 LocalTimeDelta ConvertDelta(const RemoteTimeDelta& remote_delta); | |
darin (slow to review)
2011/12/12 22:25:46
nit: ToLocalTimeDelta?
James Simonsen
2011/12/12 23:35:34
Done.
| |
62 | |
63 // Returns |remote_value| after it has been clamped within the range | |
64 // [lower_bound, upper_bound]. This function is useful when we lack tight | |
65 // enough bounds to use ConvertMilliseconds(). | |
66 static LocalTimeTicks ClampTimeInRange(const RemoteTimeTicks& remote_value, | |
darin (slow to review)
2011/12/12 22:25:46
This function feels like a small, orthogonal appen
James Simonsen
2011/12/12 23:35:34
It's too simple to worry about unit testing and I
| |
67 const LocalTimeTicks& lower_bound, | |
68 const LocalTimeTicks& upper_bound); | |
69 | |
70 private: | |
71 int64 Convert(int64 value); | |
72 | |
73 int64 offset_; | |
74 int64 numerator_; | |
75 int64 denominator_; | |
76 | |
77 int64 remote_lower_bound_; | |
78 int64 remote_upper_bound_; | |
79 }; | |
80 | |
81 class LocalTimeDelta { | |
82 public: | |
83 int ToInt32() const { return value_; } | |
84 | |
85 private: | |
86 friend class InterProcessTimeTicksConverter; | |
87 friend class LocalTimeTicks; | |
88 | |
89 LocalTimeDelta(int value) : value_(value) {} | |
90 | |
91 int value_; | |
92 }; | |
93 | |
94 class LocalTimeTicks { | |
95 public: | |
96 static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) { | |
97 return LocalTimeTicks(value.ToInternalValue()); | |
98 } | |
99 | |
100 base::TimeTicks ToTimeTicks() { | |
101 return base::TimeTicks::FromInternalValue(value_); | |
102 } | |
103 | |
104 LocalTimeTicks operator+(const LocalTimeDelta& delta) { | |
105 return LocalTimeTicks(value_ + delta.value_); | |
106 } | |
107 | |
108 private: | |
109 friend class InterProcessTimeTicksConverter; | |
110 | |
111 LocalTimeTicks(int64 value) : value_(value) {} | |
112 | |
113 int64 value_; | |
114 }; | |
115 | |
116 class RemoteTimeDelta { | |
117 public: | |
118 static RemoteTimeDelta FromRawDelta(int delta) { | |
119 return RemoteTimeDelta(delta); | |
120 } | |
121 | |
122 private: | |
123 friend class InterProcessTimeTicksConverter; | |
124 friend class RemoteTimeTicks; | |
125 | |
126 RemoteTimeDelta(int value) : value_(value) {} | |
127 | |
128 int value_; | |
129 }; | |
130 | |
131 class RemoteTimeTicks { | |
132 public: | |
133 static RemoteTimeTicks FromTimeTicks(const base::TimeTicks& ticks) { | |
134 return RemoteTimeTicks(ticks.ToInternalValue()); | |
135 } | |
136 | |
137 RemoteTimeDelta operator-(const RemoteTimeTicks& rhs) const { | |
138 return RemoteTimeDelta(value_ - rhs.value_); | |
139 } | |
140 | |
141 private: | |
142 friend class InterProcessTimeTicksConverter; | |
143 | |
144 RemoteTimeTicks(int64 value) : value_(value) {} | |
145 | |
146 int64 value_; | |
147 }; | |
148 | |
149 } // namespace content | |
150 | |
151 #endif // CONTENT_COMMON_INTER_PROCESS_TIME_TICKS_CONVERTER_H_ | |
OLD | NEW |