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)34class 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