From 2297f2e4bb1f0105754ff1da96cdacf24b4df260 Mon Sep 17 00:00:00 2001 From: Denis Nedelyaev Date: Fri, 23 Jun 2023 13:11:38 -0700 Subject: [PATCH] Allow passing a clock object to custom_stop_watch Summary: C++ allows to call static methods using instance method call syntax, that means we can pass a clock object to `custom_stop_watch` without breaking existing code and without extending its allocation size when using normal clocks with a static `now()` method. This will help using `stop_watch` in tests with a fake clock. Reviewed By: yfeldblum Differential Revision: D46899372 fbshipit-source-id: d9af1e4a5792635974fd0373f45f3dd9b9132a72 --- folly/stop_watch.h | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/folly/stop_watch.h b/folly/stop_watch.h index 4e886c8da6e..8ffdfb5f01a 100644 --- a/folly/stop_watch.h +++ b/folly/stop_watch.h @@ -21,6 +21,7 @@ #include #include +#include #include namespace folly { @@ -80,7 +81,11 @@ using monotonic_clock = std::chrono::steady_clock; * @author: Marcelo Juchem */ template -struct custom_stop_watch { +struct custom_stop_watch : private detail::inheritable { + private: + using base = detail::inheritable; + + public: using clock_type = Clock; using duration = Duration; using time_point = std::chrono::time_point; @@ -106,7 +111,7 @@ struct custom_stop_watch { * * @author: Marcelo Juchem */ - custom_stop_watch() : checkpoint_(clock_type::now()) {} + custom_stop_watch() : checkpoint_(now()) {} /** * Initializes the stop watch with the given time as its checkpoint. @@ -126,6 +131,21 @@ struct custom_stop_watch { explicit custom_stop_watch(typename clock_type::time_point checkpoint) : checkpoint_(std::move(checkpoint)) {} + /** + * Accepts a clock object, which can be useful in tests with a fake clock. + * Initializes the stop watch with the current time as its checkpoint. + */ + explicit custom_stop_watch(clock_type clock) + : base(std::move(clock)), checkpoint_(now()) {} + + /** + * Accepts a clock object, which can be useful in tests with a fake clock. + * Initializes the stop watch with the given time as its checkpoint. + */ + custom_stop_watch( + clock_type clock, typename clock_type::time_point checkpoint) + : base(std::move(clock)), checkpoint_(std::move(checkpoint)) {} + /** * Updates the stop watch checkpoint to the current time. * @@ -148,7 +168,7 @@ struct custom_stop_watch { * * @author: Marcelo Juchem */ - void reset() { checkpoint_ = clock_type::now(); } + void reset() { checkpoint_ = now(); } /** * Tells the elapsed time since the last update. @@ -164,8 +184,7 @@ struct custom_stop_watch { * @author: Marcelo Juchem */ duration elapsed() const { - return std::chrono::duration_cast( - clock_type::now() - checkpoint_); + return std::chrono::duration_cast(now() - checkpoint_); } /** @@ -185,7 +204,7 @@ struct custom_stop_watch { */ template bool elapsed(UDuration&& amount) const { - return clock_type::now() - checkpoint_ >= amount; + return now() - checkpoint_ >= amount; } /** @@ -211,7 +230,7 @@ struct custom_stop_watch { duration lap() { auto lastCheckpoint = checkpoint_; - checkpoint_ = clock_type::now(); + checkpoint_ = now(); return std::chrono::duration_cast(checkpoint_ - lastCheckpoint); } @@ -239,13 +258,13 @@ struct custom_stop_watch { */ template bool lap(UDuration&& amount) { - auto now = clock_type::now(); + auto current = now(); - if (now - checkpoint_ < amount) { + if (current - checkpoint_ < amount) { return false; } - checkpoint_ = now; + checkpoint_ = current; return true; } @@ -256,6 +275,11 @@ struct custom_stop_watch { private: typename clock_type::time_point checkpoint_; + + typename clock_type::time_point now() const { + // We cannot just do base::now() if clock_type is marked as final. + return static_cast(*this).now(); + } }; /**