xref: /aosp_15_r20/external/federated-compute/fcp/base/wall_clock_stopwatch.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FCP_BASE_WALL_CLOCK_STOPWATCH_H_
18 #define FCP_BASE_WALL_CLOCK_STOPWATCH_H_
19 
20 #include <memory>
21 
22 #include "absl/synchronization/mutex.h"
23 #include "absl/time/time.h"
24 
25 namespace fcp {
26 
27 namespace internal {
28 class RealWallClockStopwatch;
29 class NoopWallClockStopwatch;
30 }  // namespace internal
31 
32 // A utility for measuring wall clock time across multiple threads.
33 //
34 // This class is non-reentrant: `Start()` should only be called once per thread
35 // (but once `Stop()` has been called, `Start()` may be called again).
36 class WallClockStopwatch {
37  public:
38   static std::unique_ptr<WallClockStopwatch> Create();
39   static std::unique_ptr<WallClockStopwatch> CreateNoop();
40   // Disable copy and move semantics.
41   WallClockStopwatch(const WallClockStopwatch&) = delete;
42   WallClockStopwatch& operator=(const WallClockStopwatch&) = delete;
43 
44   // A handle that stops the stopwatch once destroyed.
45   class Handle {
46    public:
47     // Disable copy and move semantics.
48     Handle(const Handle&) = delete;
49     Handle& operator=(const Handle&) = delete;
50     ~Handle();
51 
52    private:
53     // If `stopwatch` is a nullptr then the Handle that does nothing (for use in
54     // testing or flagging-off the measurement with a real stopwatch).
55     explicit Handle(WallClockStopwatch* stopwatch);
56 
57     WallClockStopwatch* const stopwatch_;
58     friend internal::RealWallClockStopwatch;
59     friend internal::NoopWallClockStopwatch;
60   };
61 
62   // Start the stopwatch from this thread. If it wasn't running yet from any
63   // other thread, then time will start being accumulated from this point on.
64   // If it was already running from another thread then this call will have no
65   // immediate effect.
66   //
67   // Once the returned Handle is destroyed, the stopwatch is stopped from this
68   // thread. If it isn't running from any other thread, then time will stop
69   // being accumulated from that point on. If it still running from another
70   // thread then Handle destruction will have no immediate effect.
71   virtual Handle Start() = 0;
72 
73   // Get the total duration of wall clock time that the stopwatch has run for,
74   // up until this moment (i.e. including any still-ongoing measurement).
75   virtual absl::Duration GetTotalDuration() const = 0;
76 
77   virtual ~WallClockStopwatch() = default;
78 
79  private:
80   WallClockStopwatch() = default;
StartInternal()81   virtual void StartInternal() {}
StopInternal()82   virtual void StopInternal() {}
83   friend internal::RealWallClockStopwatch;
84   friend internal::NoopWallClockStopwatch;
85 };
86 
87 }  // namespace fcp
88 
89 #endif  // FCP_BASE_WALL_CLOCK_STOPWATCH_H_
90