1 // Copyright 2018 The Chromium Authors
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 PARTITION_ALLOC_PARTITION_ALLOC_BASE_TIME_TIME_OVERRIDE_H_
6 #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TIME_TIME_OVERRIDE_H_
7 
8 #include <atomic>
9 
10 #include "build/build_config.h"
11 #include "partition_alloc/partition_alloc_base/component_export.h"
12 #include "partition_alloc/partition_alloc_base/time/time.h"
13 
14 namespace partition_alloc::internal::base {
15 
16 using TimeNowFunction = decltype(&Time::Now);
17 using TimeTicksNowFunction = decltype(&TimeTicks::Now);
18 using ThreadTicksNowFunction = decltype(&ThreadTicks::Now);
19 
20 // Time overrides should be used with extreme caution. Discuss with //base/time
21 // OWNERS before adding a new one.
22 namespace subtle {
23 
24 // Override the return value of Time::Now and Time::NowFromSystemTime /
25 // TimeTicks::Now / ThreadTicks::Now to emulate time, e.g. for tests or to
26 // modify progression of time. It is recommended that the override be set while
27 // single-threaded and before the first call to Now() to avoid threading issues
28 // and inconsistencies in returned values. Overriding time while other threads
29 // are running is very subtle and should be reserved for developer only use
30 // cases (e.g. virtual time in devtools) where any flakiness caused by a racy
31 // time update isn't surprising. Instantiating a ScopedTimeClockOverrides while
32 // other threads are running might break their expectation that TimeTicks and
33 // ThreadTicks increase monotonically. Nested overrides are not allowed.
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)34 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) ScopedTimeClockOverrides {
35  public:
36   // Pass |nullptr| for any override if it shouldn't be overriden.
37   ScopedTimeClockOverrides(TimeNowFunction time_override,
38                            TimeTicksNowFunction time_ticks_override,
39                            ThreadTicksNowFunction thread_ticks_override);
40 
41   ScopedTimeClockOverrides(const ScopedTimeClockOverrides&) = delete;
42   ScopedTimeClockOverrides& operator=(const ScopedTimeClockOverrides&) = delete;
43 
44   // Restores the platform default Now() functions.
45   ~ScopedTimeClockOverrides();
46 
47   static bool overrides_active() { return overrides_active_; }
48 
49  private:
50   static bool overrides_active_;
51 };
52 
53 // These methods return the platform default Time::Now / TimeTicks::Now /
54 // ThreadTicks::Now values even while an override is in place. These methods
55 // should only be used in places where emulated time should be disregarded. For
56 // example, they can be used to implement test timeouts for tests that may
57 // override time.
58 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) Time TimeNowIgnoringOverride();
59 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
60 Time TimeNowFromSystemTimeIgnoringOverride();
61 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
62 TimeTicks TimeTicksNowIgnoringOverride();
63 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
64 ThreadTicks ThreadTicksNowIgnoringOverride();
65 
66 }  // namespace subtle
67 
68 namespace internal {
69 
70 // These function pointers are used by platform-independent implementations of
71 // the Now() methods and ScopedTimeClockOverrides. They are set to point to the
72 // respective NowIgnoringOverride functions by default, but can also be set by
73 // platform-specific code to select a default implementation at runtime, thereby
74 // avoiding the indirection via the NowIgnoringOverride functions. Note that the
75 // pointers can be overridden and later reset to the NowIgnoringOverride
76 // functions by ScopedTimeClockOverrides.
77 extern std::atomic<TimeNowFunction> g_time_now_function;
78 extern std::atomic<TimeNowFunction> g_time_now_from_system_time_function;
79 extern std::atomic<TimeTicksNowFunction> g_time_ticks_now_function;
80 extern std::atomic<ThreadTicksNowFunction> g_thread_ticks_now_function;
81 
82 }  // namespace internal
83 
84 }  // namespace partition_alloc::internal::base
85 
86 #endif  // PARTITION_ALLOC_PARTITION_ALLOC_BASE_TIME_TIME_OVERRIDE_H_
87