1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef API_NETEQ_TICK_TIMER_H_
12 #define API_NETEQ_TICK_TIMER_H_
13 
14 #include <stdint.h>
15 
16 #include <memory>
17 
18 #include "rtc_base/checks.h"
19 
20 namespace webrtc {
21 
22 // Implements a time counter. The counter is advanced with the Increment()
23 // methods, and is queried with the ticks() accessor. It is assumed that one
24 // "tick" of the counter corresponds to 10 ms.
25 // A TickTimer object can provide two types of associated time-measuring
26 // objects: Stopwatch and Countdown.
27 class TickTimer {
28  public:
29   // Stopwatch measures time elapsed since it was started, by querying the
30   // associated TickTimer for the current time. The intended use is to request a
31   // new Stopwatch object from a TickTimer object with the GetNewStopwatch()
32   // method. Note: since the Stopwatch object contains a reference to the
33   // TickTimer it is associated with, it cannot outlive the TickTimer.
34   class Stopwatch {
35    public:
36     explicit Stopwatch(const TickTimer& ticktimer);
37 
ElapsedTicks()38     uint64_t ElapsedTicks() const { return ticktimer_.ticks() - starttick_; }
39 
ElapsedMs()40     uint64_t ElapsedMs() const {
41       const uint64_t elapsed_ticks = ticktimer_.ticks() - starttick_;
42       const int ms_per_tick = ticktimer_.ms_per_tick();
43       return elapsed_ticks < UINT64_MAX / ms_per_tick
44                  ? elapsed_ticks * ms_per_tick
45                  : UINT64_MAX;
46     }
47 
48    private:
49     const TickTimer& ticktimer_;
50     const uint64_t starttick_;
51   };
52 
53   // Countdown counts down from a given start value with each tick of the
54   // associated TickTimer, until zero is reached. The Finished() method will
55   // return true if zero has been reached, false otherwise. The intended use is
56   // to request a new Countdown object from a TickTimer object with the
57   // GetNewCountdown() method. Note: since the Countdown object contains a
58   // reference to the TickTimer it is associated with, it cannot outlive the
59   // TickTimer.
60   class Countdown {
61    public:
62     Countdown(const TickTimer& ticktimer, uint64_t ticks_to_count);
63 
64     ~Countdown();
65 
Finished()66     bool Finished() const {
67       return stopwatch_->ElapsedTicks() >= ticks_to_count_;
68     }
69 
70    private:
71     const std::unique_ptr<Stopwatch> stopwatch_;
72     const uint64_t ticks_to_count_;
73   };
74 
TickTimer()75   TickTimer() : TickTimer(10) {}
TickTimer(int ms_per_tick)76   explicit TickTimer(int ms_per_tick) : ms_per_tick_(ms_per_tick) {
77     RTC_DCHECK_GT(ms_per_tick_, 0);
78   }
79 
80   TickTimer(const TickTimer&) = delete;
81   TickTimer& operator=(const TickTimer&) = delete;
82 
Increment()83   void Increment() { ++ticks_; }
84 
85   // Mainly intended for testing.
Increment(uint64_t x)86   void Increment(uint64_t x) { ticks_ += x; }
87 
ticks()88   uint64_t ticks() const { return ticks_; }
89 
ms_per_tick()90   int ms_per_tick() const { return ms_per_tick_; }
91 
92   // Returns a new Stopwatch object, based on the current TickTimer. Note that
93   // the new Stopwatch object contains a reference to the current TickTimer,
94   // and must therefore not outlive the TickTimer.
GetNewStopwatch()95   std::unique_ptr<Stopwatch> GetNewStopwatch() const {
96     return std::unique_ptr<Stopwatch>(new Stopwatch(*this));
97   }
98 
99   // Returns a new Countdown object, based on the current TickTimer. Note that
100   // the new Countdown object contains a reference to the current TickTimer,
101   // and must therefore not outlive the TickTimer.
GetNewCountdown(uint64_t ticks_to_count)102   std::unique_ptr<Countdown> GetNewCountdown(uint64_t ticks_to_count) const {
103     return std::unique_ptr<Countdown>(new Countdown(*this, ticks_to_count));
104   }
105 
106  private:
107   uint64_t ticks_ = 0;
108   const int ms_per_tick_;
109 };
110 
111 }  // namespace webrtc
112 #endif  // API_NETEQ_TICK_TIMER_H_
113